Built to Be Cited: An Engineer's Guide to AEO and GEO in 2026
Disclaimer: All opinions expressed in this post are my own and do not represent the views or positions of my employer.
I rebuilt vikasmishra.ai over the last two weeks, not for a redesign, but for a category of search that didn’t exist the last time I touched the SEO. Ranking on the blue links stopped being the metric. Inclusion in an AI-generated answer became the metric. Google AI Mode and AI Overviews, ChatGPT search, Perplexity, Claude, Bing Copilot — the six surfaces that matter today all do a variation of the same thing: retrieve candidate passages, re-rank them on a platform-specific quality model, generate an answer that quotes or paraphrases the highest-ranked ones, and attach citations to the sources the generation actually used. What the surfaces reward and how they cite differs; the architecture converges.
I work on cloud and AI platforms at Google. The customers I advise are mostly large digital-native businesses — marketplaces and e-tailers with tens of millions of SKUs, food-delivery platforms doing millions of orders a day, online travel and hospitality platforms with real-time inventory and pricing, and fintechs operating in the YMYL (“Your Money or Your Life”) category where AI answer accuracy is a regulatory concern, not just a marketing one. The question every one of them is asking is the same: how do we show up when a consumer asks AI Mode “best running shoes under $100,” or Gemini “what’s the cheapest flight from New York to Tokyo next weekend,” or ChatGPT “which payment app is safest for recurring subscriptions”? Much of the public writing on Answer Engine Optimization (AEO) and Generative Engine Optimization (GEO) is surface-level — trend surveys, long lists of “factors,” limited implementation depth. The engineering underneath is concrete and testable. The way to get it right is to build it on a site you control, read the Search Console signals that come back, and iterate against what the surfaces actually index.
This post is the engineering write-up. Where my site changed, I’ll show the diff. Where the conventional advice is wrong or too shallow, I’ll say so.
A note on shelf life. The specific numbers and product names in this post will drift — AI Overview citation rates, crawler names, dashboard features, exact schema properties — these change on quarterly cycles. The architecture underneath doesn’t. Retrieval-plus-generation systems reward the same properties they’ve rewarded since the first RAG systems shipped: structured, verifiable, fresh, entity-resolvable, cleanly fetchable content. Read the sections below as “here is how a retrieval-plus-generation system evaluates my site right now,” not “here is a list of tactics that will look the same in 2028.” The tactics evolve. The substrate principles don’t.
The shift, priced in three numbers
Citation is now worth more than rank. Content cited in a Google AI Overview earns roughly 35% more organic clicks than the page that ranks #1 for the same query without a citation, and 91% more paid clicks in adjacent ad slots (wellows.com). Nearly half of AI Overview citations come from pages ranking below position #5, so the citation surface is genuinely independent of classical rank — a page ranking #8 can show up in the AI Overview while the #1 doesn’t.
Bing is the ChatGPT pipeline. Approximately 92% of ChatGPT search queries route through the Bing Search API, and 87% of SearchGPT citations match Bing’s top organic results (cbwebsitedesign.co.uk). Optimizing for ChatGPT search is, mechanically, optimizing for Bing first.
LinkedIn is now the #2 LLM citation source. As of early 2026, LinkedIn has overtaken Wikipedia in LLM citation frequency, ahead of every major news publisher (wireinnovation.com). Surface area on LinkedIn now feeds the LLM training and retrieval pipelines that produce your AI citations elsewhere.
Every optimization below is downstream of one of those three numbers. The magnitudes will shift as the surfaces evolve; the direction — citation over rank, push-indexing over wait-for-crawl, verified-entity authorship over anonymous content — is durable.
Google AI Mode and the Gemini pipeline (the surface that matters most)
Because Google AI Mode is the primary consumer-facing AI search surface and the one most of my customers’ organic traffic depends on, it deserves more than a paragraph.
AI Mode is powered by Gemini’s query fan-out architecture: the user’s query is decomposed into roughly a dozen parallel sub-queries, each retrieved independently against the Google index (plus topical sub-indexes), then the retrieved passages from all fan-out branches are merged, re-ranked, and compressed into the answer (upgrowth.in). A page doesn’t compete for “one query” anymore — it competes across the entire decomposition surface.
The practical implications are specific:
Passage-level structure wins over page-level optimization. Because fan-out retrieves passages, not pages, a single sharp paragraph that answers a sub-query can be cited even if the rest of the page is mediocre. Google’s AI Overview generation favors self-contained passages in the 134–167 word range — the “semantic unit” size the synthesizer prefers for a standalone answer (wellows.com). Write each H2 section as a passage that, read in isolation, still answers the sub-question its heading implies.
E-E-A-T flows through the Knowledge Graph. Roughly 96% of AI Overview content comes from sources Google considers verified entities (clickrank.ai). “Verified entity” here means Google’s Knowledge Graph can cross-reference the author across multiple authoritative sources — LinkedIn, GitHub, Google Scholar, Wikidata, Credly, Crunchbase, academic repositories, organizational profiles. If the graph can’t confidently resolve who wrote your page, the page gets filtered before generation, not at the ranking stage. This is the single largest gap between “ranks well” and “gets cited.” (More on the schema graph below.)
Entity density beats keyword density. Gemini’s grounding layer evaluates content by how many connected entities a page references. Pages with 15 or more entities that Google’s Knowledge Graph can resolve show roughly 4.8× higher selection probability for AI Overview citation compared to pages built around keywords (hypesuite.ai). The practical move: when you mention a technology, product, person, or concept, use the Wikipedia-canonical name and, where natural, link to the authoritative source. You are not writing for a lexical matcher; you are writing for an entity resolver.
The April 2026 algorithm update tightened two things. First, first-hand experience signals (original research, primary data, named-author commentary) were weighted up. Second, the site-level Core Web Vitals aggregation introduced in March means one slow section can suppress the entire domain’s AI Overview eligibility (seovendor.co). Substrate quality is now a gating factor, not a tiebreaker.
Google’s crawlers for the AI pipeline are separate from classic Googlebot. You want all of these allowed in robots.txt: Googlebot (classical index), Google-Extended (Gemini training), Google-CloudVertexBot (Vertex AI grounding), and Gemini-Deep-Research (the research agent inside AI Mode that performs multi-step retrieval for complex queries). Blocking Google-Extended removes you from Gemini training without affecting classical Google rank — it’s a publisher choice a few large publications have made and that costs them AEO visibility.
The operational dashboard: Search Console for AI Mode
Google Search Console remains the primary dashboard for AI Mode performance, with two reports worth watching weekly:
- Search performance → Search Appearance filter. AI Overview appearances are now a filter value. Query-level impressions for “Search Appearance: AI Overview” tells you which queries you’re being cited on and which you’re not.
- Enhancements → Breadcrumbs / FAQ / Article. Schema validation errors here directly affect AI Mode eligibility. A critical-severity breadcrumb error removes the breadcrumb from AI Overview cards; a malformed
BlogPostingcan remove the author attribution entirely.
When I first validated this site in Search Console I had three invalid breadcrumb items — the error was “Either ’name’ or ‘item.name’ should be specified in ‘itemListElement’.” The cause was mundane and the kind of bug that’s easy to miss: on root-level single pages (/about/, /contact/, /privacy/) my .Section variable was the empty string, and the template emitted a ListItem with "name": "" and "item": "https://vikasmishra.ai//" (double slash). The fix was to detect the root-level case and skip the middle breadcrumb entirely, emitting [Home, Title] instead of trying to manufacture a section level that doesn’t exist. Search Console picked the fix up within 24 hours and flipped the items from Invalid to pending-revalidation. I mention the debug trace because it’s representative — almost every real AEO problem is a template edge case that the validator finds once you send it the right URL.
What this looks like at digital-native scale
A personal blog is a clean pedagogical example but the real stakes are at catalog scale. The substrate patterns are the same; the execution changes in ways that are worth walking through, because “add schema” is a one-liner for a blog and a multi-quarter platform project for a marketplace.
E-commerce and marketplaces (millions of SKUs). The citation queries that move revenue are category-level and comparison-level: “best noise-cancelling headphones under $200,” “Adidas vs Nike running shoes for marathon training,” “cheapest 55-inch 4K TV with HDMI 2.1.” Gemini answers these by retrieving passages from product detail pages (PDPs), category pages, and editorial buyer’s-guide content, then grounding them against Product schema and current Offer schema. The work to be citable:
Product+Offer+AggregateRatingschema on every PDP, with price, availability, SKU, GTIN, brand, and review aggregate. Gemini’s grounding layer validates prices against the schema before citing — stale schema makes the page ineligible, not lower-ranked. ThepriceValidUntilfield matters more than most implementations realize.ItemListschema on category pages with orderedProductreferences. This is how category pages show up in AI Mode’s comparison answers.- Fresh pricing pushed via IndexNow on every price or stock change. At catalog scale this means wiring IndexNow into the PIM (product information management) layer, not the CMS. A price that changes every 10 minutes in your inventory system but updates in Google’s index 48 hours later is a citation loss every time someone asks Gemini about the item in that window.
- Category-scoped
llms.txtrather than a monolithic one. A singlellms-full.txtfor a million-SKU catalog is useless to an AI agent. Split by category:/electronics/llms.txt,/fashion/llms.txt, each listing the top N canonical pages in that category with descriptions. Category-level editorial content (buyer’s guides, brand pages) belongs in these files; individual PDPs do not. - Editorial buyer’s-guide content is the highest-leverage content investment. Category “best X” guides with real reviewer credentials, passage-level structure, and
Review+AggregateRatingschema get cited by AI Mode at rates that PDPs never do. Vertical-specialist marketplaces that have leaned into this early — Nykaa’s beauty category content is a strong example, with reviewer-attributed comparisons and ingredient-level schema on each guide — pick up citation share that generalist marketplaces miss. The investment ratio most marketplaces should run: one strong editorial guide per category outperforms ten thousand incremental PDP metadata optimizations.
Online food delivery. Three-way local intent dominates: user location, cuisine, delivery-time tolerance. Queries look like “best ramen near me,” “DoorDash vs Uber Eats for vegan delivery in Brooklyn,” “which late-night restaurants deliver after midnight in Shoreditch.” Across markets the pattern is identical — what changes is the platform name (Zomato, DoorDash, Deliveroo, Uber Eats, Just Eat, Swiggy) and the city. The most mature implementations I’ve looked at tend to ship richer Restaurant and Menu schema coverage than the average — Zomato’s restaurant entity graph, with cuisines, menus, reviews, and neighborhood LocalBusiness signals all tied together, is a useful reference point for what “done well” looks like in this vertical. The work:
Restaurant+LocalBusiness+Menu+MenuItemschema with hours, cuisines, price range, and accurate geo coordinates. The geo coordinates feed AI Mode’s local grounding and Google Maps retrieval simultaneously.AggregateOfferschema for delivery zones and current availability. Platforms that ship this get cited; platforms that don’t get omitted when the user’s intent includes “deliver now.”- Freshness of availability is a hard gate. If your
availability: InStockoravailability: OutOfStockis stale, Gemini’s answer will either be wrong (citation liability) or Gemini will skip you (citation loss). Real-time schema updates via IndexNow or structured-data sitemaps are table stakes here, not a nice-to-have. - Reviews are the single largest local-citation lever.
Reviewschema tied toRestaurantentities, with verified reviewer signals (name, date, platform@id). Don’t fake it —Reviewspam is the highest-detection-rate category of structured-data fraud and Google’s penalty pipeline routes through manual actions, not just rank suppression.
Travel (OTAs, airlines, hotel aggregators). Real-time inventory, dynamic pricing, heavy local intent, and a citation economy where being the attributed source for “best time to visit Kyoto,” “cheapest flight from London to Lisbon next month,” “hotels near the Colosseum with airport transfer” is worth significant revenue. The travel category is unusually global in its schema practices — the larger OTAs and aggregators (MakeMyTrip, Booking.com, Expedia, Airbnb, Trip.com, Kayak) all ship structured data at a comparable level of maturity, and the competitive differentiation is no longer in the basics but in destination-entity linking, fare freshness, and editorial content quality. MakeMyTrip in particular has invested heavily in the destination-editorial side (travel guides with structured TouristDestination linking and named-author bylines), which is the surface that Gemini’s destination queries reach for. The work:
Flight,LodgingReservation,TouristDestination,Tripschema with accurate schedules, prices, and availability.- Rich editorial destination content with
Place+TouristDestinationentity linking to Wikidata or Google Places. AI Mode’s destination answers lean heavily on entity-resolved places; descriptions that name places by their Wikipedia-canonical names and link to authoritative sources win citation weight. - Fare freshness. Travel is the vertical where
dateModifiedmatters most. A fare page updated 48 hours ago will not be cited when Gemini can find the same fare updated 48 minutes ago on a competitor. The IndexNow pipeline needs to be wired into the fare cache, not the content CMS. - Review schema on properties and itineraries, with verified traveler signals. Same cautions as food delivery — real reviews win, manufactured ones eventually trigger manual action.
Fintech (payments, lending, insurance, investing). The YMYL category — “Your Money or Your Life.” Google’s E-E-A-T evaluation is strictest here and AI citation eligibility is gated on verified authorship and regulatory disclosures. Fintech customers who ignore this show up in AI Overviews at a fraction of the rate of their YMYL-disciplined competitors. The work:
- Author bylines are not optional; they are the primary eligibility signal. Every article, blog post, help doc, and product page that explains a financial concept needs a named author with a
Personschema that includes verified credentials (hasCredentialwithcredentialCategory: "verified"andrecognizedBypointing at the relevant regulator — SEC or FINRA in the US, FCA in the UK, BaFin in Germany, ESMA at the EU level, MAS in Singapore, RBI or SEBI in India — or at a recognized professional body in the jurisdiction). FinancialProduct+FinancialService+BankAccount+LoanOrCreditschema with full disclosure fields: interest rates, fees, terms, and regulator registration IDs.Dataset+Articlecitation chains for any statistic your content relies on. Unsourced financial claims are filtered before generation in Gemini’s YMYL quality pipeline. Sourced ones withcitationschema pointing at the primary data provider (central bank data, regulator disclosures, government statistics agencies, consumer protection reports) are both eligible and preferred.- Help Center and FAQ pages are the citation workhorses, not blog posts. The queries that matter — “is a mandate-based recurring payment safe,” “how do I dispute a credit card charge,” “what happens if I miss a tax filing deadline” — resolve to help-center content in Gemini’s answers. FAQ schema on those pages is the one place FAQ schema is still unambiguously worth shipping.
Organizationwith regulator registrations insameAsand accurateaddress,vatID,taxID,legalNamefields. For EU brands, thevatIDand the registered-officeaddressare primary entity-resolution signals; for US brands, the SEC EDGAR CIK and the state-of-incorporation registration are the equivalents. Make the cross-reference easy for Google’s entity resolver to perform.
Across all four verticals, one pattern: the schema data plane has to be wired into the operational system of record, not into the CMS. Prices, inventory, availability, fares, menus, interest rates, property photos — all of these change outside the CMS. If your schema updates lag the operational state by more than a few minutes, your AI-citation eligibility lags accordingly. This surfaces as an SEO problem but the root cause is platform engineering. Teams that scope the work only as a content-marketing program tend to underinvest in the substrate that actually determines whether the content can be cited at all.
What the other surfaces do differently
ChatGPT search and Bing Copilot share a backend. The path is: your page → Bing index → Bing’s AI re-ranker → OpenAI’s or Microsoft’s generation layer → citation. The February 2026 AI Performance report inside Bing Webmaster Tools is the only citation-attribution dashboard any search platform has shipped so far — it tells you, per URL, how often your page was cited by Microsoft Copilot and Copilot-powered partner surfaces (blogs.bing.com). Set up Bing Webmaster Tools if you haven’t. The IndexNow key (below) verifies ownership automatically.
Perplexity runs its own crawler (PerplexityBot) plus partner feeds, and its re-ranking model is the most freshness-biased of the four. Perplexity will prefer a page that was updated last week over a page with higher authority that was updated last year when the factual content is comparable. Stale dateModified drops you from Perplexity more aggressively than from Google.
Claude is the least transparent. ClaudeBot crawls aggressively but Anthropic doesn’t publish source-selection behavior. The defensive play is to make your content maximally fetchable for any agentic system — see the markdown-alternate section below.
You don’t choose one surface to optimize for. Most of the substrate work counts across all of them.
The schema graph (and the @id mistake that breaks it in production)
Almost every “AEO best practices” post recommends adding Article schema and Person schema. That advice is incomplete in a way that breaks the schema in production.
Structured data on a modern site is a graph. Each entity gets a stable @id (typically a URL fragment such as https://vikasmishra.ai/#person). Other entities reference that @id instead of restating the underlying fields. A BlogPosting’s author field points at the Person’s @id; the Person’s mainEntityOfPage points at the ProfilePage’s @id; the ProfilePage’s mainEntity points back at the Person. The WebSite is declared once and every BlogPosting is isPartOf it.
What goes wrong: most sites declare the Person schema only on the home page or only on /about/, but reference #person from the Article schema on every blog post. The reference dangles. When Google’s structured-data extractor fetches a blog post, it sees "author": {"@id": "https://example.com/#person"} and no #person entity on that page. The author claim doesn’t resolve to a named Person; the Person’s credentials and sameAs graph don’t attribute to the article; the authorship signal Google’s E-E-A-T evaluator explicitly weighs is absent for every post.
I caught this on my own site when I audited the JSON-LD graph across URLs. The fix is to emit Person and WebSite on every page — they’re cheap, and they make every @id reference resolve on every URL. The head template now looks like this:
{{/* Emit on every page so @id references resolve site-wide.
Before this change, #person was only declared on the home page;
the Article.author.@id reference on blog posts dangled. */}}
{{ partial "schema/website.html" . }}
{{ partial "schema/person.html" . }}
{{ if .IsHome }}
{{ partial "schema/faq.html" . }}
{{ else }}
{{ partial "schema/breadcrumb.html" . }}
{{ if .IsPage }}
{{ if eq .Section "blog" }}
{{ partial "schema/article.html" . }}
{{ end }}
{{ if eq .RelPermalink "/about/" }}
{{ partial "schema/profile-page.html" . }}
{{ end }}
{{ if .Params.faq }}
{{ partial "schema/faq-page.html" . }}
{{ end }}
{{ end }}
{{ end }}
That emits a fully-connected graph on every URL. On a blog post the graph resolves: BlogPosting → author → Person → mainEntityOfPage → ProfilePage → mainEntity → Person (closes the cycle), plus publisher → Person, isPartOf → WebSite, and a separate BreadcrumbList with its own @id referenced from ProfilePage.breadcrumb when applicable.
Validate every schema change in both Google’s Rich Results Test and the Schema.org validator. They disagree on edge cases; Google’s validator tells you what Google will actually use, the Schema.org validator catches spec violations Google doesn’t flag.
A debugging story: the double-escape
I ran into a second schema bug that’s worth recounting because it’s easy to miss and the fix is counterintuitive.
I refactored the BreadcrumbList template to use Hugo’s jsonify function on the name field, expecting it to produce safe JSON. It didn’t. The rendered output was:
{"@type":"ListItem","position":2,"name":"\"About Vikas Mishra\"","item":"..."}
The name value was the string "About Vikas Mishra" including the quote characters, rather than About Vikas Mishra. Hugo’s context-aware auto-escaping inside <script> blocks was treating jsonify’s output as HTML and re-escaping the quotes, turning the JSON string literal into a string that contained quotes. The fix was to drop jsonify on simple title fields and use plain interpolation ("name": "{{ .Title }}"), reserving jsonify for values that might contain actual quote characters. Subtle, and the kind of thing that only surfaces when a human reads the rendered HTML or Search Console flags the item as invalid.
The schema types that actually earn citations
Stop spraying every type onto every page. In priority order for AEO:
BlogPosting(notArticle—BlogPostingis the more specific subtype Google uses for blog content in AI Overviews) with inlineauthorandpublisher,image,datePublished,dateModified,wordCount,articleSection,keywords,inLanguage,timeRequired, andisAccessibleForFree.PersonwithsameAslinking to every authoritative profile, plushasCredentialfor verified certifications,worksFor,alumniOf,knowsAbout, andmainEntityOfPagepointing at the ProfilePage.ProfilePageon the canonical About URL. Per Google’s February 2026 Authors documentation update, this is now an explicit quality signal for authorship attribution.BreadcrumbListon every non-home page.WebSitedeclared once, referenced from every page.FAQPageonly on pages that genuinely answer recurring questions. Google has been cracking down on spammy FAQ schema since 2023 and over-application is a quality signal in the wrong direction.speakableas a property insideBlogPosting— the AEO-specific property most sites still don’t ship.
HowTo schema lost most of its rich-result eligibility in the March 2026 update; skip it unless your content is genuinely a numbered procedure.
Speakable: the AEO property that nobody ships
speakable is a property inside BlogPosting or Article that uses CSS selectors to identify which parts of the page are best for text-to-speech. Google Assistant and the AI Overview audio experience use it to decide what to read aloud. The AEO-relevant implication is stronger: the synthesizer treats the speakable selector output as the canonical short-form version of your content. If it has to compress your 2000-word post into a two-sentence answer, the speakable output is where it starts.
The selector pattern that works for most blog layouts:
"speakable": {
"@type": "SpeakableSpecification",
"cssSelector": [
"h1",
".prose-custom > p:first-of-type",
".prose-custom h2"
]
}
That picks the title, the lead paragraph (usually the TL;DR), and the H2 headings (usually short claims). Roughly 62% of 2026 search queries involve voice in some form (fysalyaqoob.com) — omitting speakable forfeits that surface entirely.
Writing consequence: compose your lead paragraph as a self-contained answer, not a hook. The first paragraph should work as a standalone summary when read aloud. Both my recent posts now open this way, deliberately.
llms.txt and llms-full.txt (the AI ingestion files)
The llms.txt proposal defines a markdown file at /llms.txt that gives an AI agent a structured directory of your site. None of the major LLMs has officially committed to using it as a primary input yet, and reasonable skepticism exists in the community about whether it changes anything. The implementation cost is low, though, and the companies betting on it — Anthropic, Cloudflare, Stripe, Zapier, Mintlify — are the same companies that typically set tooling norms in this space. Over 844,000 sites had implemented it by late 2025 (searchengineland.com). The expected value is positive and the marginal cost is close to zero.
The spec is strict and most implementations get it wrong:
- H1 with the project or site name (the only required section).
- Blockquote with a one-paragraph authoritative summary.
- H2 sections containing markdown link lists, one link per line, each followed by a colon and a concise description of what that page answers. Recency-first for blog sections.
- An optional “Optional” section at the end pointing to deeper resources.
The common failure mode: treating llms.txt as a bio blob, dumping CV paragraphs into it. The spec wants a smart table of contents — canonical pages, descriptions that tell the agent what each page answers.
llms-full.txt is the companion file that compiles every relevant page inline as one big markdown document. Anthropic’s is 481,349 tokens; Cloudflare ships one per product vertical. For a personal site or product docs, this is the single highest-leverage AI-ingestion surface: one URL pastes the full site context into ChatGPT, Claude, or any agent.
I generate both from Hugo at build time:
{{/* llms.txt template — spec-compliant, generated every build */}}
# {{ .Site.Title }}
> {{ .Site.Params.description }}
## Recent writing
{{- range first 25 (where .Site.RegularPages "Section" "blog").ByDate.Reverse }}
- [{{ .Title }}]({{ .Permalink }}): {{ .Description | plainify }}
{{- end }}
{{/* llms-full.txt template — compiles every post inline */}}
# {{ .Site.Title }} — Full Content for AI Ingestion
{{ range (where .Site.RegularPages "Section" "blog").ByDate.Reverse }}
### {{ .Title }}
- Published: {{ .PublishDate.Format "2006-01-02" }}
- URL: {{ .Permalink }}
{{ .RawContent }}
---
{{ end }}
Total work: about 70 lines of template, regenerated on every deploy. Mine is live at /llms.txt and /llms-full.txt.
Per-page raw markdown alternates
The single underrated move in 2026 is exposing every page as raw markdown alongside the HTML. Hugo lets you do it with a custom output format:
[outputFormats.MARKDOWN]
name = "MARKDOWN"
mediaType = "text/markdown"
baseName = "index"
isPlainText = true
rel = "alternate"
[outputs]
page = ["HTML", "MARKDOWN"]
That produces https://vikasmishra.ai/blog/<slug>/index.md for every post, served as text/markdown. Advertise the alternate in <head>:
<link rel="alternate" type="text/markdown"
href="https://vikasmishra.ai/blog/<slug>/index.md">
Why it matters: agentic AI fetchers (Perplexity, ChatGPT browsing, Claude, increasingly Bing’s grounding layer) prefer raw markdown over HTML scraping. The fetch is faster, content extraction is exact, structure (headings, code blocks, lists) is preserved without the noise of nav/footer/scripts. Pages that ship .md alternates get pulled cleanly; pages that don’t get HTML-stripped, often badly. Ask ChatGPT or Claude to “fetch and summarize” a blog post URL — the agent that grabs the .md returns a noticeably more accurate summary than one fetching the HTML.
This is the pattern Mintlify popularized for docs and Cloudflare now serves across all of developers.cloudflare.com. Within twelve months it will be a default expectation for AI-indexable content.
IndexNow: the ChatGPT pipeline most sites haven’t set up
Bing’s standard crawl interval is days to weeks depending on your crawl budget. IndexNow shortens that to minutes for any URL you push, and because 92% of ChatGPT search goes through Bing, IndexNow is functionally the release pipeline for getting into ChatGPT citations.
IndexNow (indexnow.org) is a push-based protocol Microsoft introduced. Bing, Yandex, Naver, Seznam, and a handful of smaller engines participate. Setup is three steps:
- Generate a 32-character hex API key.
- Host a verifier file at
https://<your-domain>/<key>.txtcontaining the key as the body. - POST JSON payloads with changed URLs to
https://api.indexnow.org/IndexNow.
The ping script I wired into my deploy:
#!/usr/bin/env bash
# Parses the last 7 days of sitemap entries and submits to IndexNow.
# Bing re-crawls within minutes; ChatGPT search citations follow.
set -euo pipefail
HOST="vikasmishra.ai"
KEY="67b195f48d581df4cde76566232326a2"
URLS=$(python3 parse_sitemap.py --since 7)
PAYLOAD=$(python3 -c "import json,sys; print(json.dumps({
'host': '$HOST',
'key': '$KEY',
'keyLocation': 'https://$HOST/$KEY.txt',
'urlList': '''$URLS'''.strip().split()
}))")
curl -sS -X POST https://api.indexnow.org/IndexNow \
-H "Content-Type: application/json" \
--data "$PAYLOAD"
Called after every production build. Failures are non-fatal so they can’t block a deploy. The observable effect in Bing Webmaster Tools’ crawl log is a drop in mean-time-to-crawl from days to under ten minutes, and in the AI Performance report a corresponding compression of the delay between publish time and first citation appearance.
Visible E-E-A-T (because schema-only authorship is weak)
Google’s February 2026 update to Search Central’s Authors documentation was the clearest signal yet that authorship is a direct quality consideration in ranking and AI citation. The schema-only version — Article.author referenced by @id — is necessary but not sufficient. The visible, on-page version is what Google’s quality models actually weigh.
What “visible” means on a blog post:
- Byline at the top with the author’s name, role, and a link to the canonical About page. Avatar optional but useful.
- Author bio block at the bottom with a paragraph of credentials, links to other posts by the same author, and outbound links to authoritative profiles (LinkedIn, GitHub, university page, Google Scholar, Credly).
- Microdata
itemprophints on the visible markup as a belt-and-suspenders complement to JSON-LD. Older parsers and some AI fetchers still read microdata.
I shipped both bylines on this site. The byline includes the author’s role with the employer because AEO surfaces weight employer affiliation as a topical-authority signal — a post on cloud architecture written by someone with a visibly-attributed cloud architect role at a cloud provider gets weighed higher than the same post from an unaffiliated writer. Disclaimers about the employer not endorsing the content go in the post body, not the byline; the byline is the credential signal, the disclaimer is legal hygiene.
The deeper play is entity verification via Google’s Knowledge Graph. Authors are classified as “verified entities” when the graph can cross-reference your identity across multiple authoritative sources, or unverified when it can’t. Verification raises the citation eligibility floor. The mechanism is sameAs: your Person schema’s sameAs array should list every authoritative URL that’s about you. The strongest sameAs target is Wikidata, because Wikidata is a primary input to Google’s Knowledge Graph. A Wikidata entry with sameAs back to your site closes the verification loop from both directions.
If you don’t have a Wikidata entry, create one with your notable work and third-party citations. Don’t claim a Wikidata ID in sameAs that doesn’t exist — an invalid sameAs value is worse than a missing one; Google’s entity resolver treats it as a negative signal.
Open Graph for the AI age
The default og:image in most Hugo themes is the site portrait. That’s wrong for blog shares. The portrait belongs on pages where the person is the subject — home, about, contact. For a blog post, the share preview should communicate the topic of the post, not the face of the writer.
I ship a per-section default. Blog posts and section index pages use a branded 1200×630 terminal-themed PNG generated from a 100-line Pillow script in tools/gen_og_blog.py. Home and root pages keep the portrait. Per-post image: frontmatter still overrides everything. Rebuilding the card is a single command, which matters because the card design will need iteration as you learn what drives click-through.
Caching detail people miss: X, LinkedIn, and Facebook aggressively cache OG previews per URL. If you’ve shared a URL with the wrong card, the cached preview persists. Appending ?v=2 (or any throwaway query parameter) when re-sharing forces a fresh fetch.
The advanced version is per-post auto-generated OG cards with the post title rendered onto the canvas. Hugo’s images package supports composition via images.Filter and images.Text. Worth the build-time cost if your blog covers wildly different topics per post; not worth it otherwise.
Robots.txt: explicit > implicit
User-agent: * with Allow: / already permits AI crawlers. Explicit allows are stronger because (a) they make your crawl logs auditable — you can see in access.log which AI crawlers actually showed up; (b) they survive future spec changes where a crawler honors a more granular directive; and (c) they signal intent to other engineers and security teams reading the file. The 2026 list I keep current on this site:
# Google
User-agent: Googlebot
User-agent: Google-Extended # Gemini training
User-agent: Google-CloudVertexBot # Vertex AI grounding
User-agent: Gemini-Deep-Research # AI Mode multi-step research agent
# OpenAI
User-agent: GPTBot # Training
User-agent: ChatGPT-User # Browsing
User-agent: OAI-SearchBot # ChatGPT search
# Anthropic
User-agent: ClaudeBot # Training
User-agent: Claude-User # Browsing
User-agent: Claude-SearchBot # Search
# Microsoft / Bing
User-agent: bingbot
User-agent: msnbot
# Apple Intelligence
User-agent: Applebot-Extended
# Perplexity
User-agent: PerplexityBot
User-agent: Perplexity-User
# Others
User-agent: meta-externalagent # Meta AI
User-agent: Amazonbot # Alexa / Q
User-agent: DuckAssistBot
User-agent: MistralAI-User
User-agent: cohere-ai
User-agent: YouBot # You.com
User-agent: KagiBot
User-agent: BraveBot
User-agent: Diffbot # Knowledge graph
User-agent: xAI-Bot
User-agent: GrokBot
User-agent: CCBot # Common Crawl
Each gets Allow: /. If any section shouldn’t be AI-indexed (paid content, internal docs), use Disallow: inside the relevant User-agent: block — not site-wide. Large publishers have accidentally made themselves invisible to LLMs by adding User-agent: * Disallow: / during a site migration and forgetting to remove it.
Sitemap priorities, lastmod, and the freshness signal
A sitemap with flat priority: 0.5 and no lastmod signals nothing. Hierarchical priorities and accurate lastmod change crawl behavior at every major engine.
| Page type | Priority | Changefreq |
|---|---|---|
| Home | 1.0 | daily |
Section index (/blog/, /talks/) | 0.9 | daily/weekly |
| Blog posts | 0.8 | weekly |
| About, Contact, Resume | 0.8 | monthly |
| Projects | 0.7 | monthly |
| Secondary (Photos, Reading, Privacy, Terms) | 0.6 | monthly |
lastmod should derive from actual content modification time, not build timestamp. In Hugo, enableGitInfo = true makes Lastmod come from git history; every post’s lastmod reflects its last meaningful edit automatically. That same value feeds dateModified in BlogPosting schema and og:updated_time in the head. One source, three downstream signals.
Google’s AI Mode and Perplexity both use freshness as a re-ranking lever. Stale lastmod drops you against the same claim written this month. And show the freshness to humans — my blog post header renders Updated <date> between the publish date and reading time when Lastmod > Date, which also confirms to any AI fetcher that the visible content matches the schema claim.
Core Web Vitals in 2026 (site-level, and tighter)
The March 2026 Google update tightened Core Web Vitals scoring in two ways worth internalizing:
- LCP “good” threshold dropped from 2.5s to 2.0s. Anything between 2.0 and 2.5 used to pass; it’s now “needs improvement.”
- Site-level aggregation replaced page-level scoring. Google now evaluates CWV across your whole domain. One slow section can suppress the entire domain’s AI Overview eligibility, not just that page’s rank.
For static sites with a modern build, CWV passes with margin. The two places that trip up Hugo sites:
- Font loading. Three weights of two font families blows LCP. Subset, self-host, or use
font-display: optional. - INP (Interaction to Next Paint). Third-party analytics and hover-driven JS are usually the culprit. Defer non-essential JS; use
<link rel="preconnect">for analytics endpoints to shave first-paint cost.
CLS (Cumulative Layout Shift) is solved by explicit width and height on every image so the browser reserves space before load. Should be standard by now; audit if you’re not sure.
What to skip, and the dark patterns that will cost you rank
Skip (low or negative ROI):
- FAQ schema on every page. Google has deprecated FAQ rich results since 2023 and over-application is a quality signal in the wrong direction. Use FAQ schema only on pages that genuinely answer recurring questions.
- HowTo schema for non-instructional content. Lost most rich-result eligibility in March 2026.
- Stuffed
keywordsproperty in Article schema. Essentially ignored now; Google’s entity extractor pulls topics from actual content. - Multiple
Personschemas on the same page. Route every reference through one canonical@id. - Wikidata
sameAspointing at non-existent IDs. Negative signal. Either create the Wikidata entry or omit the field.
Avoid (these will get you penalized):
- Cloaking AI bots with content different from what users see. Modern cloaking is detectable by fingerprinting, the penalty is severe, and the EU Digital Services Act now imposes fines up to 6% of global revenue for manipulative interfaces (techcrunch.com). Risk-adjusted return is negative.
- Bulk AI-generated content with no human review. The April 2026 algorithm update placed a premium on first-hand experience signals. AI-rewritten pages without depth get filtered before generation.
- Schema that doesn’t match visible content. Explicit Google Webmaster Guidelines violation: misleading structured data. Your
BlogPosting.authorhas to match the visible byline. YourdatePublishedhas to match the visible date. - Generated
RevieworRatingschema you don’t actually have. Highest-detection-rate spam pattern in Google’s evaluation pipeline.
The throughline: AEO rewards sites that make true claims with rich structure. It penalizes sites that try to game the structure to make false claims look true.
The ship order
If I were starting from a clean Hugo site tomorrow, I’d ship the work in this order:
- Foundations. Robots.txt with the full AI crawler allowlist. Sitemap with hierarchical priorities.
enableGitInfo = truesolastmodis automatic. - Schema graph.
WebSiteandPersonon every page,BlogPostingon every blog post with inlineauthorandpublisher,BreadcrumbListon every non-home page,ProfilePageon/about/. Validate every change in Google’s Rich Results Test before pushing. - Visible E-E-A-T. Author byline at the top of every post, bio block at the bottom, visible
Updated <date>when content has been revised, microdataitemprophints to complement JSON-LD. - AI ingestion files.
llms.txtto spec, generated at build time.llms-full.txtcompiling all blog posts inline. Per-page.mdalternates advertised via<link rel="alternate">. - IndexNow. Key + verifier file + ping script wired into deploy. Verify in Bing Webmaster Tools AI Performance.
- Speakable. Property inside BlogPosting with cssSelectors for title, lead, and H2s. Rewrite leads as standalone answers.
- OG cards. Per-section defaults that reflect content, not portraits. Per-post overrides via frontmatter.
- Operate. Google Search Console weekly. Bing Webmaster Tools weekly. Watch which URLs get cited and iterate.
Most teams I’ve worked with lean heavily toward new content production and underinvest in the substrate that determines whether the content is eligible to be cited. The substrate work compounds across every piece of content you ever publish; the content work doesn’t. A more even split between the two is usually the higher-return rebalance.
The durable principles (read this section if you read nothing else)
Specific schema property names change. Crawler names change. Rich-result eligibility rules change on the March and September algorithm cycles. The principles that sit under all of that have been stable through several generations of search architecture and will stay stable through several more. If you build against these, the tactical changes become minor maintenance instead of quarterly rewrites.
Make your content retrievable in the format the retriever prefers. In 2026 that means HTML plus a markdown alternate. In 2028 it will mean HTML plus markdown plus whatever structured-data formats agentic systems converge on. The principle is: expose the cleanest-possible representation of your content to any system that might fetch it. That principle was true for XML feeds in 2006, RSS in 2010, AMP in 2018, JSON-LD in 2022, and markdown alternates in 2026. It will be true for the next format.
Declare a connected, verifiable entity graph — not isolated JSON-LD blocks. Every entity has one canonical
@id; every reference resolves. This is just data modeling hygiene, and data modeling hygiene has never gone out of style. The specific types (Person,ProfilePage,BlogPosting) will evolve; the graph discipline stays the same.Make the author a verifiable entity across the open web.
sameAsto the authoritative profiles that already know who you are. Bidirectional links so any system doing entity resolution can confirm the claim. The platforms that carry authority will rotate — Wikipedia, LinkedIn, Wikidata, Google Scholar, whatever comes next — but cross-reference across multiple authoritative sources has been how identity is established since the open web existed.Keep content fresh by default, and show freshness to machines and humans alike. Accurate
lastmodin the sitemap.dateModifiedin schema. Visible “Updated X” in the rendered page. This is how every retrieval system ranks recency, and every retrieval system will rank recency as long as fresh is ever preferred over stale.Push updates instead of waiting to be crawled. Today that means IndexNow for Bing and the broader OpenAI/Microsoft surface. The specific protocol will evolve; push-indexing as a pattern won’t. If a search engine offers a push channel, use it — the payoff is always faster time-to-citation.
Write for passage retrieval, not page retrieval. Retrieval-plus-generation systems retrieve passages and synthesize. Every self-contained section, every H2 with a clean standalone answer underneath, is a separate retrieval target. This is true for any retrieval system that operates at sub-document granularity, and all of them do now.
Match the on-page signal to the structured-data claim. If your schema says the author is Dr. X, the byline says Dr. X. If
datePublishedsays April 2026, the visible date says April 2026. Google’s “misleading structured data” penalty has been on the books for years and the AEO-era quality models apply it more aggressively, not less.Favor substrate investment over content volume. Ten posts on a substrate that earns citations outperform a hundred posts on a substrate that doesn’t. The substrate compounds; the content doesn’t. Teams that rebalance their SEO budget from content-volume to substrate-quality tend to underinvest here even when they’ve read the advice — it feels less productive than shipping new pages. It isn’t.
Closing
Structured-data validators are your tests. Search Console and the equivalent per-surface dashboards are your production telemetry. Push-indexing protocols are your release pipeline. The schema graph is your data model. Each has a deterministic right answer you can implement, validate, and observe — the same workflow any serious engineering team applies to any other production system.
The metric changed: from position in a list to inclusion in a synthesized answer. The engineering required to hit it is harder to hand-wave about than classical SEO was, but it’s measurable at the substrate layer and the returns are larger because an AI Overview citation is worth materially more to a brand than a position-two blue link ever was. For large digital-native businesses — marketplaces, travel platforms, food delivery, fintechs — the outcomes over the next few years will track platform-engineering discipline more than content volume. The schema data plane wired into the system of record, push-indexing protocols in the release pipeline, and the schema graph treated as a first-class data model are platform investments. They compound; new pages don’t.
The stack on this site validates clean in Google’s Rich Results Test. The breadcrumb fix moved from Invalid to pending-revalidation in Search Console within 24 hours of push. The IndexNow-assisted publishes are already landing in Bing’s AI Performance report. Those are the observable outputs of the principles above. When the specific tactics here age, replace the tactics — not the principles.
References
- Google AI Overview ranking factors and citation economics — wellows.com, clickrank.ai
- Google AI Mode query fan-out and Gemini architecture — upgrowth.in, seovendor.co
- Knowledge Graph entity density and
sameAsauthority — hypesuite.ai, 12amagency.com, wireinnovation.com - ProfilePage and Authors schema — Google Search Central
- Speakable specification — Google Search Central
- Core Web Vitals March 2026 update — logoswebdesigns.com
- Bing AI Performance in Webmaster Tools — Microsoft Bing Blog, Feb 2026
- llms.txt specification — llmstxt.org, Anthropic llms-full.txt
- IndexNow protocol — indexnow.org
- Bing / ChatGPT retrieval share — cbwebsitedesign.co.uk, almcorp.com
- Dark patterns and DSA penalties — techcrunch.com