Created
July 1, 2025 21:03
-
-
Save tomfleet/cae3bf4e75266edc0cc69bebb29606ad to your computer and use it in GitHub Desktop.
Google AI-less Search
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Google AI-less Search | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.1 | |
| // @description Appends "-ai" to your Google search queries to help filter out AI-generated content. | |
| // @author You | |
| // @match *://*.google.com/* | |
| // @grant none | |
| // @run-at document-start | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| const appendix = " -ai"; | |
| /** | |
| * This function checks the URL of the current search results page. | |
| * If the query parameter 'q' doesn't end with our appendix, it adds it | |
| * and reloads the page. This acts as a fallback for any searches | |
| * that aren't caught by the form submission listener. | |
| */ | |
| const checkAndUpdateURL = () => { | |
| // We only want to run this on search results pages | |
| if (window.location.pathname !== '/search') { | |
| return; | |
| } | |
| const url = new URL(window.location.href); | |
| const query = url.searchParams.get('q'); | |
| // Check if a query exists and if it does NOT already end with the appendix | |
| if (query && !query.trim().toLowerCase().endsWith(appendix.toLowerCase())) { | |
| const newQuery = query + appendix; | |
| url.searchParams.set('q', newQuery); | |
| // Redirect to the new URL with the modified query | |
| window.location.href = url.href; | |
| } | |
| }; | |
| /** | |
| * This function intercepts the submission of a search form. | |
| * It finds the search input field within that form and appends our | |
| * text before the form is sent to Google's servers. | |
| * @param {Event} e The form submission event. | |
| */ | |
| const handleFormSubmit = (e) => { | |
| try { | |
| // The form element that triggered the submit event | |
| const form = e.target; | |
| // Find the search input within that specific form | |
| const searchInput = form.querySelector('input[name="q"]'); | |
| if (searchInput && searchInput.value) { | |
| // Check if the value already ends with the appendix to avoid duplicates | |
| if (!searchInput.value.trim().toLowerCase().endsWith(appendix.toLowerCase())) { | |
| searchInput.value += appendix; | |
| } | |
| } | |
| } catch (error) { | |
| console.error("Greasemonkey Script Error (handleFormSubmit):", error); | |
| } | |
| // The script does not prevent the default submission. | |
| // It modifies the value in-place, and the browser submits the modified form. | |
| }; | |
| /** | |
| * Google's page can load elements dynamically. A MutationObserver is the | |
| * most reliable way to find the search form(s) as soon as they are | |
| * added to the page, whenever that may be. | |
| */ | |
| const observeDOM = () => { | |
| const observer = new MutationObserver((mutations, obs) => { | |
| // Find all search forms on the page. Usually there's one, but it's good to be robust. | |
| const searchForms = document.querySelectorAll('form[action="/search"]'); | |
| if (searchForms.length > 0) { | |
| searchForms.forEach(form => { | |
| // We add a custom attribute to mark that we've already attached a listener, | |
| // preventing us from attaching multiple listeners to the same form. | |
| if (!form.hasAttribute('data-modified-by-script')) { | |
| form.setAttribute('data-modified-by-script', 'true'); | |
| form.addEventListener('submit', handleFormSubmit); | |
| } | |
| }); | |
| } | |
| }); | |
| // Start observing the entire document for changes to the element tree. | |
| observer.observe(document.documentElement, { | |
| childList: true, | |
| subtree: true | |
| }); | |
| }; | |
| // --- Script Execution --- | |
| // Run the URL check immediately. This is our fallback. | |
| checkAndUpdateURL(); | |
| // Start observing the DOM to catch forms as they appear. This is our primary method. | |
| observeDOM(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment