The profile an ad network would sell
Why it matters A tracker's log is not just a list of pages. Read together, the pages turn into guesses about a person's life. This lab makes that concrete, so the stakes of tracking stop being abstract.
Sam never told AdCo anything. Sam just shopped. But AdCo saw every page, and each page has a category. Count the categories and a picture appears: someone into running, perhaps expecting a baby, perhaps worried about money.
Interest profile: a summary of what a person seems interested in, built by counting the kinds of pages they viewed. Ad networks use profiles to choose which ads to show and, in some cases, sell or share them.
Some categories are more sensitive than others. Health, pregnancy, quitting smoking, money trouble and baby things can reveal a medical condition, a pregnancy or a family's finances, often before the person has told anyone close to them.
The practice world has its own list, SENSITIVE_CATEGORIES, which leaves out baby. This lab's SENSITIVE set adds it, because baby shopping so often hints at a pregnancy.
Counting with a dictionary
counts = {}
for category in ["running", "baby", "running"]:
counts[category] = counts.get(category, 0) + 1
print(counts) # {'running': 2, 'baby': 1}counts.get(key, 0) means "the current count, or 0 if this is new". Python also has collections.Counter, which does the same job in one line; either is fine.
To find the key with the biggest count, max(counts, key=counts.get) looks at every key but compares them by counts.get(key), their count:
print(max({"running": 2, "baby": 1}, key={"running": 2, "baby": 1}.get)) # runningIn this lab you use a longer session (40 pages) with a normal browser. First find AdCo's main ID for Sam (the cookie ID seen on the most records), then count the categories of that ID's records, then list which sensitive categories appear.
The defence
Partitioning (lesson 41) cuts this profile into one small piece per shop, and a blocker (Module 8) stops the reports entirely. Neither changes what each shop knows about its own visitors; they change what one outsider can join together.
In other languages
JavaScript:
const counts = {};
for (const r of mine) counts[r.category] = (counts[r.category] ?? 0) + 1;C#:
var counts = mine.GroupBy(r => r.Category).ToDictionary(g => g.Key, g => g.Count());Recap
- Counting page categories under one ID turns a log into a life story.
- Sensitive guesses (health, pregnancy, money) come from ordinary shopping.
- Partitioning and blocking stop one outsider from joining it all together.
For seed=7 and world.browsing_session(40) with a normal browser: write main_id(records) (the non-None cookie_id that appears on the most records), interests(records, cookie_id) (a dict counting the categories of records with that ID), and sensitive_found(counts) (a sorted list of the categories in SENSITIVE that appear in counts). Store the results in sam_id, profile and found.
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.