| Next revision | Previous revision |
| programming:crawler:pagegraph [2026/08/14 15:17] – Create Brave PageGraph measurement guide; Authored by Claude karel.kubicek.claude | programming:crawler:pagegraph [2026/08/14 18:16] (current) – Escape CLI flags with nowiki: DokuWiki typography was converting -- into an en-dash, printing --debug/--logging as en-dashed flags. Authored by Claude karel.kubicek.claude |
|---|
| ====== Brave PageGraph ====== | ====== Brave PageGraph ====== |
| |
| PageGraph is a **page-execution recorder**, not a browser automation library and not a graph-neural-network classifier. It patches Brave's Blink and V8 engines so that the browser records a directed, attributed graph of what happened while a page ran: which parser, script, DOM element, frame, resource, or Web API action caused the next event. The practical entry point is [[https://github.com/brave/pagegraph-crawl|pagegraph-crawl]], and the output is normally queried after the crawl with [[https://github.com/brave-experiments/pagegraph-query|pagegraph-query]]. PageGraph is the maintained successor to the AdGraph line of graph-based blocking work {[iqbal2020_adgraph]}; [[Privacy:Javascript]] is the place for the classification questions that sit on top of this trace. | PageGraph is a **page-execution recorder**, not a browser automation library and not a graph-neural-network classifier. It patches Brave's Blink and V8 engines so that the browser records a directed, attributed graph of what happened while a page ran: which parser, script, DOM element, frame, resource, or Web API action caused the next event. The practical entry point is [[https://github.com/brave/pagegraph-crawl|pagegraph-crawl]], and the output is normally queried after the crawl with [[https://github.com/brave-experiments/pagegraph-query|pagegraph-query]]. PageGraph extends the graph representation introduced by AdGraph {[iqbal2020_adgraph]}, improving event attribution and capturing more page behaviours {[siby2022_webgraph]}, and it is the branch of that line that is still maintained; [[Privacy:Javascript]] is the place for the classification questions that sit on top of this trace. |
| |
| <WRAP important> | <WRAP important> |
| | Metadata | source URL, V8 script ID and source location, event order/timestamps, and build-dependent request/response attributes | makes a graph query auditable and lets a later analysis replay the relevant history | | | Metadata | source URL, V8 script ID and source location, event order/timestamps, and build-dependent request/response attributes | makes a graph query auditable and lets a later analysis replay the relevant history | |
| |
| The original PageGraph description gives the useful concrete cases: a script-to-element edge can mean “this script changed the element”, and an element-to-resource edge can mean “this element's `src` caused the fetch” {[sjosten2020_filter]}. SugarCoat's extension makes the model especially clear for privacy work: it records the scripts on the JavaScript stack at a Web API access, the source location of each, and then traverses insertion and execution edges to find scripts injected downstream {[smith2021_sugarcoat]}. The event-loop-turn work uses the ordering metadata to extract a subgraph for one script's deterministic activity, rather than treating the whole page as one undifferentiated trace {[chen2021_detecting]}. | The original PageGraph description gives the useful concrete cases: a script-to-element edge can mean “this script changed the element”, and an element-to-resource edge can mean “this element's ''src'' caused the fetch” {[sjosten2020_filter]}. SugarCoat's extension makes the model especially clear for privacy work: it records the scripts on the JavaScript stack at a Web API access, the source location of each, and then traverses insertion and execution edges to find scripts injected downstream {[smith2021_sugarcoat]}. The event-loop-turn work uses the ordering metadata to extract a subgraph for one script's deterministic activity, rather than treating the whole page as one undifferentiated trace {[chen2021_detecting]}. |
| |
| In a simple dependency chain, the graph can retain something like: | In a simple dependency chain, the graph can retain something like: |
| </code> | </code> |
| |
| That is the distinction from a table of requests. The table tells you that `C` was requested; the graph lets you ask which element, script and upstream insertion led to it, and whether the request arose in a child frame. PageGraph's current documentation lists script execution, most resource requests, DOM changes, Shields/filter-rule effects, timestamps, remote frames, and GraphML export as supported features.(([[https://github.com/brave/brave-browser/wiki/PageGraph|Brave PageGraph documentation]], checked 2026-08-14.)) | That is the distinction from a table of requests. The table tells you that ''C'' was requested; the graph lets you ask which element, script and upstream insertion led to it, and whether the request arose in a child frame. PageGraph's current documentation lists script execution, most resource requests, DOM changes, Shields/filter-rule effects, timestamps, remote frames, and GraphML export as supported features.(([[https://github.com/brave/brave-browser/wiki/PageGraph|Brave PageGraph documentation]], checked 2026-08-14.)) |
| |
| ===== Why this resists request-level attribution errors ===== | ===== Why this resists request-level attribution errors ===== |
| * the upstream chain that brought a script, frame, or resource into the page. | * the upstream chain that brought a script, frame, or resource into the page. |
| |
| This is why the 2020 PageGraph paper reports better attribution than its AdGraph predecessor for cases such as JavaScript in an element attribute (`onerror=...`) and timer callbacks that reset the ordinary JavaScript stack {[sjosten2020_filter]}. It also broadens the observed event set to include, among other examples, image requests initiated by CSS or prefetch, modifications in local subdocuments, and failed requests {[sjosten2020_filter]}. The 2025 Local Frames crawl describes the current measurement-facing output in the same terms: salient events plus the HTML element or JavaScript unit responsible for each event, one graph per measured website {[ukani2025_local]}. | This is why the 2020 PageGraph paper reports better attribution than its AdGraph predecessor for cases such as JavaScript in an element attribute (''onerror=...'') and timer callbacks that reset the ordinary JavaScript stack {[sjosten2020_filter]}. It also broadens the observed event set to include, among other examples, image requests initiated by CSS or prefetch, modifications in local subdocuments, and failed requests {[sjosten2020_filter]}. The 2025 Local Frames crawl describes the current measurement-facing output in the same terms: salient events plus the HTML element or JavaScript unit responsible for each event, one graph per measured website {[ukani2025_local]}. |
| |
| The graph does **not** prove that an actor intended a purpose, nor does it follow arbitrary values through JavaScript variables. A script can be the causal actor for a request without the graph telling you whether the request carried an identifier. For tracking classification, combine the graph with a filter list, a label source, or manual review, and state which of those supplied the label. For data-flow questions, use a taint-tracking instrument instead. | The graph does **not** prove that an actor intended a purpose, nor does it follow arbitrary values through JavaScript variables. A script can be the causal actor for a request without the graph telling you whether the request carried an identifier. For tracking classification, combine the graph with a filter list, a label source, or manual review, and state which of those supplied the label. For data-flow questions, use a taint-tracking instrument instead. |
| ===== Current toolchain (checked 2026-08-14) ===== | ===== Current toolchain (checked 2026-08-14) ===== |
| |
| PageGraph is included in Brave builds from version 1.46 onward; enabling it still requires the PageGraph command-line settings. Recording built-in JavaScript APIs requires a Brave Nightly build, because the stable/beta builds omit that instrumentation for performance reasons.(([[https://github.com/brave/brave-browser/wiki/PageGraph|Brave's PageGraph wiki]], checked 2026-08-14.)) Do not silently substitute “Brave” for “PageGraph”: report the exact browser channel and build, and which API set was enabled. | PageGraph is included in Brave builds from version 1.46 onward, but it is off unless the browser is launched with the right command-line arguments. Brave's wiki does not enumerate them and instead directs you to ''pagegraph-crawl'', which sets them for you — so in practice you only need the flags if you are launching Brave yourself. Recording built-in JavaScript APIs requires a Brave Nightly build, because the stable/beta builds omit that instrumentation for performance reasons; which Web APIs are instrumented is fixed at build time by a ''interface.py'' file, and adding more means rebuilding Brave.(([[https://github.com/brave/brave-browser/wiki/PageGraph|Brave's PageGraph wiki]], checked 2026-08-14.)) Do not silently substitute “Brave” for “PageGraph”: report the exact browser channel and build, and which API set was enabled. |
| |
| The usable pieces are: | The usable pieces are: |
| |
| ^ Piece ^ Use now ^ State and trap ^ | ^ Piece ^ Use now ^ State and trap ^ |
| | [[https://github.com/brave/pagegraph-crawl|pagegraph-crawl]] | drives a PageGraph-enabled Brave binary and writes GraphML recordings | current command-line crawler; the README tests with Node v23.4.0 and warns that Puppeteer/devtools interaction is not itself tracked | | | [[https://github.com/brave/pagegraph-crawl|pagegraph-crawl]] | drives a PageGraph-enabled Brave binary and writes GraphML recordings | current command-line crawler; the README tests with Node v23.4.0 and warns that Puppeteer/devtools interaction is not itself tracked | |
| | [[https://github.com/brave-experiments/pagegraph-query|pagegraph-query]] | queries `html`, `requests`, `scripts`, `js-calls`, `subframes`, `unknown`, and `validate` | current query path; run validation and inspect `unknown` events before counting | | | [[https://github.com/brave-experiments/pagegraph-query|pagegraph-query]] | Python CLI; queries ''elm'', ''html'', ''requests'', ''scripts'', ''js-calls'', ''subframes'', ''unknown'', and ''validate'' | current query path; run validation and inspect ''unknown'' events before counting | |
| | [[https://github.com/brave/pagegraph-rust|pagegraph-rust]] | older Rust library/CLI | archived on 2026-07-21; its README says to use `pagegraph-query` instead | | | [[https://github.com/brave/pagegraph-rust|pagegraph-rust]] | older Rust library/CLI | archived on 2026-07-21; its README says to use ''pagegraph-query'' instead | |
| |
| The minimal crawl shape documented by `pagegraph-crawl` is: | The minimal crawl shape documented by ''pagegraph-crawl'' is: |
| |
| <code bash> | <code bash> |
| npm install | npm install |
| npm run build | npm run build |
| npm run crawl -- \\ | npm run crawl -- \ |
| -b /path/to/Brave\ Browser\ Nightly \\ | -b /path/to/Brave\ Browser\ Nightly \ |
| -u https://example.org \\ | -u https://example.org \ |
| -t 30 \\ | -t 30 \ |
| -o output/ --debug debug | -o output/ --logging verbose |
| </code> | </code> |
| |
| The `-t` value is a measurement decision, not a harmless default: a short visit sees a different execution path from a visit that waits for consent interaction, scroll, login, or delayed work. The crawler repository's warning is important for study design: PageGraph does not track Puppeteer/DevTools automation scripts, and changing the document through that automation while recording can fail.(([[https://github.com/brave/pagegraph-crawl|pagegraph-crawl README]], checked 2026-08-14.)) If the research question requires scripted interaction, document exactly when it happened, test whether the resulting graph remains valid, and report the interaction itself separately from page-caused events. | <WRAP important> |
| | Do not copy the ''%%--debug debug%%'' example that ''pagegraph-crawl'''s own README still shows. That flag no longer exists: the current argument parser accepts ''%%--logging {none,info,verbose}%%'' (default ''info''), and ''%%--debug debug%%'' exits with ''%%run.js: error: unrecognized arguments: --debug debug%%''. Verified against ''src/run.ts'' at version 1.2.13 on 2026-08-14. It is a good reminder to run any documented command before putting it in a paper's artifact appendix. |
| | </WRAP> |
| | |
| | <WRAP important> |
| | **Record the Shields state, and do not assume it.** PageGraph runs inside Brave, which ships an ad and tracker blocker, so "what the page did" depends on whether that blocker was on. The trap is that the two obvious ways to run it disagree: ''pagegraph-crawl'' defaults to ''-s down'' — Shields **off**, so a default crawl sees an essentially unfiltered web — whereas a Brave you launch yourself has Shields **on** by default. A prevalence figure means something different under each, and ''%%--shields%%'' is ignored entirely when ''%%--existing-user-data-dir%%'' is used. Verified against ''src/run.ts'' (''defaultShieldsSetting = "down"'') on 2026-08-14. |
| | </WRAP> |
| | |
| | The ''-t'' value is the dwell time in **seconds** and is a measurement decision, not a harmless default: a short visit sees a different execution path from a visit that waits for consent interaction, scroll, login, or delayed work. The crawler repository's warning is important for study design: PageGraph does not track Puppeteer/DevTools automation scripts, and changing the document through that automation while recording can fail.(([[https://github.com/brave/pagegraph-crawl|pagegraph-crawl README]], checked 2026-08-14.)) If the research question requires scripted interaction, document exactly when it happened, test whether the resulting graph remains valid, and report the interaction itself separately from page-caused events. |
| |
| ===== Cost and failure modes ===== | ===== Cost and failure modes ===== |
| PageGraph's price is a patched browser, a larger recording, and a version-maintenance obligation. | PageGraph's price is a patched browser, a larger recording, and a version-maintenance obligation. |
| |
| * **Engineering and browser drift.** The first corpus description reported approximately 12K lines of Blink/V8 patches {[sjosten2020_filter]}. Those patches are now carried in Brave, which removes the need to maintain a private fork for a basic run, but it does not remove Chromium/Brave version drift. Extending the instrumented API set can still require a rebuild. The current query documentation also says that its format documentation is incomplete.(([[https://github.com/brave-experiments/pagegraph-query|pagegraph-query]], checked 2026-08-14.)) | * **Engineering and browser drift.** The first corpus description reported approximately 12K lines of Blink/V8 patches {[sjosten2020_filter]}. Those patches are now carried in Brave, which removes the need to maintain a private fork for a basic run, but it does not remove Chromium/Brave version drift. Extending the instrumented API set can still require a rebuild. The graph format itself is under-documented: Brave's wiki says of the type documentation it points to that it "is incomplete and being built up as we go", and the page it points to belongs to the now-archived ''pagegraph-rust''.(([[https://github.com/brave/brave-browser/wiki/PageGraph|Brave PageGraph wiki, "PageGraph Documentation"]], checked 2026-08-14. It links [[https://docs.rs/pagegraph/0.1.3/pagegraph/types/index.html|docs.rs/pagegraph 0.1.3]], which documents the archived ''pagegraph-rust''.)) Budget time for reading GraphML output rather than a specification. |
| * **Storage.** In the 2022 storage-policy study, 280,219 PageGraph files occupied 405 GB {[jueckstock2022_privacy]}. A later PageGraph-derived archive, WebREC, reports 10.2 MB per `.web` archive on average, of which 1.5 MB was behavior data and 0.4 MB a screenshot; its proxy-HAR comparison averaged 13.6 MB {[hantke2025web]}. The latter is an archive bundle, not a raw PageGraph-file benchmark, but it is a useful planning scale. | * **Storage.** In the 2022 storage-policy study, 280,219 PageGraph files occupied 405 GB {[jueckstock2022_privacy]}. A later PageGraph-derived archive, WebREC, reports 10.2 MB per ''.web'' archive on average, of which 1.5 MB was behavior data and 0.4 MB a screenshot; its proxy-HAR comparison averaged 13.6 MB {[hantke2025web]}. The latter is an archive bundle, not a raw PageGraph-file benchmark, but it is a useful planning scale. |
| * **Crashes and incomplete pages.** In the 2020 Alexa-100K experiment, the PageGraph issue category accounted for 4,051 of 14,493 failed visits; 85,470 visits completed successfully {[sarker2020_hiding]}. That is a study-specific failure breakdown, not a current universal failure rate. Brave's documentation explicitly prefers crashing over writing an uncertain graph and gives a 5–10% target for crash rate on real sites; treat that as a design goal, not as a measured guarantee.(([[https://github.com/brave/brave-browser/wiki/PageGraph|PageGraph crash and limitation notes]], checked 2026-08-14.)) Count attempted, valid, invalid, timed-out, and retried pages separately. | * **Crashes and incomplete pages.** In the 2020 Alexa-100K experiment, the PageGraph issue category accounted for 4,051 of 14,493 failed visits; 85,470 visits completed successfully {[sarker2020_hiding]}. That is a study-specific failure breakdown, not a current universal failure rate. Brave's documentation explicitly prefers crashing over writing an uncertain graph and gives a 5–10% target for crash rate on real sites; treat that as a design goal, not as a measured guarantee.(([[https://github.com/brave/brave-browser/wiki/PageGraph|PageGraph crash and limitation notes]], checked 2026-08-14.)) Count attempted, valid, invalid, timed-out, and retried pages separately. |
| * **Runtime and analysis cost.** The graph is built during browser execution, then parsed and indexed. A post-hoc query is cheap compared with a second crawl, but retaining every graph, source file and response can dominate storage. Compress only after validating that the query tool can still read the result, and retain the browser build and query version beside the archive. | * **Runtime and analysis cost — no published benchmark.** The graph is built during browser execution, then parsed and indexed. Neither the corpus nor Brave's documentation gives a current per-page slowdown figure, a crash rate measured in 2026, or a graph-size distribution, so **pilot a few hundred pages on your own hardware before committing to a population size**; do not budget from the numbers below, which are all study-specific. A post-hoc query is cheap compared with a second crawl, but retaining every graph, source file and response can dominate storage. Compress only after validating that the query tool can still read the result, and retain the browser build and query version beside the archive. |
| |
| Known blind spots in the current official documentation include WebSockets, workers, request headers (response headers are supported), CSS `style=` attribution, some JavaScript URLs, and attribution of requests caused by CSS rules. Large streamed request bodies are also not recorded.(([[https://github.com/brave/brave-browser/wiki/PageGraph|PageGraph feature and limitation list]], checked 2026-08-14.)) WebREC found and reported a PageGraph limitation around event handlers inside SVG elements, later addressed upstream {[hantke2025web]}; keep a versioned regression test for any event class your result depends on. | The official "Known Limitations" list had nine entries when checked on 2026-08-14, and it is worth reading in full rather than trusting this summary: no WebSocket tracking, no worker tracking, request headers not recorded (response headers are), no CSS ''style='' attribution, some JavaScript URLs unhandled, no attribution of requests caused by CSS rules, no tracking of CSS ''@import'', incomplete HSTS/URL-change handling, and large streamed request bodies not recorded.(([[https://github.com/brave/brave-browser/wiki/PageGraph|PageGraph feature and limitation list]], checked 2026-08-14.)) WebREC found and reported a PageGraph limitation around event handlers inside SVG elements, later addressed upstream {[hantke2025web]}; keep a versioned regression test for any event class your result depends on. |
| |
| ===== PageGraph versus nearby choices ===== | ===== PageGraph versus nearby choices ===== |
| ^ Instrument ^ Best question ^ What PageGraph adds or omits ^ | ^ Instrument ^ Best question ^ What PageGraph adds or omits ^ |
| | HAR/proxy/request log | Which resources and responses occurred? | lower cost and broad compatibility; initiator and DOM cause usually need inference | | | HAR/proxy/request log | Which resources and responses occurred? | lower cost and broad compatibility; initiator and DOM cause usually need inference | |
| | In-page API hooks | Which calls did page-visible JavaScript make? | easy to deploy but hookable/detectable and below the parser/renderer boundary | | | In-page API hooks (JS shims) | Which calls did page-visible JavaScript make? | easy to deploy, but the page can detect or defeat the hook | |
| | | Patched V8 (VisibleV8) | Which browser-API calls happened, and from which script? | the closest rival instrument: also a patched Chromium and not page-detectable, but it traces API calls without PageGraph's causal DOM/request edges — the two are complementary, and {[sarker2020_hiding]} used both | |
| | PageGraph | Which actor caused this page action or request, and what was the upstream chain? | browser-level causal graph; no general value-flow semantics; Brave/Chromium only | | | PageGraph | Which actor caused this page action or request, and what was the upstream chain? | browser-level causal graph; no general value-flow semantics; Brave/Chromium only | |
| | AdGraph/WebGraph | Can graph-derived features classify ad/tracker requests? | historical/modeling line, not a substitute for the current recorder; WebGraph is a classifier built from graph features {[siby2022_webgraph]} | | | AdGraph/WebGraph | Can graph-derived features classify ad/tracker requests? | historical/modeling line, not a substitute for the current recorder; WebGraph is a classifier built from graph features {[siby2022_webgraph]} | |
| | Taint tracking | Did a particular value reach a sink? | answers a different flow question and costs a browser build | | | Taint tracking | Did a particular value reach a sink? | answers a different flow question and costs a browser build | |
| |
| ===== Use in Publications ===== | ===== Use in publications ===== |
| |
| The extraction finds **8 papers that used or produced PageGraph**, out of the **1,120 papers that ran a crawl** in the corpus (0.7%). It finds 9 tool tuples because one paper records PageGraph twice; every figure here counts papers. The corpus is the seven venues listed on [[literature:corpus]], not the whole web-measurement literature. | The extraction finds **8 papers that used or produced PageGraph**, out of the **1,120 papers that ran a crawl** in the corpus (0.7%). It finds 9 tool tuples because one paper records PageGraph twice; every figure here counts papers. The corpus is the seven venues listed on [[literature:corpus]], not the whole web-measurement literature. |
| |
| ^ Year ^ Corpus papers ^ Papers naming PageGraph ^ Share of that year's corpus ^ | ^ Year ^ Corpus papers ^ Papers using or producing PageGraph ^ Share of that year's corpus ^ |
| | 2020 | 404 | 2 | 0.5% | | | 2020 | 404 | 2 | 0.5% | |
| | 2021 | 379 | 2 | 0.5% | | | 2021 | 379 | 2 | 0.5% | |
| |
| ^ Paper ^ What PageGraph contributed ^ | ^ Paper ^ What PageGraph contributed ^ |
| | Sarker et al., IMC 2020, //Hiding in Plain Site// {[sarker2020_hiding]} | joined low-level browser-API traces to high-level script provenance for obfuscation measurement | | | Sarker et al., IMC 2020, //Hiding in Plain Site// {[sarker2020_hiding]} | complemented VisibleV8's low-level browser-API traces with PageGraph's high-level script provenance for obfuscation measurement | |
| | Sjösten et al., TheWebConf 2020, //Filter List Generation for Underserved Regions// {[sjosten2020_filter]} | attributed DOM and request chains so blocking could move upstream without breaking the page | | | Sjösten et al., TheWebConf 2020, //Filter List Generation for Underserved Regions// {[sjosten2020_filter]} | attributed DOM and request chains so blocking could move upstream without breaking the page | |
| | Smith et al., CCS 2021, //SugarCoat// {[smith2021_sugarcoat]} | found dynamically injected scripts and source locations of privacy-relevant API calls for rewriting | | | Smith et al., CCS 2021, //SugarCoat// {[smith2021_sugarcoat]} | found dynamically injected scripts and source locations of privacy-relevant API calls for rewriting | |
| | Ukani et al., CCS 2025, //Local Frames// {[ukani2025_local]} | used one event graph per site to measure salient rendering and execution events | | | Ukani et al., CCS 2025, //Local Frames// {[ukani2025_local]} | used one event graph per site to measure salient rendering and execution events | |
| | Shuang et al., NDSS 2025, //Duumviri// {[shuang2025_duumviri]} | used PageGraph as one component of rendering-graph features for tracker and breakage detection | | | Shuang et al., NDSS 2025, //Duumviri// {[shuang2025_duumviri]} | used PageGraph as one component of rendering-graph features for tracker and breakage detection | |
| | Hantke et al., USENIX Security 2025, //Web Execution Bundles// {[hantke2025web]} | carried PageGraph-style behavior graphs into a replayable `.web` archive | | | Hantke et al., USENIX Security 2025, //Web Execution Bundles// {[hantke2025web]} | carried PageGraph-style behavior graphs into a replayable ''.web'' archive | |
| |
| The historical ordering matters. AdGraph and WebGraph are useful baselines for graph-derived blocking, but their classifier results are not a current PageGraph installation recipe. For a new measurement, read Sjösten for the attribution problem, Chen for extracting stable behavior units, SugarCoat for script/API graph queries, and Hantke for the current archive and maintenance argument. Then read Jueckstock if your outcome is storage policy or compatibility rather than tracker prevalence. | The historical ordering matters. AdGraph and WebGraph are useful baselines for graph-derived blocking, but their classifier results are not a current PageGraph installation recipe. For a new measurement, read Sjösten for the attribution problem, Chen for extracting stable behavior units, SugarCoat for script/API graph queries, and Hantke for the current archive and maintenance argument. Then read Jueckstock if your outcome is storage policy or compatibility rather than tracker prevalence. |
| * the population list and snapshot, visit duration, navigation/consent/authentication actions, headful/headless mode, user-agent and vantage point, cache/storage profile, and retry/timeout policy; | * the population list and snapshot, visit duration, navigation/consent/authentication actions, headful/headless mode, user-agent and vantage point, cache/storage profile, and retry/timeout policy; |
| * counts of attempted, completed, invalid/crashed, timed-out and discarded pages, with reasons; never silently drop a PageGraph issue; | * counts of attempted, completed, invalid/crashed, timed-out and discarded pages, with reasons; never silently drop a PageGraph issue; |
| | * the Brave Shields / filter-list state during the crawl, and whether filter-rule effect edges were counted or excluded — this changes what "the page did" means and is the easiest way to make a prevalence figure incomparable; |
| * the graph unit you count (script code unit, resource, frame, action, event-loop-turn, or page), and whether a paper can contribute more than one unit; | * the graph unit you count (script code unit, resource, frame, action, event-loop-turn, or page), and whether a paper can contribute more than one unit; |
| * the attribution rule and its unknown cases: parser-caused, script-caused, cross-frame, CSS-caused, or unassigned; and | * the attribution rule and its unknown cases: parser-caused, script-caused, cross-frame, CSS-caused, or unassigned; and |
| ===== Methodology and limitations of these figures ===== | ===== Methodology and limitations of these figures ===== |
| |
| * The audit script is `scripts/report_pagegraph.mjs`; its unedited output, every query, every paper key, the fold residue, source-fact checks, and quote checks are on [[provenance:programming:crawler:pagegraph|the provenance page]]. Corpus-wide selection and extraction caveats are on [[literature:corpus]]. | * The audit script is ''scripts/report_pagegraph.mjs''; its unedited output, every query, every paper key, the fold residue, source-fact checks, and quote checks are on [[provenance:programming:crawler:pagegraph|the provenance page]]. Corpus-wide selection and extraction caveats are on [[literature:corpus]]. |
| * The population query folds only the two raw tool names `PageGraph` and `PageGraph crawler` with an ordered exact regex. It counts `used` and `produced` tool tuples, then deduplicates by paper. The unmapped residue is empty in this run and is printed as empty rather than hidden. | * The population query folds only the two raw tool names ''PageGraph'' and ''PageGraph crawler'' with an ordered exact regex. It counts ''used'' and ''produced'' tool tuples, then deduplicates by paper. The unmapped residue is empty in this run and is printed as empty rather than hidden. |
| * The 2025–2026 rows are provisional, and the seven-venue corpus omits EuroS&P, ACSAC, RAID, AsiaCCS, CHI and SOUPS. The table is a finding about this corpus, not an adoption survey. | * The 2025–2026 rows are provisional, and the seven-venue corpus omits EuroS&P, ACSAC, RAID, AsiaCCS, CHI and SOUPS. The table is a finding about this corpus, not an adoption survey. |
| * Nine PageGraph evidence quotes were checked against `paper.cols.txt`: 5 exact, 3 partial after the dataset's five-word-window check, and 1 below threshold. The one below-threshold quote was manually confirmed; a column-repair hyphenation joined “Chromium-based” in the source rendering. | * Nine PageGraph evidence quotes were checked against ''paper.cols.txt'': 5 exact, 3 partial after the dataset's five-word-window check, and 1 below threshold. The one below-threshold quote was manually confirmed; a column-repair hyphenation joined “Chromium-based” in the source rendering. |
| |
| ===== Related Pages ===== | ===== Related pages ===== |
| |
| * [[Privacy:Javascript]] — classifying the JavaScript that the graph observes. | * [[Privacy:Javascript]] — classifying the JavaScript that the graph observes. |