Ch 6 — Rendering & JavaScript¶
Part III — The render layer · The Technical SEO Reference
Playbook coupling:
seo-checklist.mdtouches rendering in four lines — URL Inspection rendered-HTML check (Phase 1, line 99), viewport-entry lazy-loading (Phase 2, line 128), infinite-scroll paginated equivalents (Phase 1, line 89), and rendered-HTML forensics in the hacked-site playbook (line 226). This chapter supplies the machinery underneath: the two-queue pipeline, the WRS behavioral contract, the byte budget, the JS-injection rulebook with its three December 2025 clarifications, framework failure modes, and the debugging workflow.
Google renders essentially every 200-status HTML page it crawls in a headless evergreen Chromium — rendering is not a special lane for "JavaScript sites." What makes JS sites fail is never a blanket inability to render; it is one of a short list of specific, documented mechanisms: state the WRS refuses to hold, interactions it refuses to perform, bytes past a cutoff it refuses to read, resources it cannot fetch, and directives that stop rendering before it starts. This chapter is that list.
6.1 The pipeline: crawl → render → index¶
🟢 "Google processes JavaScript web apps in three main phases: Crawling, Rendering, Indexing," with two queues — "Googlebot queues pages for both crawling and rendering" — JavaScript SEO basics (last updated 2026-03-04).
The mechanics, all 🟢 from the same doc plus the Crawling December: resources post (Dec 3, 2024):
- Crawl. Googlebot fetches the URL (robots.txt permitting) and "parses the response for other URLs in the href attribute of HTML links and adds the URLs to the crawl queue." Link discovery pass #1 runs on raw HTML, before any rendering.
- Hand-off. "Googlebot passes on the fetched data to the Web Rendering Service (WRS). Using Googlebot, WRS downloads the resources referenced in the original data. WRS constructs the page using all the downloaded resources as a user's browser would." Resource fetches during rendering ARE Googlebot crawls — they appear in your logs and Crawl Stats (→ Ch 2 §2.8).
- Render. "Once Google's resources allow, a headless Chromium renders the page and executes the JavaScript. Googlebot parses the rendered HTML for links again" — link discovery pass #2 — "and Google also uses the rendered HTML to index the page."
⚠️ Who gets rendered — and the two documented skips. 🟢 "All pages with a 200 HTTP status code are sent to the rendering queue, no matter whether JavaScript is present on the page" (clarified Dec 18, 2025). The two ways out: - Non-200 status: "If the HTTP status code is non-200 (for example, on error pages with 404 status code), rendering might be skipped" — so JavaScript that runs on error pages (client-side redirects on a 404 shell, injected content) may never execute for Google. - noindex in the crawled HTML: Googlebot queues 200-pages for rendering "unless a robots meta tag or header tells Google not to index the page" — the noindex-skips-rendering interlock, whose consequences live in §6.7 and Ch 7.
🟢 Google's own framing of what Googlebot is (Mar 31, 2026, "Inside Googlebot"): "Googlebot is just a user of something that resembles a centralized crawling platform. When you see Googlebot in your server logs, you are just looking at Google Search."
6.2 The WRS behavioral contract¶
What the Web Rendering Service will and will not do — each line load-bearing for a failure mode:
- 🟢 Evergreen Chromium. "Google Search runs JavaScript with an evergreen version of Chromium"; the UA's Chrome token "increases over time to match the latest Chromium release version used by Googlebot" (common crawlers doc). The "Googlebot is Chrome 41" era ended in 2019 — modern APIs are generally available, but ⚠️ Google still says it "has some limitations regarding which APIs and JavaScript features it supports" and prescribes feature detection with fallbacks for every critical API.
- 🟢 Stateless. "WRS does not retain state across page loads: Local Storage and Session Storage data are cleared across page loads. HTTP Cookies are cleared across page loads" (fix-search-javascript, last updated 2025-12-18); reaffirmed 2026: "the WRS operates statelessly — it clears local storage and session data between requests." Anything gated on returning-visitor state renders as the no-state variant. This is the mechanism behind the CMP failure in §6.12.
- 🟢 No interaction. "Google Search does not interact with your page" (lazy-loading doc); crawlers "don't 'click' buttons and generally don't trigger JavaScript functions that require user actions" (pagination doc). No scrolls, no clicks, no hovers — ever.
- 🟢 Permissions declined. "Expect Googlebot to decline user permission requests… if you make the Camera API required, Googlebot can't provide a camera."
- 🟢 HTTP only. "It does not support other types of connections, such as WebSockets or WebRTC connections… make sure to provide an HTTP fallback."
- 🟢 No media fetches during render. "Rendering pulls in and executes JavaScript and CSS files, and processes XHR requests… (it doesn't request images or videos)" (Inside Googlebot, 2026). Image indexing rides on the
srcattribute in rendered HTML (§6.9), not on the render fetching pixels. - 🟢 Blocked resources break rendering. "If WRS cannot fetch a rendering-critical resource, Google Search may have trouble extracting content of the page and allowing the page to rank in Search" — the modern form of the 2015 don't-block-JS/CSS rule (→ Ch 3 for the robots.txt side).
- ⚪ Service workers: officially unanswered. Google's statelessness list names Local Storage, Session Storage, and HTTP Cookies only; no current doc states whether WRS executes service workers. 🟡 The only known statement is Martin Splitt's July 2020 r/TechSEO Reddit AMA answer of "no plans" to support them. The book treats service-worker-delivered content as not indexable until Google says otherwise — serve critical content without depending on one.
6.3 The byte budget: 2MB, and where your tags must live¶
The March 2026 "Inside Googlebot" post plus the Feb 3, 2026 Googlebot doc update replaced the long-cited 15MB figure (→ Ch 2 §2.2 for the full fetch-limit doctrine, its canonical home). What matters for rendering:
- 🟢 "Googlebot currently fetches up to 2MB for any individual URL (excluding PDFs)… including the HTTP header." The first 2MB "is passed along to our indexing systems and the Web Rendering Service (WRS) as if it were the complete file"; bytes past the threshold "aren't fetched, they aren't rendered, and they aren't indexed."
- 🟢 Subresources get their own 2MB counters: "They have their own, separate, per-URL byte counter and don't count towards the size of the parent page."
- 🟢 Google's ordering advice: "Place your most critical elements — like meta tags,
<title>elements,<link>elements, canonicals, and essential structured data — higher up in the HTML document." Named risk patterns: "bloated inline base64 images, massive blocks of inline CSS/JavaScript, or starts with megabytes of menus." - ⚠️ A truncated file is not an error — it is silently processed as complete. A canonical or JSON-LD block sitting after 2MB of inlined framework CSS simply does not exist to Google, and nothing in GSC flags it. Diagnosis: compare raw source size to 2MB; check whether tail-of-file tags appear in URL Inspection's crawled HTML.
6.4 WRS caching and the economics of rendering¶
- 🟢 "WRS attempts to cache every resource (JavaScript and CSS) referenced in pages it renders. The time to live of the WRS cache is unaffected by HTTP caching directives; instead WRS caches everything for up to 30 days" (Crawling December, 2024). Also in the docs: "Googlebot caches aggressively… WRS may ignore caching headers. This may lead WRS to use outdated JavaScript or CSS resources."
- ⚠️ Consequence: a deployed JS bugfix can keep rendering with the stale bundle for weeks.
Cache-Controlwill not save you. 🟢 The sanctioned fix is content fingerprinting: "making a fingerprint of the content part of the filename, likemain.2bb85551.js… updates generate a different filename every time." - 🟢 Resource fetches bill the resource's host: "Crawling the resources needed to render a page will chip away from the crawl budget of the hostname that's hosting the resource." Fewer resources = less render-time crawl spend.
- ⚠️ The CDN-offload trick was amended within days of publication (Dec 6, 2024): moving critical JS/CSS to another hostname shifts crawl budget there but "can result in slower page performance due to the overhead of connection to a different hostname, so we don't recommend this strategy for critical resources." Fine for large non-critical media. (→ Ch 4 for CDN crawl mechanics.)
- 🟢 "Use cache-busting parameters cautiously: if the URLs of resources change, Google may need to crawl the resources again, even if their contents haven't changed."
6.5 The render queue: how long it really takes¶
- 🟢 The only documented duration: "The page may stay on this queue for a few seconds, but it can take longer than that."
- 🟢 (recorded statement, Chrome Dev Summit 2019) Martin Splitt, in "How to make your content shine on Google Search" (official Chrome for Developers YouTube recording): "at median, the time we spent between crawling and actually having rendered these results is – on median – it's five seconds!", with the 90th percentile "in minutes" (transcription via Onely, Nov 26, 2019). A 2019 operational figure about queue wait, not a spec and not a timeout.
- 🟢 (recorded statement, Search Off the Record, Aug 25, 2020, official transcript) Splitt on the "two waves of indexing": "I really try to like phase out this metaphor, but it keeps coming back at me… basically that's nearly a hundred percent of the cases, your website gets crawled and it gets rendered and then it gets indexed." The two-waves model is retired — stop planning around it.
- ⚪ Measurement, not doctrine: the MERJ/Vercel study (Apr 2024 data, 100,000+ Googlebot fetches, 37,000+ matched pairs, primarily nextjs.org — a fast, well-configured Next.js property) found 100% of HTML pages fully rendered; render-delay percentiles 25th = 4s, median = 10s, 75th = 26s, 90th ≈ 3 hours, 99th ≈ 18 hours. Scope caveat: one modern site's numbers, not the web's.
- ⚠️ The "5-second rendering timeout" is lore — a mangled version of Splitt's median-queue-wait figure. No render timeout is documented anywhere. Nor is a "rendering budget": the documented costs are crawl-budget costs of resource fetches (§6.4).
- 🟢 Google's own hedge stands: "server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript." Google renders; ClaudeBot, GPTBot and most AI crawlers do not (→ Ch 5 §5.6) — a client-rendered site is invisible to the non-rendering half of the crawler ecosystem.
6.6 SPAs and routing¶
- 🟢 "For single-page applications with client-side routing, use the History API to implement routing… don't use fragments to load different page content." Google's own bad-practice example is
<a href="#/products">— "Googlebot can't reliably resolve the URLs." Fragment routes do not create indexable URLs. - 🟢 The AJAX-crawling era is formally dead (Oct 14, 2015): "We are no longer recommending the AJAX crawling proposal we made back in 2009";
_escaped_fragment_is gone and "we'll generally crawl, render, and index the #! URLs" as-is. 📘 The History API (pushState) is a WHATWG HTML Standard feature. - ⚠️ SPA soft 404s. Client-routed error views return 200 and get indexed as real pages. 🟢 The two sanctioned fixes (fix-search-javascript): "Redirect to a URL where the server responds with a 404 status code," or "Add or change the robots meta tag to noindex" via JS. Underlying rule: "use a meaningful status code, like a 404 for a page that could not be found or a 401 code for pages behind a login." (Status-code semantics → Ch 2 §2.3.)
6.7 The JS-injection rulebook¶
What Google honors when JavaScript writes or rewrites page elements — sharpened by three December 2025 clarifications:
| Element | Injectable? | The rules |
|---|---|---|
rel=canonical |
Yes, discouraged | 🟢 "Google Search will pick up the injected canonical URL when rendering the page" — but (Dec 17, 2025) never use JS to change a canonical already declared in the server HTML; if you must inject, leave it out of the HTML and inject exactly one. "Conflicting or multiple rel=canonical link tags may lead to unexpected results." 🟢 Changelog, Dec 17, 2025: "Canonicalization happens before and after rendering" — both the raw and rendered canonical are read (→ Ch 8). |
| robots meta | Yes — one direction only | 🟢 "You can use JavaScript to add a robots meta tag" — but (Dec 15, 2025) ⚠️ noindex-then-remove does not work: "When Google encounters the noindex tag, it may skip rendering and JavaScript execution… If you do want the page indexed, don't use a noindex tag in the original page code." JS can add restrictions; it cannot reliably lift them. (Rule inventory → Ch 7.) |
| titles / meta description | Yes | 🟢 Documented as processable from the rendered DOM ("Describe your page with unique titles and snippets," basics doc). Generation mechanics → Ch 13. |
| JSON-LD | Yes | 🟢 "Google Search can understand and process structured data that's available in the DOM when it renders the page" (generate SD with JavaScript). ⚠️ GTM injection caveats: "Dynamically-generated markup can make Shopping crawls less frequent and less reliable" and duplicating content in GTM "increases the risk of having a mismatch." (→ Ch 12.) |
data-nosnippet |
No | 🟢 ⚠️ The one control where JS is documented as unsafe: "extraction of data-nosnippet may happen both before and after rendering. To avoid uncertainty from rendering, do not add or remove the data-nosnippet attribute of existing nodes through JavaScript" (robots meta spec). |
| robots meta placement | n/a | 🟢 Forgiving: "Google Search doesn't enforce placement of meta robots in the HTML head and will respect robots meta tags in the body section." |
⚠️ JS-hidden paywalls don't gate content (added Aug 28, 2025): "Some JavaScript paywall solutions include the full content in the server response, then use JavaScript to hide it until subscription status is confirmed. This isn't a reliable way to limit access to the content." Google reads the full response. The sanctioned pattern is server-side gating + paywall structured data (→ Ch 12).
6.8 Crawlable links¶
- 🟢 "Google can only crawl your link if it's an
<a>HTML element… with an href attribute," resolving "into an actual web address (meaning, it resembles a URI)" (links-crawlable). Google's own bad-practice list includes<span href>,<a onclick="goto(...)">, and the Angular-style<a routerLink="products/category">— though "Google may still attempt to parse" non-recommended formats. Framework router components are fine iff they emit real<a href>into the DOM (client-side interception of the click is irrelevant to Googlebot, which doesn't click — it harvests hrefs). - 🟢 Discovery happens twice (§6.1): raw-HTML links enter the crawl queue immediately; JS-injected
<a href>links are discovered from rendered HTML — later, after the queue delay. Navigation that exists only post-render works, but adds the render delay to every discovery hop; deep architectures compound it (→ Ch 10 internal-linking doctrine).
6.9 Lazy loading and infinite scroll¶
- 🟢 Core rule (lazy-loading doc): "make sure that your lazy-loading implementation loads all relevant content whenever it is visible in the viewport." Supported: native browser lazy-loading (📘 the
loadingattribute is WHATWG-standard), IntersectionObserver + polyfill, or a library doing viewport-entry loading. Why: "The methods mentioned don't rely on user actions, such as scrolling or clicking… as Google Search does not interact with your page." Scroll- and click-triggered loading is invisible. - ⚪ Industry lore claims a specific tall rendering viewport (~12,000px); Google documents no viewport dimensions — treat measured figures as inference.
- 🟢 ⚠️ Images count only via
src: "If your image or video URLs appear in the src attribute on the<img>or<video>elements in the rendered HTML, your setup works correctly" — and per the Apr 16, 2024 changelog, images are only extracted fromimg src. CSS background images and canvas drawings are not indexable images (→ Ch 14). - 🟢 "Don't add lazy-loading to content that is likely to be immediately visible" — the LCP-image rule the playbook already carries (Phase 2, line 128).
- 🟢 Infinite scroll needs paginated equivalents: "Give each chunk its own persistent, unique URL" (
?page=n— "URLs in a paginated sequence are treated as separate pages"), update the address bar via the History API, avoid relative-state URLs like?date=yesterday, sequential<a href>links between pages; rel=next/prev: "Google no longer uses these tags." Pagination architecture → Ch 10 §10.6; self-canonical rule → Ch 8.
6.10 Choosing a rendering architecture¶
From web.dev/rendering-on-the-web (updated 2026-01-05), all 🟢:
- SSR — "Rendering an app on the server to send HTML, rather than JavaScript, to the client." Fast FCP; "generating pages on the server takes time, which can increase your page's TTFB."
- Static / prerendering (SSG) — "Running a client-side application at build time to capture its initial state as static HTML." "A fast FCP, and also a lower TBT and INP… a consistently fast TTFB."
- CSR — "Rendering an app in a browser, using JavaScript to modify the DOM." "The amount of JavaScript required tends to grow as an application grows, which can impact a page's INP."
- Hydration — "Running client-side scripts to add application state and interactivity to server-rendered HTML." ⚠️ "Can have a significant negative impact on TBT and INP, even if it improves FCP."
- 🟢 Google's recommendation: "we encourage developers to consider server-side rendering or static rendering over a full rehydration approach"; SSR is "a popular choice for delivering a 'complete looking' experience that crawlers can interpret."
⚠️ Dynamic rendering is deprecated as a recommendation (dynamic-rendering doc): "Dynamic rendering was a workaround and not a long-term solution… we recommend that you use server-side rendering, static rendering, or hydration as a solution." Anyone still selling Rendertron/Prerender.io-style bot detection as "Google's recommended JS SEO fix" is a documentation decade behind. The cloaking boundary survives it: 🟢 "As long as your dynamic rendering produces similar content, Googlebot won't view dynamic rendering as cloaking… a website that serves a page about cats to users and a page about dogs to crawlers is cloaking" — and the 2015 parity rule: prerendered content must match "the user's experience, both how it looks and how it interacts."
6.11 Framework failure modes (⚪ — vendor-mechanics, Google is silent)¶
Google's docs are framework-agnostic; these recurring failure patterns are ⚪ industry/vendor mechanics mapped onto the 🟢 rules above:
- Hydration mismatch. Server HTML and client render disagree (locale/date/random content, browser-only branches); React discards or patches the server DOM. SEO risk is indirect but real: the crawled raw HTML (link-discovery pass #1, pre-render canonical read) differs from what the code intended, and error-recovery re-renders burn INP. Rule of thumb: anything SEO-critical (title, canonical, robots, links, primary content) must be identical server-side and post-hydration — the §6.7 conflict rules assume one consistent document.
- ISR/stale regeneration (Next.js Incremental Static Regeneration and equivalents). Stale-while-revalidate serving means Googlebot can receive the stale copy while users get fresh — usually harmless, but on fast-changing money data (price, availability) it desynchronizes page content from structured data feeds (→ Ch 12 GTM/Shopping caveat, same failure class). Keep
revalidatewindows shorter than your data's change cadence for indexable commerce pages. - App Router metadata (Next.js
metadataAPI and equivalents). Metadata rendered only through client components can end up absent from server HTML. All of §6.7's "injectable" allowances still carry the render delay — emit titles/canonicals/robots in the server response; framework metadata APIs that render server-side do this correctly by default. - Streaming SSR / React Server Components. Content arrives in chunks within one HTTP response — fine for Google (one URL, one 200, complete HTML at end of stream), but the 2MB counter (§6.3) applies to the streamed total, and error boundaries that swallow server errors into 200-status fallback shells create soft 404s at scale (§6.6 rules apply).
- Service-worker-dependent apps — see the open question in §6.2; do not gate content on one.
6.12 Consent banners and CMPs: the European failure signature (⚪ synthesis on 🟢 anchors)¶
Three verified facts combine into the most common EU rendering failure: 1. 🟢 WRS is stateless — no cookies, no stored consent (§6.2). 2. 🟢 Google crawls primarily from US IPs (→ Ch 2 §2.1) — geo-triggered consent flows fire or don't fire accordingly. 3. 🟢 Interstitial rules: overlays that obscure content "make it hard for Google… to understand your content" (→ Ch 15; playbook Phase 1, line 108).
⚪ The failure: a CMP that blanks or replaces page content until consent renders, for Googlebot, as a page containing only the consent dialog — every load, forever, since consent can never be stored. Diagnosis signature: URL Inspection screenshot shows the cookie wall; rendered HTML is template-only; the page drifts to "Crawled – currently not indexed" or thin-content quality loss. The compliant pattern: content renders regardless of consent state; the CMP gates tags/storage (that is what consent regulates), not the article text; no consent-conditional <body> swaps. Label any vendor's "SEO-safe CMP" claim ⚪ and verify with the URL Inspection live test.
6.13 Iframes and embedded content¶
Google's iframe documentation is sparse; label discipline matters here.
- 🟢 What exists officially: indexifembedded lets an iframe-source page that is itself noindexed be indexed as part of the embedding page (→ Ch 7 §7.6 for the full mechanics — that is its canonical home).
- 🟡 The embedder-side question — "does iframe content count as my page's content?" — has no current doc. Historic informal guidance (Mueller, various office hours): Google may sometimes flatten iframe content into the embedding page but it is unreliable and not guaranteed. Treat iframe'd content as not yours: anything that must rank on your URL belongs in your DOM.
- ⚪ Lazy-loaded iframes (loading=lazy on <iframe>, natively supported) follow §6.9's viewport rule for the embed itself; the iframe's content indexability still belongs to its source URL.
6.14 Debugging rendering¶
- 🟢 Official entry point: "To test how Google crawls and renders a URL, use the Rich Results Test or the URL Inspection Tool in Search Console. You can see loaded resources, JavaScript console output and exceptions, rendered DOM, and more information" (fix-search-javascript). The Rich Results Test is the public (no-property-needed) renderer.
- ⚠️ Know what each URL Inspection view shows (help doc). The indexed-version view reflects "the most recently indexed version of a page, not the live version"; the live test fetches in real time via Google-InspectionTool. The "View crawled page" panel shows the raw HTML returned, the HTTP headers, JavaScript console output, and any page resources loaded — Google never calls this panel rendered HTML; the rendered result is the screenshot ("a screenshot of the rendered page as the Google-InspectionTool sees it"). Verify content presence by searching the crawled-HTML panel and checking the screenshot — a JS-injected element appears in the DOM/screenshot but not in the raw-HTML panel, and that difference is itself diagnostic.
- 🟢 A passing live test is not an indexing promise: "Does a valid result mean that my page will be indexed? No." The live test skips duplicate/canonical selection and quality gates.
- 🟢 Google also recommends field JS-error collection: "collecting and auditing JavaScript errors encountered by users, including Googlebot, on your site."
- ⚠️ Retired tools: the Mobile-Friendly Test, its API, and the Mobile Usability report shut down December 2023; the old help URL 301s to Lighthouse docs. Any workflow citing them is outdated (→ Ch 15 for what mobile-parity checking looks like now).
- Workflow: (1) live test the URL → screenshot sane? (2) crawled HTML: is the critical content/tag in the raw response, or JS-only? (3) console output: framework errors, failed API calls? (4) resources: anything critical blocked by robots.txt or erroring? (5) if raw-only content is fine but indexing lags — it's the queue, not a failure; give it days, not hours, before diagnosing further (→ Ch 21).
Symptoms & diagnosis¶
| Symptom | Likely cause | Where |
|---|---|---|
| Content visible in browser, missing from Google's index | Click/scroll-triggered loading; content only via WebSocket; service-worker-dependent | §6.2, §6.9 |
| Page indexed but JS-injected sections absent | Render skipped (noindex in raw HTML; non-200) or queue delay | §6.1, §6.7 |
| Deployed JS fix; Google still renders old behavior weeks later | WRS 30-day cache ignoring HTTP cache headers; un-fingerprinted bundles | §6.4 |
| Tags at end of large HTML ignored (canonical, JSON-LD) | Past the 2MB cutoff, silently truncated | §6.3 |
| SPA error pages flooding the index / "Soft 404" statuses in GSC | Client-routed error views returning 200 | §6.6 |
| EU pages thin/deindexed; URL Inspection screenshot shows cookie wall | CMP blanking content for stateless US-IP Googlebot | §6.12 |
| Category pages indexed; nothing beyond page 1 discovered | Load-more without paginated URLs; router links without <a href> |
§6.8, §6.9 |
| Canonical flapping between URLs on a JS site | Conflicting raw-vs-rendered canonicals (canonicalization runs before AND after rendering) | §6.7, Ch 8 |
| Images on JS pages absent from Google Images | Image URLs never land in rendered img src |
§6.9, Ch 14 |
| Rankings fine on Google, invisible to AI assistants | Client-side rendering; most AI crawlers don't render | §6.5, Ch 5 |
Sources¶
All fetched 2026-08-04 (research corpus, verbatim-verified against raw HTML except where noted; V2 re-fetches all): - Understand the JavaScript SEO basics (last updated 2026-03-04) - Fix search-related JavaScript problems (2025-12-18) - Fix lazy-loaded content (2025-12-10) - Dynamic rendering as a workaround (2025-12-10) - Inside Googlebot: demystifying crawling, fetching, and the bytes we process (2026-03-31) - Crawling December: The how and why of Googlebot crawling (2024-12-03, amended 12-06) - Pagination, incremental page loading, and Search (2025-12-10) - Generate structured data with JavaScript (2025-12-10) - SEO best practices for links (2025-12-10) - Robots meta tag, data-nosnippet, and X-Robots-Tag specifications (2026-03-24) - What is Googlebot (2026-02-03) - In-depth guide to how Google Search works (2025-12-18) - URL Inspection tool help (no revision date shown; wording per V0 re-verification 2026-08-04) - Rendering on the web — web.dev (2026-01-05) - Deprecating our AJAX crawling scheme (2015-10-14) - Recorded statements (V0-verified primaries): Splitt, Chrome Dev Summit 2019 (YouTube 4pOH8Smd0Xs; Onely transcription); Splitt, Search Off the Record Aug 25, 2020 (official transcript); Splitt, r/TechSEO AMA Jul 2020 (service workers) - ⚪ MERJ/Vercel, "How Google handles JavaScript throughout the indexing process" (vercel.com/blog, Jul 31, 2024)