Link decoration across a bounce
Why it matters When third-party cookies are blocked, some trackers move the ID into the web address itself. Knowing what that looks like lets you spot it in your own address bar, and it explains why browsers now strip some link parameters.
If a club cannot give you a wristband, it can write a number on your hand. AdCo's version: when Sam clicks one of AdCo's "deals" links, Sam briefly passes through adco.example (a bounce, which you first followed hop by hop in lesson 38), and AdCo adds Sam's ID to the address of the shop he lands on.
Bounce: a quick hop through a tracker's site on the way to where you meant to go. You barely see it, but for a moment the tracker is the site in your address bar, so it can use its own first-party cookie.
Link decoration (from lesson 37): adding an ID to a link's address, for example ?adco_uid=4c1e9b0a, so the next site can read it.
In this lab third-party cookies are blocked, so cookie_id is always None. But records after a bounce now carry url_id: the ID AdCo put into the address. The shop page keeps it in its own storage, so later pages on that shop report it too.
A decorated address looks like this:
https://shopb.example/?adco_uid=d1151837cb90cdb8Python can split an address into parts with urllib.parse: urlsplit(url).query gives the text after ?, and parse_qs turns it into a dict of lists. The values are lists because a parameter may appear more than once in an address, so take the first item.
from urllib.parse import urlsplit, parse_qs
url = "https://shopb.example/?ref=mail&adco_uid=d115"
print(parse_qs(urlsplit(url).query)) # {'ref': ['mail'], 'adco_uid': ['d115']}The defences
Browsers fight this in two ways (checked October 2026). First, several browsers strip well-known decoration parameters from links, in private modes or strict settings. Second, they detect sites that only ever bounce you and clear their storage: Safari has done this since 2018, Firefox purges known trackers' storage daily by default and has fuller bounce tracking protection in Strict mode, and Chrome applies it only for people who block third-party cookies.
You already wrote a link cleaner in lesson 37. In lesson 49 (Module 8) you run it on every navigation and teach your blocker to spot and skip bouncers like AdCo's click link.
In other languages
JavaScript has a built-in parser:
const id = new URL(url).searchParams.get("adco_uid"); // null if missingGo:
u, _ := url.Parse(raw)
id := u.Query().Get("adco_uid") // "" if missingRecap
- With third-party cookies blocked, a tracker can carry the ID in the address instead.
- A bounce lets the tracker use its own cookie for a moment.
- Browsers respond by stripping tracking parameters and catching bounce sites.
Write id_in_address(url) that returns the value of the adco_uid parameter, or None if it is missing. Write join_by_url_id(records) that maps each record's url_id (skip None) to the set of sites. Then build AdCo's log for seed=7 with the pages list in the starter, block_third_party_cookies=True and decorate_links=True, and store join_by_url_id of it in joined.
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.