""" P61 — "Untergeschobene Cookies"-Erkennung. Wenn eine Site einen Vendor einbindet (z.B. "Google Tag Manager"), kommen oft AUTOMATISCH weitere Cookies/Vendors mit, die der Marketing-Manager nicht aktiv ausgewaehlt hat (DoubleClick-Werbe-IDs ueber GTM, Facebook- Conversion-API ueber Meta-Pixel, Hotjar-Recordings ueber HubSpot etc.). Dieses Modul mappt: Primary-Vendor (eingebunden) -> Implicit-Cookies/Vendors (mitgekommen) Mit Quellen-Doku aus offiziellen Anbieter-Pages. """ from __future__ import annotations from typing import TypedDict class ImplicitItem(TypedDict, total=False): name: str type: str # "cookie" | "vendor" category: str # essential/functional/statistics/marketing why: str # warum kommt das mit source_url: str # Anbieter-Doku # Primary-Vendor (lowercase, substring-match) -> Liste implizit mitgeladener Items VENDOR_PACKAGE_COOKIES: dict[str, list[ImplicitItem]] = { # Google Tag Manager — laedt typischerweise Google Analytics + Ads "google tag manager": [ {"name": "_ga", "type": "cookie", "category": "statistics", "why": "GTM laedt Google Analytics by default mit, sobald ein " "GA4-Tag konfiguriert ist.", "source_url": "https://support.google.com/tagmanager/answer/9442095"}, {"name": "_gid", "type": "cookie", "category": "statistics", "why": "Google Analytics Session-ID, automatisch mit GA.", "source_url": "https://support.google.com/analytics/answer/11397207"}, {"name": "_gcl_au", "type": "cookie", "category": "marketing", "why": "Google Ads Conversion-Linker — kommt mit jedem GTM-Container " "der ein Conversion-Tag enthaelt (z.B. Floodlight, Ads).", "source_url": "https://support.google.com/google-ads/answer/7521212"}, {"name": "Google Ads", "type": "vendor", "category": "marketing", "why": "GTM ist Google-Infrastruktur — Google sieht alle Requests " "ueber GTM (auch wenn nur Analytics konfiguriert ist).", "source_url": "https://support.google.com/tagmanager/answer/9323295"}, ], # Google Analytics — implizit oft DoubleClick / Ads-Personalization "google analytics": [ {"name": "_gcl_au", "type": "cookie", "category": "marketing", "why": "GA4 mit aktivierter Google-Signals (Werbeberichte) setzt " "Conversion-Linker — auch ohne Ads-Konfiguration.", "source_url": "https://support.google.com/analytics/answer/9445345"}, {"name": "DSID", "type": "cookie", "category": "marketing", "why": "DoubleClick-Cookie ueber doubleclick.net — laeuft mit " "GA4 + Google-Signals automatisch.", "source_url": "https://policies.google.com/technologies/cookies"}, {"name": "Google Marketing Platform", "type": "vendor", "category": "marketing", "why": "Mit Google-Signals fliessen aggregierte Daten in Googles " "Werbeprofil-Datenbank.", "source_url": "https://policies.google.com/technologies/cookies"}, ], # Meta-Pixel — kommt typischerweise mit Facebook Login + Conversion-API "meta pixel": [ {"name": "_fbc", "type": "cookie", "category": "marketing", "why": "Facebook Click-ID — wird vom Meta-Pixel beim ersten Besuch " "via Werbe-Klick gesetzt.", "source_url": "https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc"}, {"name": "fr", "type": "cookie", "category": "marketing", "why": "Facebook Cross-Site-Tracking — wird ueber facebook.com " "Subdomain gesetzt, auch ohne aktiven FB-Login.", "source_url": "https://www.facebook.com/policies/cookies/"}, {"name": "Facebook Conversion API", "type": "vendor", "category": "marketing", "why": "Server-zu-Server Tracking ergaenzt das Browser-Pixel — wird " "oft via 'Erweiterte Matching'-Setting automatisch aktiviert.", "source_url": "https://developers.facebook.com/docs/marketing-api/conversions-api/"}, ], "facebook pixel": [ # Alias-Eintrag — verweist auf gleiche implicits {"name": "_fbc", "type": "cookie", "category": "marketing", "why": "siehe Meta-Pixel-Eintrag (Aliase).", "source_url": "https://www.facebook.com/policies/cookies/"}, {"name": "fr", "type": "cookie", "category": "marketing", "why": "siehe Meta-Pixel-Eintrag (Aliase).", "source_url": "https://www.facebook.com/policies/cookies/"}, ], # HubSpot — mit jedem Embed kommt Tracking + Chat + Forms "hubspot": [ {"name": "__hstc", "type": "cookie", "category": "marketing", "why": "HubSpot-Analytics-Cookie wird beim ersten HubSpot-Tag " "automatisch gesetzt.", "source_url": "https://knowledge.hubspot.com/de/privacy-and-consent/what-cookies-does-hubspot-set-in-a-visitor-s-browser"}, {"name": "hubspotutk", "type": "cookie", "category": "marketing", "why": "User-Token zur seitenuebergreifenden Identifikation.", "source_url": "https://knowledge.hubspot.com/de/privacy-and-consent/what-cookies-does-hubspot-set-in-a-visitor-s-browser"}, {"name": "HubSpot Chat (Drift / Conversations)", "type": "vendor", "category": "functional", "why": "HubSpot CMS aktiviert oft den Chat-Widget by default.", "source_url": "https://www.hubspot.com/data-privacy/cookies"}, ], # Akamai (CDN/Security) — Bot-Manager-Cookies sind essential, aber Akamai # selbst hat Web-Performance-Cookies die als statistics gelten koennen. "akamai": [ {"name": "AKA_A2", "type": "cookie", "category": "functional", "why": "Akamai Adaptive-Acceleration Performance-Cookie.", "source_url": "https://techdocs.akamai.com/"}, ], # Adobe Analytics (Marketing Cloud) — laedt Audience-Manager-Cookies "adobe analytics": [ {"name": "s_cc", "type": "cookie", "category": "statistics", "why": "Adobe Analytics Session-Cookie.", "source_url": "https://experienceleague.adobe.com/docs/analytics/implementation/vars/config-vars/cookies.html"}, {"name": "AAM_uuid", "type": "cookie", "category": "marketing", "why": "Adobe Audience Manager — kommt mit Adobe Analytics-Tag wenn " "Audience-Sharing aktiviert ist.", "source_url": "https://experienceleague.adobe.com/docs/audience-manager.html"}, ], # LinkedIn Insight Tag — laedt LinkedIn + AdvertiserSync Cookies "linkedin insight": [ {"name": "li_sugr", "type": "cookie", "category": "marketing", "why": "LinkedIn-Browser-ID — wird vom Insight-Tag gesetzt.", "source_url": "https://www.linkedin.com/legal/l/cookie-table"}, {"name": "AnalyticsSyncHistory", "type": "cookie", "category": "marketing", "why": "LinkedIn-Cross-Domain-Tracking ueber Insight-Tag.", "source_url": "https://www.linkedin.com/legal/l/cookie-table"}, ], } def detect_implicit_cookies( declared_vendors: list[str], actual_cookies_set: list[str] | None = None, ) -> list[dict]: """Findet untergeschobene Cookies/Vendors. Args: declared_vendors: Liste der vom CMP/Banner deklarierten Vendor-Namen. actual_cookies_set: Optional — Cookie-Namen, die tatsaechlich gesetzt wurden. Wenn gegeben, wird nur reportiert was nicht in der declared-Liste UND tatsaechlich gesetzt ist. Returns: Liste Finding-Dicts mit: primary_vendor, implicit (ImplicitItem), present_in_actual (bool) """ findings: list[dict] = [] actual_lower = {c.lower() for c in (actual_cookies_set or [])} declared_lower = {v.lower() for v in declared_vendors} for primary in declared_vendors: plower = primary.lower() implicits = [] for key, items in VENDOR_PACKAGE_COOKIES.items(): if key in plower: implicits.extend(items) for impl in implicits: name_lower = impl["name"].lower() # Skip if user has explicitly declared this implicit vendor if impl["type"] == "vendor": if any(name_lower in d for d in declared_lower): continue # If actuals provided: only report if cookie really set present = True if actual_cookies_set is not None and impl["type"] == "cookie": present = impl["name"] in actual_cookies_set or any( impl["name"].lower() in c.lower() for c in actual_cookies_set ) if not present: continue findings.append({ "primary_vendor": primary, "implicit": impl, "present_in_actual": present, }) return findings