MENU
10. Search Engine Optimization
Many decisions that determine whether a page is found are made by front-end developers: which HTML is served, how links are marked up, whether content needs JavaScript, how fast the page loads and what metadata travels with it.Search engine optimization (SEO) is full of folklore, so this chapter says whether each factor is confirmed by the search engines, denied or simply unknown.The chapter starts with the machinery of crawling, ranking and AI answers, then works through the classic factor families (domain, page, backlinks, navigation and brand), SEO tools and microformats. It closes with technical SEO for JavaScript sites and generative engine optimization. Meta tags, JSON-LD, sitemaps and robots.txt (Section 2.11) and Core Web Vitals (Section 9.10) are not repeated.What you will learn:How crawling, rendering, indexing and ranking work at Google and Bing
Which ranking factors are confirmed, which are myths, and which are unknown
How links, duplicates, translations and redirects affect a site
Which SEO tools, microformats and structured data formats to use
How to make JavaScript sites visible to search engines and AI assistants
10.1 How Search Engines Work
Every web search engine discovers URLs, fetches and renders them, stores what it understood in an index, and ranks indexed pages for each query. Google and Bing now also write AI answers that cite some of those pages. Knowing where a page can drop out of this pipeline is the most useful SEO skill a developer can have.10.1.1 Crawling, Rendering and Indexing
Google describes Search as crawling, indexing and serving, with a rendering phase for JavaScript between crawling and indexing. Figure 10.1 shows the pipeline and where pages drop out.
Figure 10.1: The crawl, render, index and serve pipeline, and where
pages drop outDiscovery and crawling. Crawlers find URLs in links
on known pages, in sitemaps (Section 2.11.4) and in their crawl history.
Google only discovers links written as <a href>; a <span
onclick> that sets location is invisible to it. Bing, Yandex, Naver,
Seznam.cz and Yep also accept IndexNow pings, which share a changed URL
with every participating engine; Google is not listed as a participant.
The crawler reads robots.txt first. Most Google fetches come from
Googlebot Smartphone, because Google indexes the mobile
version of a site; Googlebot reads only the first 2 MB of an HTML, CSS
or JavaScript file (64 MB for PDFs).Rendering. Google renders with an evergreen
(regularly updated) Chromium, and Bingbot has rendered with Microsoft
Edge's engine since Bing's 2019 announcement. A fetched page waits in a
render queue "for a few seconds, but it can take longer than that". If
the initial HTML contains noindex or the status is not 200, Google may
skip rendering altogether, so a script that later removes noindex never
runs. Section 10.9.2 covers JavaScript rendering in depth.Indexing. The indexer extracts text, links and
structured data, groups near-duplicates into a cluster and picks one
canonical URL for it (Section 10.3.15). Google doesn't
guarantee that any page will be crawled, indexed or served.10.1.2 Ranking Systems: PageRank to Helpful Content and E-E-A-T
Google's founding idea, in Sergey Brin and Lawrence Page's 1998 paper "The Anatomy of a Large-Scale Hypertextual Web Search Engine", was to treat a link as a vote weighted by the importance of the page casting it. PageRank models a "random surfer" who follows links and, with probability 1 - d, jumps to a random page; the paper usually set the damping factor d to 0.85. Listing 10.1 computes it for four pages.const links = { A: ['B', 'C'], B: ['C'], C: ['A'], D: ['C'] };
const n = 4, d = 0.85;
let pr = { A: 1 / n, B: 1 / n, C: 1 / n, D: 1 / n };
for (let i = 0; i < 50; i++) {
const next = { A: (1 - d) / n, B: (1 - d) / n, C: (1 - d) / n, D: (1 - d) / n };
for (const [from, outs] of Object.entries(links)) {
for (const to of outs) next[to] += (d * pr[from]) / outs.length;
}
pr = next;
}
console.log(Object.entries(pr).map(([p, v]) => `${p}=${v.toFixed(3)}`).join(' '));
10.1.3 AI Overviews, AI Mode and Answer Engines
An answer engine replies with generated prose that cites web pages, instead of only a list of links. Google runs two such features on its index:AI Overviews, an AI-written summary above the results, rolled out to all US users in May 2024 and reached more than 200 countries and territories by May 2025. Google reported over 2.5 billion monthly active users in May 2026.
AI Mode, a conversational search for comparisons and multi-step questions, started as a Labs experiment in March 2025 and expanded to over 200 countries and territories in October 2025. It passed 1 billion monthly active users by May 2026, and in July 2026 Google said it had brought AI Overviews and AI Mode "together into one seamless Search experience".
<meta name="robots" content="max-snippet:160">
<p>Our review covers battery life, price and repairability.</p>
<div data-nosnippet>Subscriber-only benchmark tables and conclusions.</div>
10.1.4 Market Share
Worldwide, Google sends roughly nine in ten search visits, but national markets differ. Table 10.2 uses StatCounter, which counts clicks from search engines to the sites running its tracker, not the queries themselves.10.2 Domain Factors
Domain factors describe a whole site: its name, history, hosting, uptime and security. Google's ranking systems "work on the page level", but "site-wide signals and classifiers are also used." Much domain folklore comes from patents and correlation studies rather than Google's documentation, so the table sorts each factor by what Google Search Central says today.10.2.1 Age
A 2003 Google patent, "Information retrieval based on historical data" (US 7,346,839), describes scoring a document by its "inception date", possibly the date its domain was registered. A patent shows what Google invented, not what it runs, and no Search Central page lists domain age: it is unconfirmed. Age mostly stands in for the content and links a site has had time to earn.Buying an old domain for its history can backfire: Google's expired domain abuse policy targets expired domains "repurposed primarily to manipulate search rankings". Check a used domain's past in the Wayback Machine (web.archive.org (https://web.archive.org/)) first.10.2.2 Name
Google counts "the words in domain names as one of many factors", but its exact match domain system stops names like best-places-to-eat-lunch.com from getting "too much credit". The SEO Starter Guide says such keywords "alone have hardly any effect beyond appearing in breadcrumbs", and that Google "doesn't care which TLD you're using" unless you target one country. Choose a short, memorable brand people will search for by name (Section 10.6.4).10.2.3 Ownership
The same patent notes that legitimate domains "are often paid for several years in advance, while doorway (illegitimate) domains rarely are used for more than a year." Registration length, WHOIS privacy and ownership changes remain unconfirmed. What Google does confirm is the site reputation abuse policy against third-party pages placed on a site "mainly because of that host's already-established ranking signals". Hosting guest content is fine; renting out your domain's standing is not.10.2.4 Geolocation
To find a page's target country, Google weighs a country-code TLD such as .de ("a strong signal"; vanity ccTLDs like .tv and .me count as generic), hreflang (Section 10.3.11), server location ("not a definitive signal", given CDNs), and local addresses, currency and links. It "ignores locational meta tags (like geo.position...)". Pick a ccTLD only for a single-country business, and never redirect by IP address: most Googlebot crawls come from the US, so it would see only one version.10.2.5 Authority and TrustRank
TrustRank comes from a 2004 Stanford and Yahoo! paper, "Combating Web Spam with TrustRank": humans label a seed set of trusted pages and trust flows outward along links. Google holds a patent titled "Search result ranking based on trust" (US 7,603,350), but nothing shows it runs a TrustRank score: unconfirmed. "Domain Authority" (a 1-100 score from Moz) and similar vendor metrics are estimates that Moz itself says are "not a direct ranking factor". Google confirms link analysis systems, including PageRank (Section 10.1.2), and systems that "surface more authoritative pages". Use vendor scores to compare sites, never as a goal.10.2.6 Site Uptime
Downtime is a confirmed risk. On 5xx or 429 responses Googlebot slows down, and indexed URLs "are preserved in the index, but eventually dropped." Google advises a 503 status for an outage of a day or two, never a 503 for robots.txt (that halts all crawling), and a 200 placeholder page for longer closures.server {
listen 443 ssl; # certificates as in Section 1.6.5
server_name example.com;
root /var/www/maintenance; # holds maintenance.html and robots.txt
add_header Retry-After 7200 always;
error_page 503 /maintenance.html;
location = /robots.txt { try_files $uri =404; }
location = /maintenance.html { internal; }
location / { return 503; }
}
10.2.7 SSL Certificate
In August 2014 Google made HTTPS "a very lightweight signal", "affecting fewer than 1% of global queries." Today's page experience documentation lists secure serving as a good practice but says "beyond Core Web Vitals, other page experience aspects don't directly help your website rank higher": HTTPS is not a direct factor now. Serve it anyway: Chrome has labeled HTTP pages "Not secure" since version 68 (2018), many web APIs need a secure context, and Let's Encrypt is free (Section 1.6.5). When migrating, 301-redirect every HTTP URL to its HTTPS twin.10.2.8 Hacked Site
Hacked content is confirmed harm: affected pages "can appear with a warning label in search results or an interstitial warning page in the browser", and Google may remove a site entirely. On November 30, 2018 even Search Engine Land vanished from Google for over 12 hours when Google's hacked-site detection misfired. After cleaning up, choose Request Review in Search Console's Security issues report. Injected spam is often served only to Google, so check with the URL Inspection tool or a crawler-like request:curl -s -A "Googlebot/2.1 (+http://www.google.com/bot.html)" \
-e "https://www.google.com/" https://example.com/ | grep -icE "casino|viagra|loan"
10.3 Page Factors
Page factors are the part of SEO a front-end developer controls directly: markup, URLs, words, speed, links and layout. Google's How Search Works site states the simplest one outright: if a query's keywords "appear in the headings or body text of a webpage, the information might be more relevant." The table sorts the common claims about the rest.10.3.1 HTML
The <title> element is the main source of the title link, but Google also uses "the main visual title", headings, prominent text and anchor text, and replaces stuffed or boilerplate titles. That keyword-first titles perform better is unconfirmed. Write one distinct, accurate title per page (Section 2.11.1).The meta description is not a ranking factor: in 2009 Google said "we still don't use the description meta tag in our ranking", and snippets are "primarily created from the page content itself".Heading order "doesn't matter" to Google, because "the web in general is not valid HTML", and validity itself is unconfirmed as a factor. Keep the <head> valid, though: canonical and hreflang links pushed into the body by a parsing error are ignored. For images, alt text is "the most important attribute", captions and nearby text help, and file names give "very light clues":<figure>
<img src="/img/dalmatian-puppy-fetch.webp" alt="Dalmatian puppy playing fetch"
width="800" height="533">
<figcaption>Our 10-week-old Dalmatian, Pepper</figcaption>
</figure>
10.3.2 URL
Keywords in a URL path have "hardly any effect beyond appearing in breadcrumbs", and studies showing short URLs rank higher are correlations, not causes. Google's URL guide gives usability rules instead: readable words rather than long IDs (/wiki/Aviation, not /index.php?topic=42&area=3a5e...), hyphens rather than underscores between words, and no # fragments to switch content, since "Google Search generally doesn't support URL fragments"; use the History API instead. Category folders such as /shoes/running/ help users and let Google learn which sections change often. Once published, keep URLs stable, or 301-redirect old ones.10.3.3 Keywords
Query words in "the headings or body text" are Google's "most basic signal" of relevance, yet a searcher for "dogs" doesn't "want a page with the word 'dogs' on it hundreds of times". Keyword stuffing and hidden text (white on white, off-screen CSS) violate the spam policies. Keyword-density targets, the "first 100 words" rule, TF-IDF formulas and "LSI keywords" are unconfirmed: Google's documentation never mentions them. It documents RankBrain and neural matching, which relate words to concepts (Section 10.1.2), so write the words and synonyms your readers use.10.3.4 Content
Length is not a ranking factor: "Are you writing to a particular word count because you've heard or read that Google has a preferred word count? (No, we don't.)" What Google confirms is a preference for helpful, people-first content, part of its core ranking systems since March 2024: original information, clear sourcing, visible expertise and no easily verified errors. Topics that affect health or finances ("Your Money or Your Life") get "even more weight" on E-E-A-T (Section 10.1.2).Generated content is judged by value, not by tool. Generative AI "can be particularly useful when researching a topic", but the scaled content abuse policy covers many low-value pages made to manipulate rankings "no matter how it's created". Quality raters' "ratings don't directly influence ranking." Moderate user comments and mark their links rel="ugc" (Section 10.4.5).10.3.5 User-friendliness
Google weighs the "relevance and usability of pages", and its page experience checklist asks whether visitors "can easily distinguish the main content from other content". Beyond Core Web Vitals, though, such aspects "don't directly help your website rank higher"; they help by satisfying visitors. Bounce rate and time on site as direct factors are unconfirmed (Section 10.5.3).Content in tabs or accordions is fine if it is in the HTML, but Google "won't load content that requires user interactions (for example, swiping, clicking, or typing)". A clear hierarchy aids crawling (Section 10.3.9), and BreadcrumbList structured data can show the trail in desktop results.10.3.6 Loading Speed and Core Web Vitals
Speed is the one page experience aspect Google confirms: "Core Web Vitals are used by our ranking systems." "Good" means LCP within 2.5 s, INP under 200 ms and CLS under 0.1, measured on real Chrome users (the CrUX data behind Search Console's Core Web Vitals report); Section 9.10 shows how to measure and fix each.Keep expectations realistic. Google "always seeks to show the most relevant content, even if the page experience is sub-par", and good scores don't "guarantee that your pages will rank at the top". Aim for "good" for your users, not a perfect Lighthouse score for SEO.10.3.7 Mobile Usability
On October 31, 2023 Google declared mobile-first indexing complete: it "uses the mobile version of a site's content ... for indexing and ranking." Content missing from your phone layout is missing from Google, so serve the same content, structured data and metadata to every device, ideally with responsive design, "the easiest design pattern to implement and maintain."Two old claims need updating. After "Mobilegeddon" (2015) Google called mobile-friendliness a ranking signal; its page experience documentation now says aspects beyond Core Web Vitals "don't directly help". And AMP has not been required for the Top Stories carousel since 2021.10.3.8 Freshness
Google runs "query deserves freshness" systems: a search for a just-released movie or a recent earthquake favors recent pages, while evergreen queries do not. Freshness is therefore confirmed for time-sensitive queries only. Publishing frequency as a site-wide boost is not a ranking factor; Google asks whether you are adding or removing content to seem "fresh" and answers "(No, it won't)", and it treats "changing the date of pages to make them seem fresh when the content has not substantially changed" as a warning sign.Update pages when facts change, show a visible "Published" or "Last updated" date, and keep dateModified in structured data and <lastmod> in the sitemap honest (Section 10.3.13).10.3.9 Links
Google "uses links as a signal when determining the relevancy of pages and to find new pages to crawl", but reliably follows only <a> elements with an href. Descriptive anchor text ("ghost peppers", not "click here") helps people and Google, and "every page you care about should have a link from at least one other page on your site."Linking out is safe: external links "can help establish trustworthiness (for example, citing your sources)." That followed outbound links "leak" PageRank is unconfirmed, as is any ranking effect of broken links. Use nofollow only for sources you distrust and sponsored for paid links (Section 10.4.5).10.3.10 Side Content
Supplementary content (related links, calculators, author bios, contact and policy pages) earns readers' trust. Google's helpful content questions look for "clear sourcing, evidence of the expertise involved, background about the author or the site", such as "an author page or a site's About page", but no document makes an About, Terms or Privacy page a factor in itself: unconfirmed. Claims that embedded YouTube videos or other multimedia boost rankings are unconfirmed too. Add these features because visitors use them.10.3.11 Translations and hreflang
Translated pages are not duplicates: localized pages "are only considered duplicates if the main content of the page remains untranslated." Declare versions with hreflang in the HTML head, an HTTP Link header or the sitemap (all equivalent). Each version lists itself and all others with absolute URLs, or unreciprocated links are ignored. Codes are an ISO 639-1 language plus an optional ISO 3166-1 region (de-CH); a region alone is invalid, and en-UK does nothing (the code is GB). Google detects language itself and does not use hreflang or lang for that.<link rel="canonical" href="https://example.com/de/preise">
<link rel="alternate" hreflang="en" href="https://example.com/en/pricing">
<link rel="alternate" hreflang="de" href="https://example.com/de/preise">
<link rel="alternate" hreflang="de-CH" href="https://example.com/ch/preise">
<link rel="alternate" hreflang="x-default" href="https://example.com/">
10.3.12 WordPress Tags
WordPress runs 40.3% of all websites (W3Techs, September 2026), so its habits matter. Each tag creates an archive page such as /tag/seo/ listing matching posts. Google has no WordPress-specific signal; tags help only when their archives are useful to readers. A tag used once produces a thin, near-duplicate page, and since WordPress 5.5 (2020) the built-in sitemap at /wp-sitemap.xml lists tag archives by default. Use a few well-chosen tags, or drop tag archives from the sitemap:add_filter('wp_sitemaps_taxonomies', function ($taxonomies) {
unset($taxonomies['post_tag']);
return $taxonomies;
});
10.3.13 Sitemap
A sitemap aids discovery, not ranking. Google "ignores <priority> and <changefreq> values" and trusts <lastmod> only when "consistently and verifiably" accurate. Use absolute canonical URLs, at most 50,000 per file (50 MB), and keep the file at the root, because a sitemap covers only its own directory unless submitted in Search Console (Section 2.11.4). The script escapes & as &.import { writeFileSync } from 'node:fs';
const site = 'https://example.com';
const pages = [
{ path: '/', updated: '2026-09-01' },
{ path: '/product?id=45&lang=en', updated: '2026-07-30' },
];
const esc = (s) => s.replace(/&/g, '&').replace(/</g, '<');
const urls = pages.map((p) => ` <url><loc>${esc(site + p.path)}</loc>`
+ `<lastmod>${p.updated}</lastmod></url>`);
const xml = ['<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">', ...urls, '</urlset>'];
writeFileSync('sitemap.xml', xml.join('\n') + '\n');
console.log(xml.join('\n'));
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://example.com/</loc><lastmod>2026-09-01</lastmod></url>
<url><loc>https://example.com/product?id=45&lang=en</loc><lastmod>2026-07-30</lastmod></u
rl>
</urlset>
10.3.14 Using Google Analytics and Google Search Console
That installing Google Analytics or verifying Search Console helps indexing or rankings is unconfirmed, with no support in Google's documentation. Pages "can be discovered by Google" without submitting a sitemap, and sites rank without either tool.Use both for what they measure. Search Console shows Google's view (queries, clicks, impressions, average position, indexing, Core Web Vitals, security issues and manual actions) and emails you about new issues. Google Analytics 4 shows what visitors do; Universal Analytics stopped processing data on July 1, 2023. Section 10.7.1 tours both.10.3.15 Duplicate Content and Canonical URLs
The "duplicate content penalty" for your own site is a myth: "If you have some content that's accessible under multiple URLs, it's fine; don't fret about it." Google clusters the copies, picks one canonical URL and consolidates signals, though duplicates waste crawling. Copying other sites differs: scraping breaks spam policy, and a "significant volume of valid copyright removal requests" demotes a site's other content.
Figure 10.2: Duplicate URLs collapse into one canonical URLHints stack, so keep them consistent: a self-referencing canonical on
every page, internal links to the canonical form, absolute URLs, and an
HTTP header for non-HTML files:<link rel="canonical" href="https://example.com/green-dress">
Link: <https://example.com/downloads/white-paper.pdf>; rel="canonical"
10.3.16 Excessive Monetization
Ads are allowed; blocking the content is not. Google's 2012 page layout algorithm hit pages giving "a large fraction of the site's initial screen real estate to ads", but not ads above the fold "to a normal degree". Since January 10, 2017, mobile pages hidden behind intrusive interstitials "may not rank as highly"; cookie notices, age gates and "banners that use a reasonable amount of screen space" are exempt.
Figure 10.3: An intrusive interstitial versus a small, dismissible
bannerAffiliate sites are fine too: "Not every site that participates in an
affiliate program is a thin affiliate." Thin
affiliation, copied merchant text "without any original content
or added value", is spam. Mark affiliate links rel="sponsored", never
cloak them with sneaky redirects, and see Section 10.7.12 on ad
networks.10.4 External Backlink Factors
Links from other sites were the raw material of PageRank (Section 10.1.2), and Google's ranking systems guide still lists "link analysis systems and PageRank". What has aged badly is the folklore built on that fact. Google now documents which links you must label and which count as spam, and says SpamBrain neutralizes unnatural links. Each claim below is marked confirmed, not a factor or unconfirmed. Internal links are covered in Section 10.3.9.10.4.1 The Linker's Domain
Confirmed: PageRank weighs a link by the importance of the page casting it, so one link from a respected site outweighs dozens from obscure ones. Google publishes no domain "trust" score (Section 10.2.5). Unconfirmed: that referring-domain counts cause rankings (vendor studies show only correlation), that .edu, .gov or country-code domains pass a bonus, and that old domains or old links pass more. The advice to get links from different "Class C" IP blocks dates from link networks hosted on one server; classful addressing ended with CIDR in 1993, Google documents no IP-based link grouping, and most sites now share CDN addresses.10.4.2 The Linker's Content
Google's link systems use links "to determine what pages are about", so links from relevant pages in your field are the ones it interprets best. The claim that a link in a 1,000-word post beats one in a short snippet is unconfirmed; Google says "the length of the content alone doesn't matter for ranking purposes." Main-content links outweighing footer links is plausible but unpublished. Wikipedia marks external links rel="nofollow", so a citation there brings readers, not reliable ranking credit.10.4.3 Number of Links
Link counts are not additive. In the PageRank formula a page divides its vote among its outbound links, so a page with 300 external links passes a sliver of what a page with three passes. Sitewide footer or blogroll links are many links from one source, and footer links planted across many sites are named link spam. Link velocity, a boost for a rising link count and a penalty for a falling one, is unconfirmed; a sudden surge of bought links is what SpamBrain is built to catch.10.4.4 Linking Text
Anchor text is confirmed: Brin and Page attached link text to the target page because "anchors often provide more accurate descriptions of web pages than the pages themselves." Google asks for anchors that are "descriptive, reasonably concise, and relevant" and uses an image link's alt text as its anchor. Exact-match keyword anchors are a risk: "links with optimized anchor text" in guest posts and press releases are named spam. Weight from the link title attribute is unconfirmed. Pharmacy or casino phrases in Search Console's Top linking text table can signal a hack or spam attack.10.4.5 nofollow, sponsored and ugc
rel="nofollow" was proposed in 2005 against comment spam, and Google originally ignored such links. On 10 September 2019 Google added sponsored and ugc and made all three "hints about which links to consider or exclude", for ranking at once and for crawling and indexing from 1 March 2020.<a href="https://shop.example/" rel="sponsored">Partner offer</a>
<a href="https://visitor.example/" rel="ugc nofollow">Commenter's site</a>
10.4.6 Redirection
Redirects are normal for site moves and retired URLs. Google treats a permanent redirect (301, 308) as a signal that the target should be canonical and documents no PageRank loss, so redirect old URLs permanently to their closest replacement to keep their links (Section 10.3.15). The spam policies forbid sneaky redirects, which show "users and search engines different content", such as redirecting only mobile users to a spam domain. Doorway abuse, pages built to rank for similar queries and funnel visitors elsewhere, is a separate violation.10.4.7 Dubious Links
Google defines link spam as "creating links to or from a site primarily for the purpose of manipulating search rankings". The old warnings about directories, comments, press releases and widgets are now written policy:10.4.8 Unnatural Links
Since the December 2022 link spam update, SpamBrain detects "sites buying links, and sites used for the purpose of passing outgoing links", and their credit is lost. Human reviewers add Unnatural links to your site or Unnatural links from your site manual actions in Search Console, so selling links is as risky as buying them. Google "works very hard" to stop third parties harming your site, and "most sites will not need" the disavow tool: use it only for a real or likely manual action, as a UTF-8 .txt file of URLs and domain:example.com lines. The Google Sandbox for new sites is denied: John Mueller said in 2021 that holding new pages back "is not the case".10.4.9 Links of Special Significance
Extra weight for links to a homepage is unconfirmed. Links from real, editorially run sites beating fake blogs is confirmed in spirit, because SpamBrain targets sites that exist to pass links. Blog comments are content, not a ranking bonus, and their links belong under ugc. Guest posting reaches readers, but guest posts with optimized anchors are spam. The Google+ Circles claim is obsolete: consumer Google+ shut down on 2 April 2019. The durable strategy is to publish something others want to cite.10.5 Navigation Factors
Old checklists credited RankBrain with watching how searchers behave; Google describes it as a system that relates words to concepts (Section 10.1.2). Behavior does matter, though. Google's How Search Works site states: "We also use aggregated and anonymized interaction data to assess whether search results are relevant to queries." Two events added detail, with limits worth stating precisely:The US v. Google antitrust trial. Google's Pandu Nayak testified in 2023, as reported by Search Engine Land, that Navboost, dating back "at least to 2005", is "one of the important signals" and memorizes clicks on queries from the past 13 months. It cannot help pages that have no clicks.
The 2024 API documentation leak. Internal Content Warehouse API documentation published on GitHub in March 2024 surfaced in May. It names 14,014 attributes, including goodClicks, badClicks, lastLongestClicks and chromeInTotal. It "did not specify how any of the ranking features are weighted", nor which are used today; Google warned against assumptions "based on out-of-context, outdated, or incomplete information."
10.5.1 Direct Traffic
The claim that Google has "confirmed" using Chrome data to count site visits is wrong. Google has not documented it; the leaked chromeInTotal attribute is the closest evidence, and how it is used is unknown. What Google does document is the Chrome UX Report, real-user performance data behind Core Web Vitals (Section 9.10). Studies correlating direct traffic with rankings may simply reflect that popular brands get both. Treat direct visits, shown in GA4's Direct channel, as a sign of loyalty worth earning, not a ranking lever.10.5.2 Organic Click-through
Search Console reports organic click-through rate (CTR) as clicks divided by impressions (Section 10.3.14). Clicks feed ranking in aggregate, but not as a raw "more clicks, higher rank" rule: a Google slide shown at the trial warned that ranking purely on clicks would "promote low-quality, click-bait results", so click data is weighed alongside other signals. A site-wide "quality score" from organic CTR is unconfirmed; Quality Score is a Google Ads metric. Earn clicks honestly with accurate titles and descriptions that the page then delivers on.
Figure 10.4: Click data as described in the trial and the leak
(weights unknown)10.5.3 Bounce Rate and Engagement
In Google Analytics 4 a session is engaged if it lasts longer than 10 seconds, triggers a key event or views two or more pages; bounce rate is "the percentage of sessions that were not engaged." No Google documentation names Analytics bounce rate as a ranking signal, and Google cannot see it on sites without Analytics. Dwell time and pogo-sticking (returning to the results to click another listing) are a different matter: the leaked lastLongestClicks and badClicks attributes suggest Google classifies clicks this way, but thresholds and weights are unknown. A one-page visit that answers the question is a success, so optimize for satisfied visitors, not for a lower bounce number.10.5.4 Repeating Traffic
Boosts for returning visitors or for pages bookmarked in Chrome are unconfirmed; Google has documented neither, and nothing public shows how Chrome data, if used, would be weighted. Returning visitors still matter commercially: they subscribe, buy and link. Build reasons to return, such as fresh content (Section 10.3.8), newsletters and useful tools.10.5.5 Search History
Personalization is confirmed. Google says it uses "your location, past Search history, and Search settings to determine what is most relevant", so "football" shows the Chicago Bears in Chicago and the Premier League in London. The "About this result" panel shows whether search history influenced a result, and personalization can be switched off. Google also says Search "does not put people in 'filter bubbles'" and does not infer sensitive traits such as religion. The practical lesson: your own searches mislead you about rankings. Check average position in Search Console (Section 10.3.14) instead.10.5.6 Featured Snippets
A featured snippet shows a passage from a page above its link. Google's documentation is blunt about requesting one: "How can I mark my page as a featured snippet? You can't." Its systems choose passages that answer the query, so clear headings that match questions, followed by a direct answer in the first sentence or a short list or table, give them good candidates; claims that length, HTTPS or authority decide selection come from vendor studies, not Google. Clicking a snippet scrolls the visitor to the quoted passage. To opt out, use nosnippet (all snippets), a low max-snippet (no guarantee) or data-nosnippet on specific text; nosnippet and max-snippet also limit use in AI Overviews (Section 10.1.3).<meta name="robots" content="max-snippet:50">
<p data-nosnippet>Prices change daily; see the checkout page.</p>
10.6 Brand Factors
Big brands dominate many results pages, which has launched years of brand-signal theories. Google's documentation describes no brand score. It does describe systems that reward what strong brands tend to have: trusted links, clicks, reviews and a clear identity. The table sorts the claims.10.6.1 Transactional Searches
Shopping, travel and local queries often show product grids, flight boxes or maps instead of ten plain links, so the organic listings start lower. The belief that big brands got a blanket boost dates from the 2009 "Vince" change; Matt Cutts described it as a minor change factoring trust, quality and PageRank into generic queries, not a brand push. Brand and navigational queries behave differently: Google's site diversity system "generally won't show more than two web page listings from the same site", but may show more when "especially relevant", which is why a brand search can return a page of results from one domain.10.6.2 Brand Name in Anchor Text
That brand-name anchors signal a "strong brand" is unconfirmed; Google documents anchor text only as a description of the target page (Section 10.4.4). Brand anchors are still what a natural link profile looks like, because people link to a company by its name or URL, and they avoid the keyword-optimized anchors Google names as spam. If your Search Console Top linking text is mostly exact commercial phrases rather than your name, someone has probably been building links.10.6.3 Brand Mentions
Whether an unlinked mention of your brand helps ranking is unconfirmed. Google does confirm that its site name system, which picks the name shown beside each result, uses "references to it that appear on the web". For news publishers, Top Stories now has a documented, user-driven lever: a searcher can pick preferred sources, whose content is then "more likely to appear in Top Stories" with a "preferred" badge, and is also badged in AI Mode and AI Overviews. Only domain and subdomain sites qualify, and you may invite readers with a deep link.10.6.4 Brand Searches
The claims that searches for your brand prove you are "a real brand", and that searches for "brand + keyword" lift your ranking for the keyword alone, are unconfirmed. Neither Google's documentation nor the trial reporting describes such a mechanism. Brand searches are still valuable traffic from people who already know you. Track them by filtering the Search Console Performance report by queries containing your brand name, and watch the non-brand remainder to see whether your content wins new visitors.10.6.5 Social Media
No Google documentation lists follower counts, likes or posting activity as ranking signals, so treat those claims as unconfirmed. Social media works indirectly: Google's SEO starter guide recommends "social media promotion" and calls word of mouth "one of the most effective and lasting ways" to build traffic, because people who discover you there may link, search for you and return. Tie your profiles to your site with Organization structured data on the home page; its sameAs property lists "your organization's profile page on a social media or review site" and helps Google "disambiguate your organization" (Section 2.11).<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Example Widgets",
"url": "https://www.example.com",
"logo": "https://www.example.com/images/logo.png",
"sameAs": ["https://www.linkedin.com/company/example", "https://github.com/example"]
}
</script>
10.6.6 Brick-and-mortar Location
For local results this factor is confirmed. Google's Business Profile guide says local results are "mainly based on relevance, distance, and popularity", and that prominence reflects "how many websites link to your business and how many reviews you have"; there is "no way to request or pay for a better local ranking." Claim and complete your Business Profile, keep name, address and phone consistent with your site, and ask customers for reviews. Whether Google checks for an office address to judge brand strength in ordinary web results is unconfirmed.10.7 SEO Tools
Start with Google Search Console and Bing Webmaster Tools, which see data no third party can, then add one commercial suite. Prices are entry plans as listed on vendor pricing pages in September 2026; annual billing is often cheaper. Defunct tools are named at the end of each subsection.10.7.1 Google Tools
10.7.2 Website Analysis
10.7.3 Keyword Research
Beyond Keyword Planner, KeywordTool.io (https://keywordtool.io/) mines autocomplete (free list; Pro $88/month), KWFinder is part of Mangools, Ubersuggest (limited free features) and AnswerThePublic come from Neil Patel, and Soovle (now SEO.com) is free. Longtail PRO and ANTRanks are gone.10.7.4 Rank Monitoring
Search Console shows average positions free. Paid trackers follow chosen keywords by location and device: SE Ranking ($129/month), Advanced Web Ranking ($139/month), Nightwatch (â¬79/month, billed yearly), WooRank, RankWatch and Authority Labs. Alexa Rank is gone (alexa.com now points to Amazon's voice assistant), and checkpagerank.net redirects to SEOptimer.10.7.5 Linking
Each backlink index runs its own crawler and sees a different subset of links. Ahrefs (https://ahrefs.com/) costs $129/month (free Ahrefs Webmaster Tools for your own sites), Majestic $49.99/month and LinkResearchTools from $5,799/year; Whitespark handles local citations, and Seobility and OpenLinkProfiler offer free checkers. Backlink Builder's site is blank. See Section 10.4 for which links help.10.7.6 Speed Test
PageSpeed Insights pairs a Lighthouse lab run with real-user Chrome UX Report data (Sections 1.3.3 and 9.10). GTmetrix (https://gtmetrix.com/) adds test locations and monitoring: free to start, paid from $4.99/month billed yearly. Quick Sprout is now a blog with no speed test.10.7.7 Penalty Checkers
Only Search Console's Manual actions report shows a Google penalty. "Penalty checkers" such as Semrush Sensor, AccuRanker's Google Grump and Algoroo measure ranking turbulence on tracked keywords, which tells you whether a drop matches an algorithm update. The Panguin tool and Website Penalty Indicator are offline.10.7.8 Plagiarism Detection
Copyscape (https://www.copyscape.com/) finds copies of a page free (10 results); Premium checks cost 3 cents for 200 words plus 1 cent per extra 100. Its sister Siteliner finds duplicate content within your site. Also: Quetext (free to 1,000 words; $14.99/month), Grammarly (Pro $12/month), DupliChecker (from $5/week) and SmallSEOTools. PlagScan closed on January 1, 2026.10.7.9 Sitemap and robots.txt Tools
Section 2.11.4 writes both files by hand. XML-Sitemaps.com crawls up to 500 URLs free, and MySitemapGenerator is free; the SEO Book and SmallSEOTools robots.txt generators still work, while LinkGraph's and Sure Oak's are gone. Check the result in Search Console's robots.txt report.10.7.10 Chrome Toolbar Extensions
SEOquake (free, 1,000,000 users) audits pages and shows Semrush metrics; MozBar (free, 900,000 users) shows Moz's Domain and Page Authority. Both are vendor estimates, not Google data. Check My Links has left the Chrome Web Store.10.7.11 WordPress Plugins
Active installs on WordPress.org: Yoast SEO 10+ million (Premium $118.80/year), Rank Math 4+ million (PRO from â¬7.99/month), All in One SEO 2+ million, XML Sitemap Generator for Google and Smush 1+ million each, W3 Total Cache 900,000+, The SEO Framework 200,000+ and AMP for WP 70,000+. Run only one SEO plugin.10.7.12 Ad Networks
AdSense pays publishers 80% of AdSense for Content revenue after the advertiser platform's fee (about 68% for Google Ads buyers). Alternatives: Ezoic, Media.net, Monumetric (from 10,000 pageviews/month), Taboola and Revcontent (native), Amazon Associates, Skimlinks and Sovrn (affiliate), Infolinks, BuySellAds, BidVertiser and PopCash (pop-unders). PropellerAds' publisher side is now Monetag, ylliX merged into Advertica, and Adversal is offline.10.7.13 Survey Networks
SurveyMonkey has a free Basic plan; Pollfish charges from $0.95 per panel response. Google Opinion Rewards (100M+ downloads) is the respondent side, paying up to $1.00 in Play credit per survey.10.7.14 Site Worth Estimators
SiteWorthTraffic, SitePrice, Website Worth Checker and MyWorthWeb guess value from estimated traffic; they cannot see your revenue, so ignore them. MageNet is actually a contextual ad marketplace. GetWebPrice, UpSiteWorth and Websites Worth Calculator are offline.10.8 Microformats
Microformats add meaning to HTML with class and rel values. A root class h-* marks an object; property prefixes tell parsers how to read values: p- text, u- URL, dt- date/time, e- embedded HTML. Parsers emit JSON (items, rels, rel-urls), so the page doubles as an API.Outputs below come from microformats-parser (https://github.com/microformats/microformats-parser) (MIT, npm install microformats-parser) via mf2(html, { baseUrl: 'https://example.com/' }), showing items[0], wrapped.10.8.1 h-adr, h-geo and h-card
h-card describes a person or organization (p-name, u-url, u-email, u-photo, p-tel, p-org). h-adr holds an address (p-street-address, p-locality, p-postal-code, p-country-name) and h-geo WGS84 coordinates (p-latitude, p-longitude); both usually nest inside a card or event.<p class="h-card"><a class="p-name u-url" href="https://example.com/">Lip Phang</a>,
<b class="p-adr h-adr"><i class="p-locality">Paris</i>, <i class="p-country-name">France</i></b>
<b class="p-geo h-geo"><i class="p-latitude">48.86</i>, <i class="p-longitude">2.35</i></b></p>
{"type": ["h-card"], "properties": {
"name": ["Lip Phang"],
"url": ["https://example.com/"],
"adr": [{"type": ["h-adr"], "properties": {"locality": ["Paris"], "country-name":
["France"]},
"value": "Paris, France"}],
"geo": [{"type": ["h-geo"], "properties": {"latitude": ["48.86"], "longitude": ["2.35"]},
"value": "48.86, 2.35"}]
}}
10.8.2 h-entry and h-feed
h-entry marks a dated post: p-name, p-summary, e-content, dt-published, p-author, p-category, u-url, plus reply and like links (u-in-reply-to, u-like-of). Wrap a list of entries in h-feed (p-name, p-author, u-url, u-photo).<article class="h-entry"><h1 class="p-name">Microformats are amazing</h1>
<p>By <a class="p-author h-card" href="/">Lip Phang</a>, <time class="dt-published"
datetime="2026-09-16">16 Sep 2026</time></p>
<div class="e-content"><p>Class names turn this page into an API.</p></div></article>
{"type": ["h-entry"], "properties": {"name": ["Microformats are amazing"],
"author": [{"type": ["h-card"], "properties": {"name": ["Lip Phang"],
"url": ["https://example.com/"]}, "value": "Lip Phang"}], "published": ["2026-09-16"],
"content": [{"value": "Class names turn this page into an API.",
"html": "<p>Class names turn this page into an API.</p>"}]}}
10.8.3 h-event
h-event uses p-name, p-summary, dt-start, dt-end, dt-duration, u-url, p-category and p-location (text, or a nested h-card or h-adr).<div class="h-event"><b class="p-name">HTML Meetup</b>, <span class="p-location">Berlin</span>:
<time class="dt-start" datetime="2026-10-03T10:00">3 Oct, 10 am</time> to
<time class="dt-end" datetime="2026-10-03T17:00">5 pm</time></div>
{"type": ["h-event"], "properties": {"name": ["HTML Meetup"], "location": ["Berlin"],
"start": ["2026-10-03T10:00"], "end": ["2026-10-03T17:00"]}}
10.8.4 h-item, h-listing and h-product
h-product offers p-name, u-photo, p-brand, p-category, e-description, u-url, u-identifier, p-review and p-price. h-item (p-name, u-url, u-photo) rarely stands alone; it names what an h-review reviews. h-listing is a draft.<div class="h-product"><img class="u-photo" src="/mfd.png" alt="">
<b class="p-name">Microformats For Dummies</b> <data class="p-price" value="20.00">$20</data>
from <a class="p-brand h-card" href="https://acme.example/">ACME</a></div>
{"type": ["h-product"], "properties": {"photo": ["https://example.com/mfd.png"],
"name": ["Microformats For Dummies"], "price": ["20.00"], "brand": [{"type": ["h-card"],
"properties": {"name": ["ACME"], "url": ["https://acme.example/"]}, "value": "ACME"}]}}
10.8.5 h-recipe and h-resume
h-recipe uses p-name, p-ingredient, p-yield, e-instructions, dt-duration, u-photo, p-author and p-nutrition. h-resume uses p-name, p-summary, p-contact (an h-card), p-education, p-experience, p-skill and p-affiliation. Both are drafts.<article class="h-recipe"><h2 class="p-name">Bagels</h2>
<ul><li class="p-ingredient">Flour</li><li class="p-ingredient">Yeast</li></ul>
<p>Takes <time class="dt-duration" datetime="PT1H">1 hour</time>,
serves <data class="p-yield" value="4">four</data>.</p></article>
{"type": ["h-recipe"], "properties": {"name": ["Bagels"], "ingredient": ["Flour", "Yeast"],
"duration": ["PT1H"], "yield": ["4"]}}
10.8.6 h-review and h-review-aggregate
h-review uses p-name, p-item, p-author, dt-published, p-rating, p-best, p-worst and e-content. h-review-aggregate summarizes many reviews with p-item, p-average, p-best, p-worst, p-count and p-votes (its spec is still a stub).<div class="h-review"><a class="p-item h-item" href="https://microformats.org/">Microformats</a>
<data class="p-rating" value="5">5 stars</data> by <span class="p-author h-card">Joe Bloggs</span>
<p class="p-summary">The simplest way to publish structured data.</p></div>
{"type": ["h-review"], "properties": {"item": [{"type": ["h-item"],
"properties": {"name": ["Microformats"], "url": ["https://microformats.org/"]},
"value": "Microformats"}], "rating": ["5"], "author": [{"type": ["h-card"],
"properties": {"name": ["Joe Bloggs"]}, "value": "Joe Bloggs"}],
"summary": ["The simplest way to publish structured data."]}}
10.8.7 rel-author, rel-enclosure, rel-license, rel-nofollow and rel-tag
rel values describe the link itself. author, license, nofollow and tag are link types in the HTML Standard; enclosure marks a downloadable attachment such as a podcast file. Parsers collect them page-wide rather than inside an h-* object.<a rel="author" href="/about">Erin Smith</a>
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>
<a rel="tag" href="/tags/html">html</a>
<a rel="enclosure" href="/talk.mp4">Download the talk</a>
<a rel="nofollow ugc" href="https://spam.example/">A commenter's link</a>
<a rel="me" href="https://social.example/@erin">Mastodon</a>
<a rel="friend met co-worker" href="https://josh.example/">Josh</a>
{"rels": {"author": ["https://example.com/about"],
"license": ["https://creativecommons.org/licenses/by/4.0/"],
"tag": ["https://example.com/tags/html"], "enclosure": ["https://example.com/talk.mp4"],
"nofollow": ["https://spam.example/"], "ugc": ["https://spam.example/"],
"me": ["https://social.example/@erin"], "friend": ["https://josh.example/"],
"met": ["https://josh.example/"], "co-worker": ["https://josh.example/"]}}
10.8.8 XFN
XHTML Friends Network (XFN 1.1, by Tantek Ãelik, Matt Mullenweg and Eric Meyer) describes people you link to: friendship (contact, acquaintance, friend), met, professional (co-worker, colleague), plus family, romantic and geographical values. Its lasting value is rel="me" ("this profile is also me"): when your Mastodon profile lists your site and the site links back with rel="me", Mastodon shows a checkmark.10.8.9 Microformats versus JSON-LD and Microdata
10.9 Technical SEO for JavaScript Sites
A framework decides what HTML a crawler receives, and a crawler decides whether it will run your JavaScript to see more. Section 1.12.7 introduced the rendering strategies; this section looks at them from the crawler's side, then covers how Googlebot renders, how to test structured data (Section 2.11.3) and how to structure sites for several languages and countries.10.9.1 CSR, SSR, SSG and Hydration from a Crawler's Viewpoint
Every crawler reads the initial HTML response. Only some go on to execute JavaScript and read the rendered DOM: Googlebot renders with an evergreen Chromium, Bingbot with Edge's engine (Section 10.1.1), and Applebot "may render the content of your website within a browser". Google still recommends server-side or pre-rendering because "not all bots can run JavaScript": a December 2024 Vercel and MERJ study found that GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot and Common Crawl's CCBot executed no JavaScript at all.
Figure 10.5: What crawlers find in the response and after rendering,
by rendering strategyClient-side rendering (CSR). The shell has no text and no <a href> links, so Google finds nothing until the page leaves the render queue, and a non-rendering bot sees an empty page.
Server-side rendering (SSR) with hydration. Text, links, <title> and JSON-LD arrive in the response. Content fetched only after hydration, such as reviews loaded in useEffect, falls back to CSR rules.
Static site generation (SSG) and ISR. Every crawler gets complete HTML from a CDN; the risk is stale prices until the page is regenerated.
Dynamic rendering, prerendered HTML served only to bots, "was a workaround and not a long-term solution"; Google recommends SSR, static rendering or hydration instead.
10.9.2 How Googlebot Renders JavaScript
Googlebot queues every URL that returns 200 for rendering unless a robots meta tag or header forbids indexing. When resources allow, the Web Rendering Service (WRS) runs the page in headless Chromium and parses the rendered HTML. In March 2026 Google dropped its old warning: it has rendered JavaScript "for multiple years now". What breaks sites are the differences from a user's browser:const res = await fetch(`/api/products/${id}`);
if (res.status === 404) {
document.head.insertAdjacentHTML('beforeend', '<meta name="robots" content="noindex">');
renderNotFound();
} else {
renderProduct(await res.json());
}
10.9.3 Structured Data Testing and Rich Results
Valid JSON-LD (Section 2.11.3) makes a page eligible for a rich result, but Google says it "does not guarantee" one. Templates and serving issues break markup after launch, so test at every stage: the Rich Results Test while developing, the Schema Markup Validator (https://validator.schema.org/) for schema.org rules without Google's, then the URL Inspection tool and Search Console's site-wide rich result reports.The Rich Results Test (https://search.google.com/test/rich-results) accepts a URL or a code snippet and fetches as Google-InspectionTool on a smartphone, so robots.txt can block it and a local server needs a tunnel. It reads the rendered source, so JSON-LD injected by JavaScript counts, though Google warns this makes Shopping crawls "less frequent and less reliable".Catch syntax errors in the build first. Run this script on each built page (node check-jsonld.mjs dist/kettle.html); here the page's second block has a trailing comma:import { readFileSync } from 'node:fs';
const html = readFileSync(process.argv[2], 'utf8');
const re = /<script type="application\/ld\+json">([\s\S]*?)<\/script>/g;
for (const [, json] of html.matchAll(re)) {
try {
console.log('OK ', JSON.parse(json)['@type']);
} catch (err) {
console.log('ERROR', err.message);
process.exitCode = 1;
}
}
OK Product
ERROR Expected double-quoted property name in JSON at position 80 (line 2 column 80)
10.9.4 International and Multi-regional Sites
A multilingual site offers several languages; a multi-regional site targets several countries. Google recommends a separate URL for each version, annotated with hreflang (Section 10.3.11), and advises against URL parameters such as ?loc=de:<!doctype html>
<html lang="de" style="font-family: system-ui, sans-serif">
<p id="suggest" hidden style="background: #e3f2fd; padding: 10px">
This page is also available in English. <a href="/en/kettle">Switch to English</a>
</p>
<h1>Wasserkocher aus Edelstahl</h1>
<script>
if (navigator.languages.some((lang) => lang.startsWith('en'))) {
document.getElementById('suggest').hidden = false;
}
</script>
Figure 10.6: Browser output of Listing 10.2310.10 Generative Engine Optimization
Generative engine optimization (GEO), also sold as answer engine optimization (AEO), aims to get a site cited in AI answers. Google's own guide says that for its AI features this "is still SEO". Other assistants run their own crawlers and indexes, so a few controls and measurements are new.10.10.1 How AI Assistants Choose and Cite Sources
AI assistants answer current questions with retrieval-augmented generation (RAG), which Google says is "also known as grounding": the model searches an index, reads the retrieved pages and writes an answer with links to the pages that support it. Google grounds AI Overviews and AI Mode in its core ranking systems and query fan-out (Section 10.1.3). ChatGPT search surfaces sites through OAI-SearchBot, Perplexity through PerplexityBot, and Claude through Claude-SearchBot and Claude-User (Section 10.10.2).
Figure 10.7: A grounded AI answer and where a page can drop outIn Anthropic's web search API, for example, the model decides when to
search, may search several times, and attaches citations to parts of its
answer, each with a URL, a title and up to 150 characters of cited_text.
A citation points at a passage, so facts you want credited must be text
in your initial HTML (Section 10.9.1).What the evidence says. The 2023 paper GEO:
Generative Engine Optimization (Aggarwal et al., KDD 2024) tested
page rewrites on its GEO-bench query set: adding citations, quotations
and statistics raised visibility by 30-40% on its main metric, while
keyword stuffing did not help. For its own AI features, Google says to
skip chunking content, rewriting for AI, buying mentions and special
schema.org markup, and to write "non-commodity content": first-hand
experience and data that summaries cannot supply.10.10.2 llms.txt, AI Crawlers and robots.txt Controls
AI companies separate training crawlers from search crawlers and user-triggered fetchers, each with its own robots.txt token (Section 2.11.4). Blocking OpenAI's or Anthropic's training bot keeps you in their AI search; blocking their search bot can remove you.User-agent: GPTBot
User-agent: ClaudeBot
User-agent: Google-Extended
User-agent: Applebot-Extended
Disallow: /
User-agent: *
Allow: /
10.10.3 Measuring Visibility in AI Answers
Measure impressions and citations, not only clicks. Four sources are dependable:Google Search Console. The Generative AI performance report, open to all sites since August 31, 2026, shows impressions in AI Overviews and AI Mode by page, country, date and device.
Bing Webmaster Tools. AI Performance, in public preview since February 2026, counts citations per URL in Microsoft Copilot and Bing's AI summaries, with sample "grounding queries".
Server logs. They show which pages each AI crawler fetches; check hits against the IP ranges the operators publish, since user agents are easy to fake.
Analytics referrals. Visits from assistant domains such as chatgpt.com, perplexity.ai and copilot.microsoft.com appear as referral traffic when the browser sends a referrer.
grep -oE 'GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-User|PerplexityBot' \
/var/log/nginx/access.log | sort | uniq -c | sort -rn
A. HTML Element Reference (Every Element in One Table)
All 113 elements of the WHATWG HTML Living Standard, plus the embedded svg and math, in the spec's category order: metadata, sections, grouping, text, edits, embedded, tables, forms, interactive, scripting. § gives the section that teaches each. Obsolete elements such as center, font, frame, marquee and param fail validation.B. CSS Property Quick Reference
The most-used properties by area (box model, flexbox and grid, text, visual effects, motion), with initial values from the CSS specifications. An asterisk marks an inherited property.C. JavaScript Built-in Objects Quick Reference
ECMAScript's global objects with their most-used static and prototype members (from is Array.from(), at is arr.at()).D. VS Code and Chrome DevTools Keyboard Shortcuts
Default bindings from the official documentation, VS Code on the left and Chrome DevTools on the right. On Linux, VS Code copies a line with Ctrl+Shift+Alt+Down and formats with Ctrl+Shift+I. Help > Keyboard Shortcut Reference prints VS Code's full list (Section 1.2.3); DevTools tooltips show theirs (Section 1.3).E. Glossary
Numbers in parentheses give the section that explains each term.ARIA: attributes that expose roles and states to assistive technology (2.10). AST: the abstract syntax tree a parser builds from source code (7.1.3). Baseline: a feature that works in Chrome, Edge, Firefox and Safari (1.1.3). BEM: Block-Element-Modifier class naming (4.12.3). bfcache: the back/forward cache that restores pages instantly (9.10). Bundler: a tool that joins modules into optimized files (1.8.1). Cascade layer: an @layer that ranks groups of rules before specificity (4.3.14). Closure: a function plus the variables it captured (6.5.7). Container query: styles chosen by a container's size (4.10.12). Core Web Vitals: LCP, INP and CLS, Google's user-experience metrics (9.10). CORS: headers that let a server share resources across origins (2.8.1). CSP: a policy restricting where scripts and other resources load from (2.8.5). Custom element: an author-defined HTML tag backed by a class (2.7.1). Custom property: a CSS variable written --name (4.2.10).DOM: the live object tree of a document (8.1.1). E-E-A-T: Experience, Expertise, Authoritativeness and Trustworthiness, Google's quality criteria (10.1.2). Event delegation: one listener on an ancestor handling events from many children (8.8.1). Event loop: the scheduler that runs tasks and microtasks (6.6.1). Formatting context: the layout mode, such as block or flex, of a box's children (4.8.11). Generic: a type parameterized by other types (7.7.1). GEO: optimizing content to be cited by AI assistants (10.10). Hoisting: declarations processed before code runs (6.5.3). Hydration: attaching JavaScript to server-rendered HTML (10.9.1). Islands: interactive components in an otherwise static page (1.12.7). JIT: just-in-time compilation of hot code to machine code (6.1.4). JSON-LD: structured data in a script block (2.11.3). Microtask: a queued callback, such as a promise reaction, run before the next task (6.6.5). Narrowing: refining a union type with checks (7.4).Polyfill: code that implements a missing feature (9.13). Preflight: Tailwind's base reset stylesheet (5.4). Progressive web app: an installable, offline-capable site (9.4.13). Prototype chain: the linked objects searched for inherited properties (6.3.10). Reflow: recalculating layout after a change (8.1.4). Secure context: a page served over HTTPS or localhost, required by powerful APIs (9.1). Service worker: a script that intercepts network requests (9.4.4). Shadow DOM: an encapsulated subtree with scoped styles (2.2.5). Signals: reactive values that update dependents directly (8.8.3). Source map: a file mapping built code back to source (6.24.3). Specificity: the weight that decides between competing selectors (4.3.12). SSR and SSG: rendering HTML on the server per request or at build time (1.12.7). Stacking context: a group painted as one layer along the z-axis (4.8.2). Temporal dead zone: the span before a let or const is initialized (6.2.4). Tree shaking: removing unused exports from a bundle (1.8.1). Utility-first: styling with single-purpose classes (5.1.1). Virtual DOM: an in-memory tree diffed to patch the real DOM (8.8.3). XSS: injecting script into a page through unsanitized input (8.8.4).F. Index of Open-source Libraries and Tools (GitHub URLs, by Chapter)
Every open-source project whose GitHub repository this book cites, listed under the chapter that first mentions it and sorted by owner. Prefix each path with https://github.com/ to reach the repository.Chapter 1. angular/angular, angular/angular.js, caddyserver/caddy, certbot/certbot, ChromeDevTools/chrome-devtools-mcp, ChromeDevTools/devtools-frontend, ddclient/ddclient, emberjs/ember.js, FiloSottile/mkcert, GoogleChrome/lighthouse, ionic-team/ionic-framework, karma-runner/karma, lit/lit, nuxt/nuxt, nvm-windows/nvm, preactjs/preact, QwikDev/qwik, react/react, solidjs/solid, sveltejs/svelte, vuejs/core, withastro/astro.Chapter 2. alpinejs/alpine, bigskysoftware/htmx, cheeriojs/cheerio, cure53/DOMPurify, davidjbradshaw/iframe-resizer, dequelabs/axe-core, emmetio/emmet, evanw/esbuild, expressjs/cors, flatpickr/flatpickr, handlebars-lang/handlebars.js, helmetjs/helmet, inikulin/parse5, jsdom/jsdom, keithamus/invokers-polyfill, Leaflet/Leaflet, libjxl/libjxl, lit/lit/tree/main/packages/labs/ssr, lovell/sharp, mde/ejs, mozilla/nunjucks, nvaccess/nvda, orchidjs/tom-select, pa11y/pa11y, parcel-bundler/lightningcss, paulirish/lite-youtube-embed, pugjs/pug, shoelace-style/webawesome, stenciljs/core, TanStack/table, terser/html-minifier-terser, terser/terser, validator/validator, vercel/satori, web-platform-dx/web-features.Chapter 3. bootstrap-vue-next/bootstrap-vue-next, ColorlibHQ/AdminLTE, coreui/coreui, desandro/masonry, FullHuman/purgecss, mdbootstrap/mdb-ui-kit, ng-bootstrap/ng-bootstrap, react-bootstrap/react-bootstrap, tabler/tabler, thomaspark/bootswatch, twbs/bootstrap.Chapter 4. csstools/postcss-plugins, floating-ui/floating-ui, fonttools/fonttools, postcss/autoprefixer, postcss/postcss, svg/svgo, unjs/fontaine.Chapter 5. dcastil/tailwind-merge, htmlstreamofficial/preline, joe-bell/cva, lukeed/clsx, saadeghi/daisyui, shadcn-ui/ui, sindresorhus/modern-normalize, tailwindlabs/headlessui, tailwindlabs/prettier-plugin-tailwindcss, tailwindlabs/tailwindcss-typography, tailwindlabs/tailwindcss/releases/latest, themesberg/flowbite.Chapter 6. axios/axios, colinhacks/zod, date-fns/date-fns, fullcalendar/temporal-polyfill, iamkun/dayjs, immerjs/immer, lodash/lodash, MikeMcl/decimal.js, moment/luxon, promises-aplus/promises-tests, ramda/ramda, ReactiveX/rxjs, sindresorhus/escape-string-regexp, sindresorhus/p-limit, uuidjs/uuid, zloirock/core-js.Chapter 7. AssemblyScript/assemblyscript, DefinitelyTyped/DefinitelyTyped, facebook/flow, fi3ework/vite-plugin-checker, mmkal/expect-type, rolldown/tsdown, sindresorhus/type-fest, typescript-eslint/typescript-eslint.Chapter 8. fabiospampinato/cash, jquery/jquery, jquery/jquery-migrate, TanStack/virtual, wiki/shared/books/front-end/eslint-plugin-no-jquery, wilsonpage/fastdom.Chapter 9. Dash-Industry-Forum/dash.js, dexie/Dexie.js, djipco/webmidi, GoogleChrome/web-vitals, GoogleChrome/workbox, GoogleChromeLabs/comlink, jakearchibald/idb, jakearchibald/idb-keyval, KaTeX/KaTeX, MasterKale/SimpleWebAuthn, mfreed7/xslt_polyfill, Modernizr/Modernizr, motiondivision/motion, openai/whisper, orestbida/cookieconsent, PlasmoHQ/plasmo, plausible/analytics, ronkok/Temml, SortableJS/Sortable, Tonejs/Tone.js, utterance/utterances, Vanilagy/mediabunny, video-dev/hls.js, wxt-dev/wxt.Chapter 10. microformats/microformats-parser.G. Answers to "Test Yourself!"
Answers to the questions in Section 6.27; all outputs come from Node.js 25.3 3 3, then 0 1 2. The var callbacks share one i, already 3 when the timers fire; let binds a fresh j per iteration (Sections 6.2.4 and 6.5.7).
A D F C E B. An async function runs synchronously until its first await; microtasks (C, then E) run before the next macrotask B (Section 6.6.5).
1 undefined, then a TypeError. The arrow takes this from the module scope (undefined), and the detached inc has no this either (Sections 6.5.2 and 6.23).
false [ 1, 10, 9 ] object false true. 0.1 has no exact binary form (Section 6.10.6), sort() compares strings, typeof null is a historical bug, and only Object.is finds NaN equal to itself.
[ 1, NaN, NaN ] [ 1, 2, 3 ]. map passes the index as a second argument, so parseInt('2', 1) uses an invalid radix (Section 6.13.4).
1 2. Spread makes a shallow copy, so inner is still shared; structuredClone() copies deeply (Section 6.3.9).
null 5 d 0 d. Destructuring defaults apply only to undefined; || rejects every falsy value, ?? only null and undefined (Sections 6.13.5 and 6.22.7).
{"d":null,"e":"1970-01-01T00:00:00.000Z"}. undefined, functions and symbol keys are skipped, NaN becomes null, and Date has a toJSON() method (Section 6.3.2).
1 20 true. The first next(5) only starts the generator, so 5 is discarded; 10 becomes x (Section 6.5.9).
[ 'rejected', 'fulfilled' ], then AggregateError [ 1, 2 ]. Promise.any rejects only when every input rejects (Section 6.6.7).
true false function. #x in o checks for the private field without throwing, and a class is a function (Sections 6.7.6 and 6.5.5).
Yes, if each read of a yields a new value. == converts objects through Symbol.toPrimitive, valueOf() or toString() (Sections 6.11.3 and 6.3.8); a Proxy (Section 6.21) works too, as does a global getter, which even fools ===. The old with trick is illegal in modules (Section 6.23). Three ways:
let i = 0;
const a = { [Symbol.toPrimitive]: () => ++i };
console.log(a == 1 && a == 2 && a == 3);
const b = [1, 2, 3];
b.join = b.shift; // arrays convert to strings via join()
console.log(b == 1 && b == 2 && b == 3);
let n = 0;
Object.defineProperty(globalThis, 'c', { get: () => ++n }); // globalThis, not window
console.log(c == 1 && c == 2 && c == 3, c === 4);
true
true
true true