| name | speculation-rules |
| description | Executes performance and network analysis on websites using the Speculation Rules API for background prerendering, prefetching, mixed eagerness rule sets, and instant page transitions. Use when identifying high-intent candidate pages for speculative loading, injecting and testing dynamic speculation rules (list or document rules with exclusions and server-side tags), automating hover triggers via Chrome DevTools for Agents, capturing and isolating background Prerender WebContents network requests across CDP targets (including Sec-Speculation-Tags headers), or implementing activation hold-back deferral logic for ad monetization and analytics scripts. Don't use for Single Page Applications (SPAs), legacy <link rel="prerender"> tags, or general web performance audits unrelated to the Speculation Rules API. |
Description
This skill provides step-by-step instructions for executing performance and network analysis on websites using the modern Speculation Rules API, specifically focusing on prerendering, prefetching, and mixed rule sets. The primary goal is to improve next-page load performance (including Largest Contentful Paint (LCP)) and achieve instant page transitions (~0ms load time) by speculatively downloading and rendering high-intent target pages in the background while ensuring zero waste of ad viewability or bandwidth resources.
Triggering Conditions
Invoke this skill when the user query involves:
- Speculation Rules API prerendering, prefetching, or achieving instant (~0ms LCP) page transitions.
- Identifying and evaluating candidate pages (e.g., static pages cached at the edge, PDPs, listing details, high-eCPM category hubs) for speculative loading on Multi-Page Applications (MPAs).
- Designing list rules (
urls) or document rules (where selectors with exclusions) and configuring eagerness levels (immediate, eager, moderate, conservative) or mixed prefetch/prerender rule sets.
- Injecting dynamic Speculation Rules JSON configurations, managing Chrome's 2-slot FIFO queue protection, and applying server-side tracking tags (
tag / Sec-Speculation-Tags).
- Triggering background prerenders via hover events using
chrome-devtools CLI without activating the page.
- Capturing, differentiating, and isolating background Prerender WebContents network requests strictly while triggered in the background without activating the page (
navigate_page must NEVER be called).
- Designing evidence-based activation hold-back scripts (
whenActivated / prerenderingchange) to defer ad monetization tags (e.g., Criteo, OpenX, PubMatic) and analytics beacons until page activation.
Tooling Requirements & Setup
Use Chrome DevTools for Agents
- Mandatory Tooling: Always use
chrome-devtools CLI (or MCP server tools) to automate browser navigation, inspect DOM elements, inject scripts, trigger hover events, and capture network requests.
- CLI Availability & Installation:
- Check if
chrome-devtools CLI is available: which chrome-devtools.
- If
chrome-devtools is not installed or available in PATH, download/install it globally using npm i chrome-devtools-mcp@latest -g before proceeding.
- Strict Rule — NO Puppeteer: Do NOT install or use Puppeteer, Playwright, or standard browser automation packages. Perform all actions directly via
chrome-devtools.
- Output File Location: All generated files (raw network request JSON files, speculation rules JSON configurations, JavaScript hold-back scripts and list of which requests to hold back on the speculated page, and markdown analysis reports) MUST be created ONLY inside the
./speculation-rules-analysis directory under the current working directory (./speculation-rules-analysis/). Do NOT create output files directly in the root working directory (./).
Core Execution Workflow (The 5 Steps)
Follow these 5 core steps sequentially for any target website <example.com>:
Step 1: Identify Candidate Pages for Prerendering & Rationale
Objective
Identify potential candidate pages on the target site that should be prefetched or prerendered by emulating a user journey and explain why for page <example.com>.
Application Architecture & Suitability Checks
- Multi-Page Applications (MPAs) vs. Single Page Applications (SPAs):
- Speculation rules are designed for multi-page applications (MPAs) where the browser navigates to a new HTML document on each navigation. Do NOT use speculation rules on Single Page Applications (SPAs), as the browser does not perform full document navigations in SPAs.
- Static vs. Dynamic Content & Edge Caching:
- Static Pages: Speculative loading is exceptionally effective for static pages where content changes infrequently and pages are cheap to serve—especially when cached at the edge CDN.
- Dynamic Pages: Exercise caution with dynamic pages where content changes frequently or depends on live user session state, due to potential stale content or higher backend compute costs.
- Excluding State-Changing Endpoints:
- Never speculate URLs that trigger state changes (e.g.,
/logout, /add-to-cart, /checkout, or query parameters like ?add-to-cart=1). Explicitly exclude these from document rules.
Selection Rationale & Criteria
- High-Intent Conversion Destinations:
- Product Detail Pages (PDPs) / Listing Detail Pages / Article Pages (e.g.,
/article/*): When users browse listing grids, categories, or search results, hovering over an item link indicates high intent to navigate. Prerendering downloads the HTML document, critical layout CSS, core JavaScript, and LCP hero images in advance, enabling instant transition (~0ms LCP delay).
- High-eCPM Category Verticals:
- Premium Section Hubs (e.g.,
/vip/*, /premium/*, /finance/, /autos/): Categories carrying high advertiser demand and high CPM yields. Prerendering these section hubs from primary navigation pre-warms key category grids and hero ad slots.
How to Execute Step 1 using chrome-devtools:
chrome-devtools new_page "https://example.com"
chrome-devtools take_snapshot
chrome-devtools click "CMP_CONSENT_BUTTON_UID"
chrome-devtools evaluate_script "() => Array.from(document.querySelectorAll('a[href]')).map(a => ({ href: a.href, text: a.innerText.trim() }))"
Step 2: Inject Speculation Rules Based on Recommendations
Objective
Formulate the optimal Speculation Rules API JSON configuration for prerendering, prefetching, or mixed rule sets and dynamically inject it into the page's <head>.
Rules Design & Configuration Architecture
- List Rules vs. Document Rules:
- Document Rules (
where): Strongly preferred over list rules because they are flexible, can be shared across multiple pages, dynamically match links using href and CSS selectors, and support boolean operators (and, or, not).
- List Rules (
urls): A hardcoded array of known URLs. Useful when prefetching/prerendering a fixed set of high-yield destination links.
- Eagerness Levels (
eagerness):
immediate: Speculates as soon as possible upon DOM insertion. Use sparingly for only a tiny number of extremely high-confidence links.
eager: Triggers on slight user signals (e.g., hovering for a short period).
moderate: Triggers on stronger interaction signals (e.g., hovering over a link for ~200ms). Recommended default for prerender rules.
conservative: Triggers on explicit commitment signals (e.g., pointer/mouse button down prior to mouseup).
- Prefetch vs. Prerender Trade-offs & Mixed Rule Sets:
- Prefetch: Conservatively fetches only the main HTML resource. Lower client/server resource consumption; ideal starting point or for lower-confidence links.
- Prerender: Fully renders the page in a background WebContents process (executing HTML, CSS, JS, fonts, and API requests). Higher resource usage but provides instant (~0ms) transitions.
- Mixed Rule Sets: Combine
prefetch at eager eagerness with prerender at moderate eagerness so links are prefetched early on initial hover and upgraded to full prerender when the user continues hovering.
- Server-Side Identification via
tag:
- Assign a
"tag" property either globally or per-rule (e.g., "tag": "pdp-prerender"). The browser includes this tag in the Sec-Speculation-Tags HTTP request header, enabling server-side logging and debugging of speculative requests.
- Chrome 2-Slot FIFO Queue Protection & Exclusions:
- Interaction-based prerender rules (
eager, moderate, conservative) share a strict 2-slot First-In, First-Out (FIFO) queue in Chrome.
- Explicitly exclude low-value links, admin interfaces (
/wp-admin), and state-changing actions (/logout, /add-to-cart) from occupying the queue.
How to Execute Step 2 using chrome-devtools:
Inject a mixed speculation rules script (combining eager prefetch + moderate prerender with server-side tags and exclusions) into document.head using evaluate_script:
chrome-devtools evaluate_script "() => {
const specScript = document.createElement('script');
specScript.id = 'prerender-speculation-rules';
specScript.type = 'speculationrules';
specScript.textContent = JSON.stringify({
prefetch: [
{
tag: 'prefetch-candidate-links',
source: 'document',
where: {
and: [
{ href_matches: '/*' },
{ not: { href_matches: '/wp-admin/*' } },
{ not: { href_matches: '/*\\?*(^|&)add-to-cart=*' } },
{ not: { selector_matches: '.do-not-prerender' } },
{ not: { selector_matches: '[rel~=\x22nofollow\x22]' } }
]
},
eagerness: 'eager'
}
],
prerender: [
{
tag: 'prerender-candidate-links',
source: 'document',
where: {
and: [
{ href_matches: '/*' },
{ not: { href_matches: '/wp-admin/*' } },
{ not: { href_matches: '/*\\?*(^|&)add-to-cart=*' } },
{ not: { selector_matches: '.do-not-prerender' } },
{ not: { selector_matches: '[rel~=\x22nofollow\x22]' } }
]
},
eagerness: 'moderate'
}
]
});
document.head.appendChild(specScript);
return { injected: true, supports: HTMLScriptElement.supports('speculationrules'), html: specScript.outerHTML };
}"
Save the recommended speculation rules JSON snippet as speculation_rules.json inside the ./speculation-rules-analysis/ directory (./speculation-rules-analysis/speculation_rules.json).
Step 3: Trigger Speculation Rules by Hover
Objective
Trigger the injected prerender speculation rules by hovering over candidate links (mouseover / pointerover) to ensure background prerendering is initiated without navigating to or activating the page.
How to Execute Step 3 using chrome-devtools:
chrome-devtools hover "CANDIDATE_LINK_UID"
chrome-devtools evaluate_script "() => {
const targetUrl = 'https://example.com/v/candidate-page';
const link = Array.from(document.querySelectorAll('a')).find(a => a.href === targetUrl);
if (link) {
link.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
link.dispatchEvent(new PointerEvent('pointerover', { bubbles: true }));
link.dispatchEvent(new PointerEvent('pointerenter', { bubbles: true }));
return { triggered: true, targetUrl };
}
return { error: 'Link not found' };
}"
Crucial: Do NOT click or activate the page. Keep the prerendered page strictly in the background.
Step 4: Capture & Differentiate Speculation Network Requests (Raw JSON File)
Objective
List down all network requests generated by the triggered speculation, including all network requests originating from the speculated page context (without activating the page). Differentiate requests made on the speculated page versus the main page, list the raw requests as is, and save them in separate JSON files for each page inside the ./speculation-rules-analysis/ directory named using the slugified page title: <main-page-title>-main.json and <speculated-page-title>-speculated.json (or <speculated-page-title>-speculated-1.json, <speculated-page-title>-speculated-2.json, etc., if multiple speculated pages are evaluated).
STRICT DATA INTEGRITY & ARCHITECTURAL ISOLATION RULES (CRITICAL)
- STRICT DATA INTEGRITY: Rely ONLY on network requests that were actually captured and observed from the triggered speculation.
- ZERO FABRICATION: Do NOT make up, assume, or extrapolate requests that are NOT explicitly present in the recorded network requests log or preload headers for the speculated page context.
- CHROMIUM PRERENDER TARGET ISOLATION & PRESERVED CDP SESSION TRACKING: When a Speculation Rules Prerender (
"prerender") is triggered, network execution occurs in two distinct tiers across separate Chrome DevTools Protocol (CDP) targets:
- Tier A (Top-Level Navigation Fetch): The active main page target records ONLY the initial HTML document navigation requests.
- Tier B (Background Sub-Resource Execution): Upon receiving the HTML response, Chromium spawns an isolated background Prerender WebContents (a separate CDP target/process) to parse the DOM, execute scripts, and download all critical sub-resources (stylesheets, JavaScript bundles, typography fonts, hero images, and data API endpoints).
- STRICT RULE — DO NOT OPEN BACKGROUND TABS: Do NOT open candidate URLs in background tabs (
chrome-devtools new_page <url> --background). All speculative loading must occur strictly via the Speculation Rules API in the background of the active page.
- STRICT RULE — DO NOT THROTTLE CPU DURING PRERENDER CAPTURE: Chromium automatically disables or downgrades full background Prerender WebContents (
"prerender") when CPU throttling (--cpuThrottlingRate > 1) or memory saver mode is active. Always ensure CPU throttling is disabled (--cpuThrottlingRate 1) so full background prerendering and sub-resource execution occurs normally.
- STRICT RULE — DO NOT USE MOBILE EMULATION FOR FULL BACKGROUND PRERENDER CAPTURE: Mobile emulation (
chrome-devtools emulate --viewport ...) causes Chromium to downgrade interaction-based prerenders ("prerender") to prefetches ("prefetch"), downloading only the top-level HTML document. When capturing full background sub-resource execution (including third-party ad conversion and telemetry scripts), perform the capture without mobile emulation (chrome-devtools new_page <url> + chrome-devtools take_snapshot).
- HOW TO READ AND LOG REQUESTS MADE IN THE BACKGROUND (STRICTLY UNACTIVATED CAPTURE):
- Do NOT navigate to or activate the candidate link (
chrome-devtools navigate_page must NEVER be called to capture network requests).
- Trigger the speculation rule on the main page via hover (
chrome-devtools hover <uid> or evaluate_script), wait ~8 seconds for background execution, and run chrome-devtools list_network_requests --pageSize 2000 --includePreservedRequests=true --output-format json > ./speculation-rules-analysis/after_hover_no_activation.json while remaining strictly on the main page. All requests with new request IDs after the hover trigger represent background speculation requests executed without activation.
- CRITICAL RULE — AVOID NAIVE URL SUBSTRING MATCHING: When classifying requests into
main_page vs speculated_page, do NOT rely on naive URL substring matching (e.g., checking if the item ID or pathname is in the URL). Sub-resources (such as CDN images, and API calls) do NOT contain candidate item IDs in their URL strings. Relying on simple URL substrings will misclassify all speculated sub-resources as main page requests!
- SEPARATE REQUESTS JSON FILES PER PAGE WITH PAGE TITLE IN FILENAME: Instead of mixing all requests into a single file, split and export them into separate JSON files inside the
./speculation-rules-analysis/ directory (./speculation-rules-analysis/), including the slugified/kebab-case page title in the file name:
<main-page-title>-main.json — All network requests belonging to the main page context (context: "main_page"). Use the slugified page title of the main page (e.g., marktplaats-de-plek-om-nieuwe-en-tweedehands-spullen-te-kopen-en-verkopen-main.json).
<speculated-page-title>-speculated.json (or <speculated-page-title>-speculated-<n>.json) — All network requests belonging to each speculated page context (context: "speculated_page_unactivated_background"). Use the slugified page title of the speculated page (e.g., puma-rebound-joy-sneakers-zwart-wit-en-grijs-speculated.json).
How to Execute Step 4 using chrome-devtools:
To capture background speculation network requests strictly without activating the page:
chrome-devtools list_network_requests --pageSize 1000 --includePreservedRequests=true --output-format json > ./speculation-rules-analysis/before_hover.json
chrome-devtools hover "CANDIDATE_LINK_UID_1"
chrome-devtools list_network_requests --pageSize 2000 --includePreservedRequests=true --output-format json > ./speculation-rules-analysis/after_hover_no_activation.json
How to Verify, Classify & Split Speculated Sub-Resources in Python:
Use Python to parse the captured JSON log (./speculation-rules-analysis/after_hover_no_activation.json) and split requests into separate JSON files per page (<page-title>-main.json and <page-title>-speculated.json):
- Tier A Identification: Locate the initial navigation requests matching candidate URLs. Inspect HTTP request headers for the
Sec-Speculation-Tags header to confirm server-side tag attribution if "tag" was configured in the rule set.
- Background Speculation Verification:
- Filter requests by request ID (
requestId not in before_ids) to identify background speculation network requests executed upon hover.
- Verify ad conversion pings, floodlight tags, telemetry beacons, subresources, and prefetch/prerender navigation requests fired during unactivated background speculation.
- Save Separate Output Files: Export main page requests to
<page-title>-main.json and each speculated page's requests containing all unactivated background-executed requests to <page-title>-speculated.json (or <page-title>-speculated-1.json, <page-title>-speculated-2.json).
Step 5: Evidence-Based Deferral & Activation Hold-Back Analysis
Objective
Analyze the network requests for the speculated page, list down the specific network requests which should be held back or deferred until the user actually navigates to/activates the page (prerenderingchange), and explain why.
STRICT EVIDENCE-BASED DEFERRAL RULES
- Base deferral recommendations strictly on requests actually observed or verified in the speculation network trace and preload headers from Step 4 (
context: "speculated_page").
- CRITICAL RULE — ONLY REPORT DEFERRALS FOR SCRIPTS ACTUALLY REQUESTED ON THE SPECULATED PAGE: Do NOT list ad scripts, header bidding wrappers, analytics beacons, or telemetry scripts as "requests to be deferred on the speculated page" if those scripts were NOT actually requested on the speculated page (
context: "speculated_page"). NEVER copy ad or analytics requests from the main page (context: "main_page") and list them as scripts to be deferred on the speculated page.
- ZERO DEFERRED SCRIPTS WHEN 0 AD SCRIPTS ARE REQUESTED: If zero ad scripts or analytics tags were requested on the speculated page, explicitly document that 0 ad scripts/analytics scripts were requested on the speculated page and therefore 0 scripts require deferral.
- Clearly distinguish between resources that SHOULD be pre-downloaded during speculation (to achieve ~0ms LCP transitions) versus requests that MUST be held back until activation (only if present on the speculated page).
- What to Pre-Download During Speculation:
- Critical layout and styling: category stylesheets.
- Application runtime: Core UI scripts and React frameworks.
- Visual fidelity: Web typography fonts and primary LCP hero images.
- What MUST be Held Back Until Activation (ONLY IF OBSERVED ON SPECULATED PAGE):
- Advertising & Monetization Scripts: Ad tags, header bidding wrappers, and publisher tags (e.g. Criteo, OpenX, PubMatic, ID5 sync) must be held back until
prerenderingchange resolves. If executed during background speculation, ad slots request false impressions that inflate impression counts, destroy click-through rates (CTR), degrade eCPM, and violate IAB/ActiveView viewability standards.
- Analytics & Session Telemetry: User session tracking and analytics beacons (e.g., Clarity, LinkedIn Insight, Snapchat, BrandMetrics, UserZoom, internal display metrics) must be held back to prevent recording false pageviews and distorting user conversion funnels.
- Heavy Dynamic API Calls: Personalized recommendation feeds, live bidding sockets, or user-specific targeting queries should be delayed until activation to conserve server bandwidth and avoid unnecessary backend compute.
Implementation Patterns (JavaScript Activation Hold-Back)
Save implementation patterns in activation_holdback.js inside the ./speculation-rules-analysis/ directory (./speculation-rules-analysis/activation_holdback.js):
const whenActivated = new Promise((resolve) => {
if (document.prerendering) {
document.addEventListener('prerenderingchange', () => resolve(), { once: true });
} else {
resolve();
}
});
async function loadDeferredScript(src) {
await whenActivated;
const script = document.createElement('script');
script.src = src;
script.async = true;
document.head.appendChild(script);
}
function injectDynamicPrerenderRules(highYieldUrls) {
const existing = document.getElementById('adtech-prerender-rules');
if (existing) existing.remove();
const rules = {
"prerender": [
{
"source": "list",
"urls": highYieldUrls,
"eagerness": "eager"
}
]
};
const script = document.createElement('script');
script.id = 'adtech-prerender-rules';
script.type = 'speculationrules';
script.textContent = JSON.stringify(rules);
document.head.appendChild(script);
}
const HIGH_VALUE_PATTERNS = [/\/v\//, /\/vip\//];
document.addEventListener('mouseover', (event) => {
const link = event.target.closest('a');
if (!link) return;
try {
const url = new URL(link.href);
if (url.origin === window.location.origin) {
const isHighValue = HIGH_VALUE_PATTERNS.some(p => p.test(url.pathname));
if (!isHighValue && !link.hasAttribute('rel')) {
link.setAttribute('rel', 'nofollow');
}
}
} catch (e) {}
});
Speculation Rules Best Practices & Browser Fallbacks
Best Practices Summary
- DO use speculation rules to prefetch and prerender pages that the user is likely to visit next.
- DO use speculation rules for static sites where content changes infrequently and pages are cheap to produce—especially when cached at the edge CDN.
- DO exercise care when using speculation rules for dynamic pages, where content changes frequently or pages are computationally expensive to serve.
- DO prefer document rules (
where) over list rules (urls), as they are more flexible, allow shared rules across multiple pages, and automatically match dynamic page elements.
- DO consider the trade-offs between
prefetch (lightweight resource usage) and prerender (instant page transitions but higher resource consumption). Ask the developer for their preference if unsure.
- DO consider the trade-offs between the different
eagerness levels (immediate, eager, moderate, conservative), or combine them in a mixed rule set to prefetch eagerly and upgrade to prerendering on stronger signals.
- DO NOT overuse speculation rules (e.g., speculating every link on a page). Respect browser speculation limits (2 concurrent non-eager speculations) and reserve
immediate for rare, exceptionally high-confidence cases.
- DO NOT speculate URLs that trigger state changes (like
/logout, /add-to-cart, or /checkout) and explicitly exclude them using "not" clauses in document rules.
- DO NOT use speculation rules on Single Page Applications (SPAs). Speculation rules rely on full-document MPAs.
Browser Support & Progressive Enhancement
- Speculative loading is a modern web standard with Baseline limited availability.
- Always treat speculative loading as a progressive enhancement. Unsupporting browsers simply ignore
<script type="speculationrules"> blocks safely without JavaScript errors or broken navigation. Feature-test dynamically in JavaScript via HTMLScriptElement.supports('speculationrules').
Required Output Artifacts (All Created ONLY in ./speculation-rules-analysis/ Directory)
Upon completing the 5 steps, ensure the following files exist in ONLY the folder (./speculation-rules-analysis) under the current working directory (do NOT create them directly in ./):
<main-page-title>-main.json — Complete raw network requests log for the main page context (context: "main_page"), named using the slugified title of the main page.
<speculated-page-title>-speculated.json (or <speculated-page-title>-speculated-1.json, etc.) — Complete raw network requests log for each speculated page context (context: "speculated_page"), named using the slugified title of the speculated page.
speculation_rules.json — Recommended Speculation Rules API JSON configuration snippet for prerendering.
activation_holdback.js — JavaScript activation hold-back script, dynamic yield prerender rules, and FIFO queue protection filter.
speculation_rules_analysis_report.md — Comprehensive analysis report documenting candidate selection, injected rules, trigger verification, network request breakdown, and evidence-based deferral analysis.