├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── assets
├── 1.0.0.zip
├── 1.0.1.zip
├── marquee-promo.png
├── privacy.md
├── small-promo.png
├── ss1.png
└── ss2.png
├── icons
├── icon.png
├── icon128.png
├── icon16.png
├── icon32.png
└── icon48.png
├── manifest.json
├── popup
├── hello.html
├── popup.css
└── popup.js
└── script
├── content-script.css
└── content-script.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "editor.formatOnSave": true
4 | }
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Guilherme Oenning
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Refined Search Results
4 |
5 | I never click on any `quora.com` links when doing a Google search, and I'm sure many of you have a few websites that you also avoid as much as possible when they show up on your search results.
6 |
7 | Maybe you don't like the quality of their content, or they are known for paywalled content, or maybe they just have a terrible user experience. This extension allows you to remove these sites from your search results, to give you more space for the results that actually matter to you.
8 |
9 | ## How to use it
10 |
11 | 1. Install the [Chrome Extension](https://chromewebstore.google.com/detail/refined-search-results/kmhlpeknclnafdbjdbbbhelolcfnfabi)
12 | 2. Configure the list of domains you don't want to see on Google
13 | 3. Enjoy a cleaner search experience ✨
14 |
15 | ## 🔐 Privacy
16 |
17 | The extension does not collect or store any data. The source code is 100% open soure and available on this repository.
18 |
19 | ## 📄 License
20 |
21 | MIT License
22 |
23 | ## 💖 Sponsor
24 |
25 | This project is open source and free thanks to [SEO Gets](https://seogets.com)
26 |
27 | 
28 |
--------------------------------------------------------------------------------
/assets/1.0.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/assets/1.0.0.zip
--------------------------------------------------------------------------------
/assets/1.0.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/assets/1.0.1.zip
--------------------------------------------------------------------------------
/assets/marquee-promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/assets/marquee-promo.png
--------------------------------------------------------------------------------
/assets/privacy.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy
2 |
3 | The Refined Search Results browser extension does not collect or store any information about the user.
4 |
5 | The code is 100% open source and available on https://github.com/goenning/refined-search-results
6 |
--------------------------------------------------------------------------------
/assets/small-promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/assets/small-promo.png
--------------------------------------------------------------------------------
/assets/ss1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/assets/ss1.png
--------------------------------------------------------------------------------
/assets/ss2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/assets/ss2.png
--------------------------------------------------------------------------------
/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/icons/icon.png
--------------------------------------------------------------------------------
/icons/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/icons/icon128.png
--------------------------------------------------------------------------------
/icons/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/icons/icon16.png
--------------------------------------------------------------------------------
/icons/icon32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/icons/icon32.png
--------------------------------------------------------------------------------
/icons/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/goenning/refined-search-results/abbc75a8f15f1e97dca888d8f878c1730c4506fb/icons/icon48.png
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Refined Search Results",
3 | "description": "Remove unwanted search results from Google for a better search experience.",
4 | "version": "1.0.2",
5 | "manifest_version": 3,
6 | "action": {
7 | "default_popup": "popup/hello.html"
8 | },
9 | "permissions": ["storage"],
10 | "icons": {
11 | "16": "icons/icon16.png",
12 | "32": "icons/icon32.png",
13 | "48": "icons/icon48.png",
14 | "128": "icons/icon128.png"
15 | },
16 | "content_scripts": [
17 | {
18 | "matches": [
19 | "https://www.google.com/*",
20 | "https://www.google.co.in/*",
21 | "https://www.google.com.br/*",
22 | "https://www.google.co.jp/*",
23 | "https://www.google.de/*",
24 | "https://www.google.co.uk/*",
25 | "https://www.google.fr/*",
26 | "https://www.google.ru/*",
27 | "https://www.google.com.mx/*",
28 | "https://www.google.com.tr/*",
29 | "https://www.google.it/*",
30 | "https://www.google.com.au/*",
31 | "https://www.google.com.tw/*",
32 | "https://www.google.ca/*",
33 | "https://www.google.com.hk/*",
34 | "https://www.google.com.ar/*",
35 | "https://www.google.es/*",
36 | "https://www.google.co.id/*",
37 | "https://www.google.pl/*",
38 | "https://www.google.com.eg/*",
39 | "https://www.google.com.sa/*",
40 | "https://www.google.co.th/*",
41 | "https://www.google.com.ua/*",
42 | "https://www.google.com.vn/*",
43 | "https://www.google.com.ph/*",
44 | "https://www.google.com.pk/*",
45 | "https://www.google.co.za/*",
46 | "https://www.google.com.ng/*",
47 | "https://www.google.com.bd/*",
48 | "https://www.google.nl/*",
49 | "https://www.google.co.ve/*",
50 | "https://www.google.com.co/*",
51 | "https://www.google.com.sg/*",
52 | "https://www.google.com.tr/*",
53 | "https://www.google.com.my/*",
54 | "https://www.google.cl/*",
55 | "https://www.google.be/*",
56 | "https://www.google.ch/*",
57 | "https://www.google.at/*",
58 | "https://www.google.com.pe/*",
59 | "https://www.google.se/*",
60 | "https://www.google.dk/*",
61 | "https://www.google.pt/*",
62 | "https://www.google.cz/*",
63 | "https://www.google.ae/*",
64 | "https://www.google.fi/*",
65 | "https://www.google.gr/*",
66 | "https://www.google.no/*",
67 | "https://www.google.co.hu/*",
68 | "https://www.google.ro/*",
69 | "https://www.google.ie/*",
70 | "https://www.google.co.il/*",
71 | "https://www.google.co.kr/*",
72 | "https://www.google.co.nz/*",
73 | "https://www.google.com.ec/*",
74 | "https://www.google.co.cr/*",
75 | "https://www.google.com.gt/*",
76 | "https://www.google.com.pa/*",
77 | "https://www.google.com.pe/*",
78 | "https://www.google.com.do/*",
79 | "https://www.google.com.bo/*",
80 | "https://www.google.com.ni/*",
81 | "https://www.google.com.py/*",
82 | "https://www.google.com.sv/*",
83 | "https://www.google.com.uy/*",
84 | "https://www.google.com.hn/*",
85 | "https://www.google.com.pr/*",
86 | "https://www.google.tt/*",
87 | "https://www.google.com.fj/*",
88 | "https://www.google.com.na/*",
89 | "https://www.google.com.sb/*",
90 | "https://www.google.com.pg/*",
91 | "https://www.google.com.et/*",
92 | "https://www.google.com.jm/*",
93 | "https://www.google.gl/*",
94 | "https://www.google.gy/*",
95 | "https://www.google.gp/*",
96 | "https://www.google.kg/*",
97 | "https://www.google.tn/*",
98 | "https://www.google.mu/*",
99 | "https://www.google.ci/*",
100 | "https://www.google.cm/*",
101 | "https://www.google.cg/*",
102 | "https://www.google.ml/*",
103 | "https://www.google.gm/*",
104 | "https://www.google.ga/*",
105 | "https://www.google.sn/*",
106 | "https://www.google.ne/*",
107 | "https://www.google.bj/*",
108 | "https://www.google.td/*",
109 | "https://www.google.cf/*",
110 | "https://www.google.so/*",
111 | "https://www.google.dj/*",
112 | "https://www.google.com.sl/*",
113 | "https://www.google.sc/*",
114 | "https://www.google.re/*",
115 | "https://www.google.mu/*",
116 | "https://www.google.as/*",
117 | "https://www.google.gg/*",
118 | "https://www.google.im/*",
119 | "https://www.google.je/*",
120 | "https://www.google.ac/*",
121 | "https://www.google.sh/*",
122 | "https://www.google.ms/*",
123 | "https://www.google.ki/*",
124 | "https://www.google.fm/*",
125 | "https://www.google.nr/*",
126 | "https://www.google.pn/*",
127 | "https://www.google.tk/*",
128 | "https://www.google.to/*"
129 | ],
130 | "js": ["script/content-script.js"],
131 | "css": ["script/content-script.css"]
132 | }
133 | ]
134 | }
135 |
--------------------------------------------------------------------------------
/popup/hello.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Refined Search Results
8 | Excluded Domains
9 |
10 | Links from domains you enter here will be excluded from the search
11 | results
12 |
13 |
14 |
20 |
21 | - Enter a single domain per line
22 | - "linkedin.com" will exclude subdomains like "de.linkedin.com"
23 |
24 |
25 | Suggestions
26 |
27 | Forum
28 |
29 |
30 |
31 |
32 |
33 |
34 | Social Media
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/popup/popup.css:
--------------------------------------------------------------------------------
1 | :root {
2 | color-scheme: light dark;
3 | }
4 |
5 | html {
6 | font-family: ui-sans-serif, system-ui, sans-serif;
7 | padding: 0px;
8 | }
9 |
10 | body {
11 | width: 300px;
12 | margin: 0px;
13 | }
14 |
15 | main {
16 | padding: 4px 8px;
17 | }
18 |
19 | h1 {
20 | margin-top: 0px;
21 | }
22 |
23 | h4 {
24 | margin: 0;
25 | margin-top: 10px;
26 | margin-bottom: 4px;
27 | }
28 |
29 | textarea {
30 | width: 100%;
31 | max-width: 100%;
32 | min-width: 100%;
33 | border-radius: 5px;
34 | font-size: 14px;
35 | padding: 5px;
36 | margin: 4px 0px;
37 | font-family: inherit;
38 | }
39 |
40 | p {
41 | margin: 0;
42 | }
43 |
44 | ul {
45 | margin: 0;
46 | padding-left: 16px;
47 | }
48 |
49 | h2 {
50 | margin-top: 0;
51 | margin-bottom: 4px;
52 | }
53 |
54 | h3 {
55 | margin-top: 40px;
56 | margin-bottom: 4px;
57 | }
58 |
59 | .suggestions {
60 | display: flex;
61 | flex-wrap: wrap;
62 | gap: 4px;
63 | }
64 |
65 | .suggestions > button {
66 | border: 1px solid #ccc;
67 | display: inline;
68 | border-radius: 4px;
69 | padding: 2px 4px;
70 | cursor: pointer;
71 | }
72 |
73 | .suggestions > button:hover {
74 | background-color: #ccc;
75 | }
76 |
77 | footer {
78 | border-top: 1px solid #d4d4d8;
79 | color: #78716c;
80 | text-align: center;
81 | margin-top: 24px;
82 | margin-bottom: 8px;
83 | }
84 |
85 | footer a {
86 | color: #3b82f6;
87 | text-align: center;
88 | }
89 |
90 | footer p {
91 | margin-top: 6px;
92 | }
93 |
--------------------------------------------------------------------------------
/popup/popup.js:
--------------------------------------------------------------------------------
1 | (async () => {
2 | const stored = await chrome.storage.local.get("excludeList");
3 |
4 | const input = document.getElementById("exclude-input");
5 | console.log("DOMContentLoaded", stored, input);
6 |
7 | if (stored.excludeList && stored.excludeList.length > 0) {
8 | stored.excludeList.forEach((excluded) => {
9 | input.value += `${excluded}\n`;
10 | });
11 | }
12 |
13 | input.addEventListener("change", function () {
14 | const values = input.value
15 | .split("\n")
16 | .map((value) => value.trim())
17 | .filter((value) => value.length > 0);
18 |
19 | chrome.storage.local.set({ excludeList: values });
20 | });
21 |
22 | const suggestions = document.querySelectorAll(".suggestions button");
23 | for (const suggestion of suggestions) {
24 | suggestion.addEventListener("click", function () {
25 | const domain = suggestion.getAttribute("data-domain");
26 | if (!input.value.includes(domain)) {
27 | if (input.value === "" || input.value.endsWith("\n")) {
28 | input.value += `${domain}\n`;
29 | } else {
30 | input.value += `\n${domain}\n`;
31 | }
32 | input.dispatchEvent(new Event("change"));
33 | }
34 | });
35 | }
36 | })();
37 |
--------------------------------------------------------------------------------
/script/content-script.css:
--------------------------------------------------------------------------------
1 | .esr-replaced {
2 | color: #71717a !important;
3 | font-size: 11px;
4 | }
5 |
6 | .esr-replaced a {
7 | color: #71717a !important;
8 | }
9 |
10 | .esr-replaced span {
11 | margin-left: 2px;
12 | }
13 |
14 | .esr-replaced a:hover {
15 | color: #8ab4f8 !important;
16 | }
17 |
--------------------------------------------------------------------------------
/script/content-script.js:
--------------------------------------------------------------------------------
1 | function matchesUrl(url, domain) {
2 | try {
3 | const urlObj = new URL(url);
4 | return urlObj.hostname.endsWith(domain);
5 | } catch (e) {
6 | return false;
7 | }
8 | }
9 |
10 | function findParentDivContainer(node) {
11 | let parentNode = node.parentNode;
12 | while (parentNode !== null) {
13 | const isDiv = parentNode.nodeName.toLowerCase() === "div";
14 | const isContainer = parentNode.hasAttribute("data-hveid");
15 | if (isDiv && isContainer) {
16 | return parentNode;
17 | }
18 | parentNode = parentNode.parentNode;
19 | }
20 | return null;
21 | }
22 |
23 | function replaceLink(node, url) {
24 | node.style.display = "none";
25 |
26 | if (node.parentNode.querySelector(".esr-replaced")) {
27 | return;
28 | }
29 |
30 | const p = document.createElement("p");
31 | p.className = "esr-replaced";
32 |
33 | const a = document.createElement("a");
34 | a.href = url;
35 | a.innerText = url;
36 |
37 | const text = document.createElement("span");
38 | text.innerText = `removed by the Refined Search Results`;
39 |
40 | p.appendChild(a);
41 | p.appendChild(text);
42 |
43 | node.parentNode.appendChild(p);
44 | }
45 |
46 | (async () => {
47 | const main = document.getElementById("main");
48 | const stored = await chrome.storage.local.get("excludeList");
49 |
50 | const excludeList = stored.excludeList || [];
51 |
52 | function searchAndReplace() {
53 | const links = main.querySelectorAll("a[ping]");
54 | for (const link of links) {
55 | const url = link.getAttribute("href");
56 | for (const domain of excludeList) {
57 | if (matchesUrl(url, domain)) {
58 | const parentDiv = findParentDivContainer(link);
59 | if (parentDiv) {
60 | replaceLink(parentDiv, url);
61 | }
62 | }
63 | }
64 | }
65 | }
66 |
67 | const opts = {
68 | attributes: false,
69 | childList: true,
70 | subtree: true,
71 | };
72 |
73 | const callback = () => {
74 | observer.disconnect();
75 | searchAndReplace();
76 | observer.observe(main, opts);
77 | };
78 |
79 | const observer = new MutationObserver(callback);
80 | observer.observe(main, opts);
81 | searchAndReplace();
82 | })();
83 |
--------------------------------------------------------------------------------