Another approach to allow google ads with Pihole

Everywhere we can see people complaining that they can no longer click on google ads when using Pi-hole. The answers are always the same: works as intended, look further down.
When I looked at the blocked URLs, I saw the URL that I really wanted after "adurl=". E.g.

> https://www.googleadservices.com/pagead/aclk?...&adurl=wantedUrl

. The approach is to strip everything before adurl= and redirect to the wanted URL. Sometimes it is more complicated than this, because adurl refers to another ad server, like ad.doubleclick.net, then the wanted url is in another parameter.

I test this approach with a small Chrome extension. It has just two files. Put them in an empty directory, and call chrome://extensions/ , then "load unpacked from directory" or so. The two files are
manifest.json:

{
	"name": "pihole_googleads",
	"description": "make google ads usable for Pihole",
	"version": "1.0",
	"manifest_version": 3,
	"declarative_net_request": {
		"rule_resources": [{
			"id": "ruleset",
			"enabled": true,
			"path": "rules.json"
		}]
	},
	"permissions": [
		"declarativeNetRequest"
	],
	"host_permissions": [
		"https://www.googleadservices.com/*"
	]
}

and rules.json:

[
	{
		"id": 1,
		"priority": 2,
		"action": {
			"type": "redirect",
			"redirect": {
				"regexSubstitution": "\\1"
			}
		},
		"condition": {
			"regexFilter": "^https://www.googleadservices.com/.*adurl=https://ad.doubleclick.net/.*_clickid_%3F(.*)%3F.*",
			"resourceTypes": [ "main_frame" ]
		}
	},
	{
		"id": 2,
		"priority": 2,
		"action": {
			"type": "redirect",
			"redirect": {
				"regexSubstitution": "\\1"
			}
		},
		"condition": {
			"regexFilter": "^https://www.googleadservices.com/.*adurl=https://clickserve.dartsearch.net/.*ds_dest_url%3D(.*)%3F.*",
			"resourceTypes": [ "main_frame" ]
		}
	},
	{
		"id": 3,
		"priority": 1,
		"action": {
			"type": "redirect",
			"redirect": {
				"regexSubstitution": "\\1"
			}
		},
		"condition": {
			"regexFilter": "^https://www.googleadservices.com/.*adurl=(.*)%3F.*",
			"resourceTypes": [ "main_frame" ]
		}
	},
	{
		"id": 4,
		"priority": 1,
		"action": {
			"type": "redirect",
			"redirect": {
				"regexSubstitution": "\\1"
			}
		},
		"condition": {
			"regexFilter": "^https://www.googleadservices.com/.*adurl=(.*)",
			"resourceTypes": [ "main_frame" ]
		}
	}
]

Basically, the condition specifies a regexp, and the part in () is referred to in regexSubstitution as \1.

The 3F-stuff is there, because the url after adurl is urlencoded, and I can not find out how to unencode before redirect. The 3F is the question mark, so essentially the wanted URL is stripped from the parameters.

I know this is very rough, but I looked into Chrome Extensions only for a few hours, and my hope is, that someone who reads this comes up with something more polished.

I tested this on a few ads, and I was quite pleased.

2 Likes

Pi-hole doesn't block at the URL level, it blocks at the domain level.

This seems very odd. Run an adblocker (i.e. Pi-hole) for the purpose of blocking ads. Then, circumvent this ad blocker so you can get to ads.

This is the much more preferred approach. Why go to the ad-served link when the regular link is just a few lines below?

Can be achieved, using pihole, read here (Whitelist Google Ads for some clients with Pi-hole).

Your approach looks similar to that of the Google search link fix browser extension I've been using, but that seems to be discontinued?

Anyway, this seems more related Google's dynamically scripted URL link manipulations (channeling you through their tracking sites instead of taking you straight to the target site) than to Pi-hole: You'd benefit from changing the link in the browser back to the originally intended target site regardless -and even in the absence of- any additional client-side or server-side filtering. :slight_smile:

Most of the search engines are now funneling their first page of results though tracking sites, or at least the top ones. I notice that Bing will put a tiny "AD" next to it which tells me not to select it. You have to scroll down much further to get the real site, here is an example searching for Kohl's. The one with AD many times will route you though their tracking servers.

To jpgpi250: Yes, I was aware of this alternative. Basically, this is why I choose the title "another approach". Your link should show to the moderators, to what lengths people go who like to continue to use pihole, and still look for peace with the rest of the family. I use pihole in the simplest configuration, where I just told the router to use pihole for DNS requests, and pihole, to use 1.1.1.1. I want to avoid to configure DNS on every device. And I do not want to start whitelisting. Unfortunately, it turns out that Chrome on Android does not support extensions, so my wife, for whom I experimented with this approach, can still not click on google ads...
To Bucking_Horn: I looked shortly on the github page of the Google search link fix. It does not mention adurl, or googleadservices, and is archived since 10 years. The extension can no longer be found anywhere. I suspect also that the links of google ads have changed since that time.
I do not intend to work against pihole. Rather, I am fond of pihole, and I think there are a lot of people either deinstalling pihole or whitelisting google ads entirely or configure pihole for each device, just because household members insist to be able to click on google ads.
To RonV42: I am in Germany and here there are no ads for Kohls. Also, the ad links on Bing look very different, and the original URL is not in clear text as on Google. So this approach does not work with Bing, only with Google.

Put your wife's device(s) in their own Pi-hole management group, assign all your current adlists to that group and whitelist the Google ad domains for that group only.

She will be able to load Google ads, but they will continue to be blocked for the rest of the network.

Hey! I followed the PDF Guide; however, I ran into conflicts. After restart and reload DNS and deleting the device's cache, it works and allows the whitelisted domains. However, after a few minutes, the Ads are being blocked again. This happens on all the "googleads" devices. Is there something that could overwrite the whitelist? Something cache related? I use Unbound as the Upstream DNS Server, maybe something on that?

check the scripts comment lines (pihole version).

# This script will work for both v5 and v6, change the value to match your version.
# gravity database: pi-hole v5 - version = 15, v6 version = 19

if the script ran without errors, seven (7) whitelist entries should exist with the comment 'allow google ads'.

Thank you for your prompt reply! I didn't use the script. I just entered everything mentioned in the guide to the Pi-Hole interface manually. Is that the reason it just worked for a few minutes? Does this also means the script requires a cron job, or do I need to execute it just once?

no cronjob required

run it just once, this will create the whitelist entries and the group. You only have to add devices (that require google ads) to the group.

run pihole -d (or tools // generate debug log) and post the link here to have it examined by a moderator / developer (they are the only ones with acces to the logs - regular users can't acces the logs).

Now I am running in problems to run the script. This might be because I am runing Pi-Hole in a Docker/Portainer Environment.

I placed the script here:
/var/lib/docker/volumes/pihole_data/_data

Which is the /etc/pihole target.
But if I execute the script from there, by ./googleads.sh
I got this message:

/var/lib/docker/volumes/pihole_data/_data$ ./googleads.sh
./googleads.sh: line 27: pihole-FTL: command not found
 [e[0;91m!e[0m] This script was written for gravity database version 15 e[0;92m(current version: )e[0m.
 [e[0;94mie[0m] Open an issue on GitHub (https://github.com/jpgpi250/piholemanual/issues).

I changed the version to 15 since I am using v5. So I changed it to this:

# This script will work for both v5 and v6, change the value to match your version.
# gravity database: pi-hole v5 - version = 15, v6 version = 19
dbversion=$(pihole-FTL sqlite3 "${gravitydb}" ".timeout = 2000" \
	"SELECT value FROM 'info' \
		WHERE property = 'version';")
if [[ "${dbversion}" != "15" ]]; then
	echo -e "${NOK}This script was written for gravity database version 15 ${GREEN}(current version: ${dbversion})${NC}."
	echo -e "${INFO}Open an issue on GitHub (https://github.com/jpgpi250/piholemanual/issues)."
	exit
fi

I also made the file executable by: sudo chmod +x ./googleads.sh

So this way it seems not to work. Therefore, I guess that I need to run the script inside the Pi-Hole Container, then? But if I "ls" inside, I can't find the script. I got this file structure:

root@pihole:/# ls
bin  boot  command  dev  etc  home  lib  macvendor.db  media  mnt  opt  package  pihole.docker.tag  proc  root  run  s6-init  sbin  srv  sys  tmp  usr  var

cd into etc/pihole results in "No such file or directory"

Therefore, I am feeling pretty confused right now.

sorry, I don't use / know docker, thus can't help you...

No problem, and thank you for your help! One last question: Setting the whole thing up from the UI (Whitelist, Group, Clients from the PDF Guide) should result in the same behavior as the script, right?
I just wonder why it works for a few minutes and the starts to block the Google Ads again.

You need to run the script inside the container.

Option 1:
If you are using Portainer, open the Portainer console for this container and execute the scritp in /etc/pihole.

Option 2:
If you want to execute the command from your host, you will need to use docker exec command:

docker exec -it <pihole_container_name> bash -c "/etc/pihole/googleads.sh"
1 Like

Thank you so much! Now I got it up and running.
Unfortunately, it only works for a few minutes. Thereafter, on all devices, the Google Ads are being blocked again for some reason. So something changes in the background. Any idea?

Edit: After waiting for 8 hours now it finally works. :heart_eyes: