| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| provenance:privacy:server_side_tracking [2026/08/21 06:59] – Fix a run of literal apostrophes that rendered as sixteen quotes. Authored by Claude karel.kubicek.claude | provenance:privacy:server_side_tracking [2026/08/21 14:47] (current) – Section 11.2: record the attribution error and the rule for an interested expert's claims vs assessments karel.kubicek.claude |
|---|
| | ''sgtm'' | ''/\bsGTM\b|server[- ]?side (?:google )?tag manager|server[- ]?side google analytics|\bsGA\b/i'' | 2 | 0.0% | | | ''sgtm'' | ''/\bsGTM\b|server[- ]?side (?:google )?tag manager|server[- ]?side google analytics|\bsGA\b/i'' | 2 | 0.0% | |
| | ''capi'' | ''/conversions? api|\bCAPI\b|events api/i'' | 16 | 0.3% | | | ''capi'' | ''/conversions? api|\bCAPI\b|events api/i'' | 16 | 0.3% | |
| | ''capi_product'' | ''%%/Conversions? API/%%'' — case-**sensitive**, because the product is a proper noun | 4 | 0.1% | | | ''capi_product'' | ''/Conversions? API/'' — case-**sensitive**, because the product is a proper noun | 4 | 0.1% | |
| | ''moved_server'' | the widest phrasing probe — see the script | 18 | 0.3% | | | ''moved_server'' | the widest phrasing probe — see the script | 18 | 0.3% | |
| | ''cname_cloak'' | ''/CNAME[- ]?(?:cloak\w*|based|tracking|redirection|redirect\w*|delegation)/i'' | 46 | 0.8% | | | ''cname_cloak'' | ''/CNAME[- ]?(?:cloak\w*|based|tracking|redirection|redirect\w*|delegation)/i'' | 46 | 0.8% | |
| |
| ^ Width ^ Regex ^ Papers ^ | ^ Width ^ Regex ^ Papers ^ |
| | narrow | ''%%/Conversions? API/%%'' | **4** | | | narrow | ''/Conversions? API/'' | **4** | |
| | wide | ''%%/conversions? api|\bCAPI\b|events api/i%%'' | **16** | | | wide | ''/conversions? api|\bCAPI\b|events api/i'' | **16** | |
| |
| All twelve wide-only papers are noise, and all twelve are printed in §4.1 under ''-- wide-only hits --'': | All twelve wide-only papers are noise, and all twelve are printed in §4.1 under ''-- wide-only hits --'': |
| | EasyPrivacy carries server-side-specific rules | ''easylist.to/easylist/easyprivacy.txt'' | Downloaded 2026-08-21. ''Version: 202608210608'', ''Commit: 0ad9e733cadaffac3c0b445bf27f33d3da5546da'', 56,674 lines. Rules located by line number: ''&sst.gcsub='' (29), ''?v=2&tid=G-$~third-party'' (2996), ''&sst.sw_exp='' (3097), ''||mstm.motorsport.com^'' (16159). **The list changes several times a day; re-run the script rather than citing this sentence** | | | EasyPrivacy carries server-side-specific rules | ''easylist.to/easylist/easyprivacy.txt'' | Downloaded 2026-08-21. ''Version: 202608210608'', ''Commit: 0ad9e733cadaffac3c0b445bf27f33d3da5546da'', 56,674 lines. Rules located by line number: ''&sst.gcsub='' (29), ''?v=2&tid=G-$~third-party'' (2996), ''&sst.sw_exp='' (3097), ''||mstm.motorsport.com^'' (16159). **The list changes several times a day; re-run the script rather than citing this sentence** | |
| | AdGuard's CNAME-cloaked tracker list is actively maintained | GitHub REST API on ''AdguardTeam/cname-trackers'' | Fetched 2026-08-21: ''archived: false'', ''pushed_at: 2026-08-17T15:56:27Z'' | | | AdGuard's CNAME-cloaked tracker list is actively maintained | GitHub REST API on ''AdguardTeam/cname-trackers'' | Fetched 2026-08-21: ''archived: false'', ''pushed_at: 2026-08-17T15:56:27Z'' | |
| | SST-Guard is **not peer-reviewed**: arXiv v1 only, plus a PETS 2026 poster | ''export.arxiv.org/api/query?id_list=2604.27497''; ''petsymposium.org/2026/accepted-posters.php''; ''petsymposium.org/2026/cfposters.php'' | Fetched 2026-08-21. arXiv: a single entry, ''published'' and ''updated'' both ''2026-04-30T06:50:14Z'' — so **v1 only** — and **no ''%%<arxiv:journal_ref>%%'' element**, which is what arXiv emits once a paper has a venue. **The first version of this table said "preprint with no venue", which the currency reviewer refuted**: the paper is on the PETS 2026 accepted-posters list. The qualification that saves the framing is PETS's own: "Proposals will be lightly reviewed for relevance to PETS and adherence to formatting guidelines" and "Posters will not be peer-reviewed". All three checks are now in ''sst_external_checks.sh'' | | | SST-Guard is **not peer-reviewed**: arXiv v1 only, plus a PETS 2026 poster | ''export.arxiv.org/api/query?id_list=2604.27497''; ''petsymposium.org/2026/accepted-posters.php''; ''petsymposium.org/2026/cfposters.php'' | Fetched 2026-08-21. arXiv: a single entry, ''published'' and ''updated'' both ''2026-04-30T06:50:14Z'' — so **v1 only** — and **no ''<arxiv:journal_ref>'' element**, which is what arXiv emits once a paper has a venue. **The first version of this table said "preprint with no venue", which the currency reviewer refuted**: the paper is on the PETS 2026 accepted-posters list. The qualification that saves the framing is PETS's own: "Proposals will be lightly reviewed for relevance to PETS and adherence to formatting guidelines" and "Posters will not be peer-reviewed". All three checks are now in ''sst_external_checks.sh'' | |
| | Mertens et al. 2026 is **accepted at ACM CCS 2026** | ''sigsac.org/ccs/CCS2026/program/accepted-papers.html''; HAL API on ''halId_s:hal-05466083'' | Fetched 2026-08-21. The CCS accepted-papers page carries "Detecting and Measuring Client- and Server-Side Google Tag Manager and its Tags in 80K Websites" with all five HAL authors. **The first version of this table concluded the opposite** from HAL and DBLP alone: HAL still says ''docType_s: UNDEFINED'', ''submittedDate_s: 2026-02-06'', no ''conferenceTitle_s'' and no ''journalTitle_s'', and DBLP lists the authors' EuroS&P 2025 paper and no 2026 one. **Neither repository knows about an acceptance until publication**, which is the lesson: for a 2026 paper, check the venue's own accepted-papers page, not the preprint servers. Now in ''sst_external_checks.sh'' | | | Mertens et al. 2026 is **accepted at ACM CCS 2026** | ''sigsac.org/ccs/CCS2026/program/accepted-papers.html''; HAL API on ''halId_s:hal-05466083'' | Fetched 2026-08-21. The CCS accepted-papers page carries "Detecting and Measuring Client- and Server-Side Google Tag Manager and its Tags in 80K Websites" with all five HAL authors. **The first version of this table concluded the opposite** from HAL and DBLP alone: HAL still says ''docType_s: UNDEFINED'', ''submittedDate_s: 2026-02-06'', no ''conferenceTitle_s'' and no ''journalTitle_s'', and DBLP lists the authors' EuroS&P 2025 paper and no 2026 one. **Neither repository knows about an acceptance until publication**, which is the lesson: for a 2026 paper, check the venue's own accepted-papers page, not the preprint servers. Now in ''sst_external_checks.sh'' | |
| | The SST-Guard artefacts are as described | ''github.com/jazlan01/sst-guard'' | Cloned 2026-08-21. Single commit ''9e013d4'' of 2026-04-30 UTC (''git log'' shows 2026-04-29 21:20 -0700; the page and this table use UTC so they agree with the GitHub API). 37 MB: four data files plus ''dist_chrome.zip'' | | | The SST-Guard artefacts are as described | ''github.com/jazlan01/sst-guard'' | Cloned 2026-08-21. Single commit ''9e013d4'' of 2026-04-30 UTC (''git log'' shows 2026-04-29 21:20 -0700; the page and this table use UTC so they agree with the GitHub API). 37 MB: four data files plus ''dist_chrome.zip'' | |
| |
| ^ Source ^ Renders as ^ | ^ Source ^ Renders as ^ |
| | ''%%| Table 1 | ''''Cloaked trackers | 474 | 389'''' |%%'' | two cells, the second being ''%%<code>Cloaked trackers | 474 | 389</code>%%'' | | | ''%%| Table 1 | ''''%%Cloaked trackers | 474 | 389%%'''' |%%'' | two cells, the second being ''%%<code>Cloaked trackers | 474 | 389</code>%%'' | |
| | a cell containing ''%%/^GA1\.[123]...$/%%'' | one cell, caret intact | | | a cell containing ''/^GA1\.[123]...$/'' | one cell, caret intact | |
| |
| So the delimiters are resolved before inline markup is parsed, and content inside inline monospace is safe. **The regex literals on the content page were wrapped in nowiki anyway** — not to silence the checker, which still flags them, but because DokuWiki's typography //does// reach inside inline monospace and had already been caught turning the double quotes in a published regex curly earlier in this run. | So the delimiters are resolved before inline markup is parsed, and content inside inline monospace is safe. **The regex literals on the content page were wrapped in nowiki anyway** — not to silence the checker, which still flags them, but because DokuWiki's typography //does// reach inside inline monospace and had already been caught turning the double quotes in a published regex curly earlier in this run. |
| This matters beyond one page: the checker is shared, and the next person to see six flags will "fix" tables that are not broken. Its condition should be narrowed to pipes and carets outside inline monospace and ''%%<code>%%'' spans, or it should print the rendered cell count alongside its own. | This matters beyond one page: the checker is shared, and the next person to see six flags will "fix" tables that are not broken. Its condition should be narrowed to pipes and carets outside inline monospace and ''%%<code>%%'' spans, or it should print the rendered cell count alongside its own. |
| |
| ===== 11. Run log ===== | **Done in the second sitting (§11.3).** ''check_tables.mjs'' now strips wikilinks, ''%%…%%'' nowiki and ''%%''''…''''%%'' inline monospace before counting. Across all pages that turns 14 flags into **1**, which is a real defect on ''provenance:statistics:pvalue_corrections'' (a row one cell short) and belongs to that page. |
| | |
| | ===== 11. Author review, 2026-08-21 (second sitting) ===== |
| | |
| | Karel sent the page to **Jazlan, the first author of SST-Guard**, who replied the same day. He is an expert on the topic and an interested party in one of the sources this page audits; both facts are on the record here, and every claim below was re-derived from a source rather than accepted on his word. |
| | |
| | ==== 11.1 The substantive correction: non-Google SST is detected, but not verifiable ==== |
| | |
| | His words: "SST Guard does detect CAPI implementations via GTM, and so does Mertens et. al (2026). the problem is verifiability." |
| | |
| | The page had said "**Nothing detects SST for any platform other than Google**", sourced to SST-Guard's own limitations section (§8: "SST-Guard does not currently generalize to other server-side trackers […] Meta, TikTok, Snapchat, and Reddit do not offer a debugging tool equivalent to Tag Assistant, leaving no reliable source for training labels"). **That was a misreading of a limitation about //validation// as a limitation about //visibility//.** Two independent sources contradict the stronger claim: |
| | |
| | * The **Mertens et al. HAL v2 full text**((''hal.science/hal-05466083v2/document'', 17 pp., downloaded 2026-08-21. The first sitting used only the HAL //abstract//, which reports "398 Server-Side Tags instances" without breaking them down by vendor. Reading the abstract where the full text was one fetch away is what let the wrong sentence stand — the correction cost one ''curl'' and one ''pypdf'' extraction.)) Table 7 breaks the 398 server-side Tag instances down by vendor: **161** websites for Meta CAPI (detected via ''_gtmeec'' and ''_fbp''), **15** for Snapchat (''_scid''), **9** for TikTok Events API (''_ttp''), 2 for Microsoft, 1 for LINE. Meta is the **largest single group**, ahead of every Google Tag. §4.6.1 verbatim: "We find that Tags that provide the “Facebook Conversion” service are the most popular, followed by Tags provided by Google". |
| | * **SST-Guard §6** reaches the same platforms from the payload side: "the presence of non-standard keys like ''ep.event_id'' and ''ep.fb_event_name'' provide proof that other server-side trackers are being implemented alongside sGA, most likely with sGTM". The page already quoted this in the //Consequences// section while asserting the opposite in //Open Questions// — an internal contradiction that four reviewers and I all missed. |
| | |
| | What survives, and is now stated as three separate things rather than one: no non-Google ground truth exists (SST-Guard §8); the signal does not identify //which// Tag — Mertens et al. group five distinct Meta CAPI templates because "it is not possible to identify which one is installed"; and nothing confirms the data reached Meta. Plus the shared boundary: all of it requires the deployment to ride in a GTM container. |
| | |
| | ==== 11.2 The heuristic he flagged, whose assessment it is, and why that matters ==== |
| | |
| | His words: "Mertens et. al (2026) has opened the door for basic heuristics like "_fbp cookie set as first party AND a GTM template for meta pixel not detected". It is a super super super weak heuristic, but the paper is accepted." |
| | |
| | **An attribution error in the first version of this section, corrected the same day.** The page carried this as "the one heuristic Mertens et al. make available for Meta is very weak, **and its author says so**", which reads as if Mertens et al. had rated their own result weak. They did not: they neither propose this heuristic nor evaluate it, and no author of that paper was contacted at any point. The "super super super weak" verdict is Jazlan's, and **SST-Guard is a directly competing detector of the same phenomenon** — so it is one method's author rating what a rival's result enables. Karel flagged this and had flagged the competing interest in advance; the page now names whose assessment it is, that it is a competitor's, and that Mertens et al. were not asked, in the same sentence as the quote. |
| | |
| | Recording the quote is still right — a reader who meets this heuristic second-hand should know one expert calls it very weak — but a quoted verdict from a competitor is evidence about the field's disagreements, not a neutral evaluation, and the page must not launder it into one. **What the page rests on instead is the technical objection, which is mine and holds independently of who raised it**: the discriminating power sits entirely in the //absence// of the client-side template, and Mertens et al. themselves report **6.7%** of GTM sites obfuscating the container's presence — so the negative half of the conjunction is the half most easily broken. That argument would survive if the verdict were withdrawn. |
| | |
| | **The general rule this run learned.** Expert review from a named source in the field is worth more than any amount of my own re-reading — §11.1 is the proof, since the substantive correction there came from him and was then confirmed straight out of Mertens et al.'s Table 7. But a source with a stake sets a second obligation, not a lower weight: separate what they claim from what they assess. Claims get checked against the primary source and, once verified, stand on that source (§11.1 needs no attribution to Jazlan at all — Table 7 says it). Assessments of a competitor stay attributed, are never used as the load-bearing reason for anything, and carry the competing interest next to the quote. The failure mode here was collapsing an assessment into a claim by writing "its author" — one wrong noun turned a rival's opinion into the paper's own admission. |
| | |
| | ==== 11.3 The code claims, re-run against the fixed release ==== |
| | |
| | He also fixed the extension after seeing the page. Two new commits, both 2026-08-21: ''32fedb3'' "Bug fix for static browser fingerprint" and ''18a312c'' "Fixed regex patterns that mismatched from the training process". Only ''dist_chrome.zip'' changed. His characterisation — "there were hardcoded values specific to host of the crawl he performed (think of user agent), and they are now templated for the user" — matches what the bytes show. |
| | |
| | Both audit scripts were made build-agnostic (the extractor is minified to a different name in each build, and ''18a312c'' appends a UA Client Hints IIFE after the template arrays, so the block is now cut at its terminator rather than at a hard-coded identifier) and **re-run against both releases**. Old figures reproduce exactly, which is the check that the script change did not move anything. |
| | |
| | ^ Claim as first published ^ Status at ''18a312c'' ^ |
| | | ''dl'' template matches no ordinary URL (''%%[\^\s&#]%%'', escaped caret) | **Fixed** — ''%%[^\s&#]%%''; 100.0% agreement with the published column | |
| | | ''uafvl'' 0.0% under the shipped regex against 99.5% published | **Fixed** — explicit brand-array alternation; 100.0% | |
| | | ''window'' fingerprint pins one Apple-Silicon Mac; network ''uap''/''uapv''/''uaa'' pin the Linux crawl host; the two disagree | **Fixed** — ''chrome_version'', ''platform_version'', ''uapv'' become ''%%/(?!)/%%'' and are rewritten at startup from ''navigator.userAgentData.getHighEntropyValues''; ''uaa''/''uab''/''uap'' widen to value sets | |
| | | ''gcs'', ''tcfd'', ''ep.user_agent'' fire on 73.3%/11.0%/2.9% while the published columns are constant zero | **Reconciled, downward** — all three regexes are now wrapped in literal single quotes no parameter value contains, so extension and data agree at 100% by both being inert | |
| | | Cookie and ''cid'' templates hard-code the ''17'' epoch prefix, dead after 2027-01-15 | **Not fixed** — still in ''pattern_1'', ''pattern_2'', ''pattern_5'', ''gaGlobal[vid]'' and ''cid''. The only item on the original list a reader inheriting this code still has to repair | |
| | | Shipped extractor vs published columns: 79.3% per-cell; any-parameter variant 83.1%, exactly 100% on 14 of 23 | **Improved, not closed** — 87.5% and 95.4%, exactly 100% on 19 of 23. The residue is entirely the environment features (''uapv'' 4.2%, ''uab'' 95.2%, ''uaa''/''uap'' 97.2%), which a second machine cannot reproduce by construction | |
| | |
| | ''uapv'' reads 4.2% because this replay runs under Node, where ''navigator.userAgentData'' does not exist. That is not an artefact to apologise for: the runtime rewrite sits inside a bare ''catch {}'', so off-Chromium the template stays ''%%/(?!)/%%'' and the feature reads as a confident zero rather than as missing. It is on the page as the one residue of the fingerprint fix. |
| | |
| | **A tooling fix fell out of this.** ''check_tables.mjs'' counts ''%%[|^]%%'' per row to catch cells split by a literal pipe, but did not strip ''%%…%%'' nowiki spans, so every regex containing ''%%^%%'' or ''%%|%%'' inside nowiki was a false positive — which is why the //Reproducible?// table appeared inconsistent while rendering correctly. Now stripped, alongside wikilinks. Re-running the fixed checker across all pages surfaces **14** genuinely inconsistent tables on //other// pages, where the pipes are inside ''%%''…''%%'' rather than nowiki; those are pre-existing, were not touched in this sitting, and are left for the pages that own them. |
| | |
| | ==== 11.4 What was not changed ==== |
| | |
| | * The **prevalence spread** (0.38%–38%), the interaction-depth argument, and the "which definition, which population, which interaction depth" framing — untouched. Nothing in the review bore on them. |
| | * **The audit's verdict on reusability.** 95.4% is not 100%, and the offline pipeline still is not released, so the page still says you cannot report SST-Guard's accuracy as yours. |
| | * **The 2027-01-15 expiry has still not been raised with the authors as an issue.** It is now moot as a courtesy — the author has read the page — but the deferred work item stands, and this sitting did not file anything on a third party's repository. |
| | |
| | ===== 12. Run log ===== |
| |
| ^ When ^ What ^ | ^ When ^ What ^ |
| | 2026-08-21 | **The rendered page initially showed only 5 of 13 references.** ''bibtex4dw'' caches the bibliography, so newly added keys render as inline markers with no entry. Fixed by requesting ''?purge=true'' on ''literature:bibliography'' and then on the page; re-verified 13 of 13 | | | 2026-08-21 | **The rendered page initially showed only 5 of 13 references.** ''bibtex4dw'' caches the bibliography, so newly added keys render as inline markers with no entry. Fixed by requesting ''?purge=true'' on ''literature:bibliography'' and then on the page; re-verified 13 of 13 | |
| | 2026-08-21 | Four-reviewer pass (§10); fixes applied; this provenance page published | | | 2026-08-21 | Four-reviewer pass (§10); fixes applied; this provenance page published | |
| | | 2026-08-21 | **Third sitting.** Karel caught an attribution error: the "super super super weak" verdict on Mertens et al.'s heuristic is Jazlan's, a competing author's, and had been written as if it were the paper's own authors' ("its author says so"). Corrected on the content page and recorded in §11.2, together with the rule for handling an interested expert's assessments versus their claims | |
| | | 2026-08-21 | **Second sitting (§11).** Author review from Jazlan (SST-Guard). Fetched the Mertens et al. HAL v2 full text; corrected the non-Google-detection claim from Table 7; pulled ''18a312c''; made ''sst_guard_templates.mjs'' and ''sst_guard_replay.mjs'' build-agnostic and re-ran both against both releases; fixed the nowiki blind spot in ''check_tables.mjs''; added 6 EXTERNAL entries to ''sst_number_guard.mjs'' and re-ran it to zero unaccounted figures | |
| |
| ^ Housekeeping ^ Value ^ | ^ Housekeeping ^ Value ^ |