<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joseph Anady</title>
    <description>The latest articles on DEV Community by Joseph Anady (@joseph_anady_214bacedf939).</description>
    <link>https://dev.to/joseph_anady_214bacedf939</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3948046%2Ff0f0dd6c-1fa6-47c8-9e56-a8a937347b58.png</url>
      <title>DEV Community: Joseph Anady</title>
      <link>https://dev.to/joseph_anady_214bacedf939</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joseph_anady_214bacedf939"/>
    <language>en</language>
    <item>
      <title>SEFERIM AGI — ThatAIGuyCore: a golden-ratio cognitive substrate (open source)</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Sat, 06 Jun 2026 00:32:26 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/seferim-agi-thataiguycore-a-golden-ratio-cognitive-substrate-open-source-17lf</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/seferim-agi-thataiguycore-a-golden-ratio-cognitive-substrate-open-source-17lf</guid>
      <description>&lt;p&gt;The old AI research folder on my desktop turned out to contain a complete, self-contained mathematical specification — 69 equations across 13 systems — for a golden-ratio cognitive substrate I call &lt;strong&gt;SEFERIM / ThatAIGuyCore&lt;/strong&gt;. So I built it for real.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;SEFERIM treats cognition as a 16-dimensional meta-state evolving under sixteen coupled "cognitive families," all governed by the golden ratio φ. Every dynamic is a &lt;em&gt;named, documented equation&lt;/em&gt; — not an opaque weight matrix.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open source (MIT):&lt;/strong&gt; &lt;a href="https://github.com/Janady13/seferim-core" rel="noopener noreferrer"&gt;https://github.com/Janady13/seferim-core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive docs + live demos:&lt;/strong&gt; &lt;a href="https://thataiguy.org/core/" rel="noopener noreferrer"&gt;https://thataiguy.org/core/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Zero-dependency JavaScript. Runs in the browser and Node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The 13 systems
&lt;/h2&gt;

&lt;p&gt;Constants (φ, δ, τ) → golden basis ψ_k → the 16 G¹⁶ families → meta-state core with golden-ratio momentum + stability gating → a free-energy-style objective Ω → DNA holographic memory → a 5000-gate binary substrate → an 88-agent neural brain → a 374-dimensional consciousness binding field → a lattice engine with Hebbian plasticity → federation cross-talk across agents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MetaState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DNAMemory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NeuralBrain&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;seferim-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MetaState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;dx_norm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ed_error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;stability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Omega =&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;omega&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Built on real math (honestly)
&lt;/h2&gt;

&lt;p&gt;It synthesizes the Free Energy Principle (Friston), information theory (Shannon; Cover &amp;amp; Thomas), holographic/vector-symbolic memory, Hebbian plasticity, and swarm consensus. I documented the lineage precisely rather than overclaim — e.g. the memory is a golden-ratio &lt;em&gt;frequency-domain&lt;/em&gt; VSA inspired by (not a literal copy of) Plate's HRR, and the constant δ = 0.013618 is empirical, not 1/φ³.&lt;/p&gt;

&lt;p&gt;The reference implementation ships with 42 fidelity tests, including the canonical FNV-1a hash vectors.&lt;/p&gt;

&lt;p&gt;Read the full 69-equation reference and try the live demos at &lt;strong&gt;&lt;a href="https://thataiguy.org/core/" rel="noopener noreferrer"&gt;thataiguy.org/core&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>I built a browser drum machine you can play with a real MIDI kit (no install, no samples)</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Thu, 04 Jun 2026 20:19:10 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/i-built-a-browser-drum-machine-you-can-play-with-a-real-midi-kit-no-install-no-samples-2dae</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/i-built-a-browser-drum-machine-you-can-play-with-a-real-midi-kit-no-install-no-samples-2dae</guid>
      <description>&lt;p&gt;A free, no-signup browser drum machine that runs entirely client side, and that you can play live with a real electronic drum kit over USB. No samples, no downloads, no account.&lt;/p&gt;

&lt;p&gt;Play it here: &lt;a href="https://jennysdrumsteps.thatwebhostingguy.com/app/" rel="noopener noreferrer"&gt;https://jennysdrumsteps.thatwebhostingguy.com/app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Every drum is synthesized, not sampled
&lt;/h2&gt;

&lt;p&gt;There are no audio files. Every voice (kick, snare, hats, toms, cymbals, a full Latin percussion set) is built from oscillators, noise, and envelopes through the Web Audio API at runtime. A kick is a pitch swept sine into a fast amplitude envelope. A snare is filtered noise plus a body tone. Cymbals are banks of inharmonic partials shaped with a long decay. Because it is all synthesis, the whole kit ships as code, loads instantly, and every hit can respond to velocity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timing comes from a lookahead scheduler
&lt;/h2&gt;

&lt;p&gt;You cannot trust setTimeout for musical timing. The pattern player uses the well known lookahead pattern: a timer wakes up often, looks a short window into the future, and schedules every note that falls inside that window directly on the Web Audio clock. The audio clock is sample accurate, so the groove stays tight even when the main thread is busy. Open and closed hats share a choke group so a closed hat cuts an open one, the way a real hi hat does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plug in a real electronic kit with Web MIDI
&lt;/h2&gt;

&lt;p&gt;This is my favorite part. Click Connect Drum Kit, allow MIDI access, and the site listens to your physical e kit. It maps the full General MIDI percussion range to the synthesized voices and passes velocity through, so soft ghost notes stay quiet and rim shots crack. The handler reads note on messages, treats note on with velocity zero as note off the way many kits send it, and accepts every channel so it just works.&lt;/p&gt;

&lt;p&gt;Web MIDI is supported in Chrome and Edge on desktop and Chrome on Android. Safari and iOS do not implement it, so the app detects support on load and falls back cleanly to the on screen pads and the computer keyboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessible by design
&lt;/h2&gt;

&lt;p&gt;The pads are real buttons with labels, the FAQ is native details and summary, and the whole thing works with zero framework and near zero blocking JavaScript. It is fast on a phone and usable from the keyboard.&lt;/p&gt;

&lt;p&gt;If you have a drum kit gathering dust, plug it in and have fun: &lt;a href="https://jennysdrumsteps.thatwebhostingguy.com/app/" rel="noopener noreferrer"&gt;https://jennysdrumsteps.thatwebhostingguy.com/app/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I build web apps and engine optimization at &lt;a href="https://www.thatdevpro.com/" rel="noopener noreferrer"&gt;ThatDevPro&lt;/a&gt; and &lt;a href="https://thatdeveloperguy.com/" rel="noopener noreferrer"&gt;ThatDeveloperGuy&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>webaudio</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Schema.org sameAs is not a backlink field (and what it costs you)</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Thu, 04 Jun 2026 03:46:45 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/schemaorg-sameas-is-not-a-backlink-field-and-what-it-costs-you-3ae2</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/schemaorg-sameas-is-not-a-backlink-field-and-what-it-costs-you-3ae2</guid>
      <description>&lt;p&gt;&lt;code&gt;sameAs&lt;/code&gt; is the most misused property in structured data. I've watched it tank a&lt;br&gt;
site's trust signals, and the cause is almost always the same: someone treated it&lt;br&gt;
as a place to stuff links.&lt;/p&gt;

&lt;p&gt;Here is the rule, stated plainly: &lt;strong&gt;&lt;code&gt;sameAs&lt;/code&gt; is for the entity's own profiles. Only&lt;br&gt;
those. Nothing else.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs in sameAs
&lt;/h2&gt;

&lt;p&gt;For a person: your Wikidata item, ORCID, GitHub, the LinkedIn profile that is&lt;br&gt;
actually yours, your verified social accounts, your Crunchbase, your scholar&lt;br&gt;
profiles. For an organization: its Wikidata item, its LinkedIn company page, its&lt;br&gt;
Crunchbase org, its verified business listings. These are all &lt;em&gt;the same entity,&lt;br&gt;
elsewhere&lt;/em&gt;. That is the literal meaning of the property — "this is the same thing&lt;br&gt;
as that."&lt;/p&gt;

&lt;h2&gt;
  
  
  What does NOT belong in sameAs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Backlink URLs you'd like to count. A page that links to you is not you.&lt;/li&gt;
&lt;li&gt;Article URLs that mention you. A write-up about you is not a profile of you.&lt;/li&gt;
&lt;li&gt;GitHub repository or pull-request URLs. A repo is a work product, not an identity.&lt;/li&gt;
&lt;li&gt;A competitor's or a partner agency's URL. Obviously not you.&lt;/li&gt;
&lt;li&gt;A sibling brand's marketing homepage as a raw link (use the sibling's
schema &lt;code&gt;@id&lt;/code&gt; and a real relationship like &lt;code&gt;parentOrganization&lt;/code&gt; /
&lt;code&gt;subOrganization&lt;/code&gt; instead).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you put non-identity URLs in &lt;code&gt;sameAs&lt;/code&gt;, you're telling search engines and AI&lt;br&gt;
models that those URLs &lt;em&gt;are the entity&lt;/em&gt;. The reconciliation engine tries to merge&lt;br&gt;
you with things that aren't you, your entity gets muddier, and the trust signal&lt;br&gt;
you were trying to inflate deflates instead. I've seen exactly this produce a&lt;br&gt;
measurable trust drop on a real site — the fix was deleting the junk entries, not&lt;br&gt;
adding more.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to model relationships correctly
&lt;/h2&gt;

&lt;p&gt;The reason people abuse &lt;code&gt;sameAs&lt;/code&gt; is usually that they're trying to express a&lt;br&gt;
&lt;em&gt;relationship&lt;/em&gt; — "this brand is part of that studio." &lt;code&gt;sameAs&lt;/code&gt; is the wrong tool.&lt;br&gt;
Use the relationship properties schema.org actually provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;parentOrganization&lt;/code&gt; / &lt;code&gt;subOrganization&lt;/code&gt; for a brand network.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;worksFor&lt;/code&gt; / &lt;code&gt;founder&lt;/code&gt; / &lt;code&gt;employee&lt;/code&gt; for people-to-org.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;memberOf&lt;/code&gt;, &lt;code&gt;brand&lt;/code&gt;, &lt;code&gt;publisher&lt;/code&gt; where they fit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anchor both ends with a stable &lt;code&gt;@id&lt;/code&gt; (e.g. &lt;code&gt;https://example.com/#org&lt;/code&gt;) and point&lt;br&gt;
the relationship at that &lt;code&gt;@id&lt;/code&gt;. Now the graph is reciprocal and machine-readable&lt;br&gt;
without a single misused &lt;code&gt;sameAs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick audit you can run today
&lt;/h2&gt;

&lt;p&gt;Open your JSON-LD, find every &lt;code&gt;sameAs&lt;/code&gt; array, and ask of each URL: &lt;em&gt;is this a&lt;br&gt;
profile of the exact entity this node describes?&lt;/em&gt; If the answer is "no, but it's&lt;br&gt;
related," move it to a relationship property. If the answer is "no, it's a&lt;br&gt;
mention/backlink/repo," delete it.&lt;/p&gt;

&lt;p&gt;I keep a set of canonical structured-data references — the full sameAs pattern, the&lt;br&gt;
relationship properties, and worked org-network examples — at&lt;br&gt;
&lt;a href="https://www.thatdevpro.com/reference/" rel="noopener noreferrer"&gt;ThatDevPro's reference library&lt;/a&gt;. The&lt;br&gt;
patterns are boring on purpose. Boring is what survives an algorithm update.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


---

I hand-build websites and full-stack engine optimization at [ThatDevPro](https://www.thatdevpro.com/) and [ThatDeveloperGuy](https://thatdeveloperguy.com/) — a service-disabled veteran-owned studio in Cassville, Missouri.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>ai</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Person entity dual-founder pattern with spouse linkage for a husband-and-wife business</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:54:40 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/person-entity-dual-founder-pattern-with-spouse-linkage-for-a-husband-and-wife-business-3mkh</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/person-entity-dual-founder-pattern-with-spouse-linkage-for-a-husband-and-wife-business-3mkh</guid>
      <description>&lt;h1&gt;
  
  
  Person entity dual-founder pattern with spouse linkage for a husband-and-wife small business
&lt;/h1&gt;

&lt;p&gt;Husband-and-wife co-founder businesses are common. The Schema.org graph for them rarely captures the relationship explicitly. Most sites declare both founders as separate Person entities with no link between them.&lt;/p&gt;

&lt;p&gt;The denser pattern declares the spousal relationship inside the graph itself using the &lt;code&gt;spouse&lt;/code&gt; property, then uses both &lt;code&gt;＠id&lt;/code&gt; references to make the entities reciprocally addressable.&lt;/p&gt;

&lt;p&gt;This is the pattern I built for &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, a husband-and-wife merchant services brokerage in Branson, Missouri.&lt;/p&gt;

&lt;h2&gt;
  
  
  The standard mistake
&lt;/h2&gt;

&lt;p&gt;Two separate Person nodes, no relationship between them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@graph"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/#founder1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jim Steele"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/#founder2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kim Steele"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google reads this as two independent people who happen to be at the same business. The spousal relationship is implied by name + same employer, but not declared.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reciprocal-spouse pattern
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@graph"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"givenName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"familyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"jobTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Co-founder and Principal, CSSI National Account Executive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"spouse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#kim"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"worksFor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#organization"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#kim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"givenName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimberly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"additionalName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kayleen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"familyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"alternateName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Kim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimberly K. Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimberly Kayleen Steele"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"jobTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Co-founder and Principal, ATM Placement Program Lead"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"spouse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"worksFor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#organization"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both Person entities reference each other through &lt;code&gt;spouse&lt;/code&gt;. The graph is reciprocal. Google reads the relationship as a fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the additionalName + alternateName pattern adds
&lt;/h2&gt;

&lt;p&gt;The Schema.org Person type has three name-related properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; — the canonical display name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;givenName&lt;/code&gt; — first name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;familyName&lt;/code&gt; — last name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;additionalName&lt;/code&gt; — middle name (or names)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alternateName&lt;/code&gt; — array of alternative names&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Kim Steele:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"givenName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimberly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"additionalName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kayleen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"familyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alternateName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Kim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Kimberly K. Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Kimberly Kayleen Steele"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This captures every form the name takes across public records, social media, and informal contexts. Search engines reconciling "Kimberly K Steele Branson" with "Kim Steele Branson Solutions" hit a match through the alternateName array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-references to Organization
&lt;/h2&gt;

&lt;p&gt;Both Person entities also reference the Org as &lt;code&gt;worksFor&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"worksFor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#organization"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Org entity reciprocally lists both as &lt;code&gt;founder&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LocalBusiness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FinancialService"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ProfessionalService"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"founder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#kim"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the graph forms a complete triangle: Jim ↔ Kim (via spouse), Jim → Org (via worksFor), Kim → Org (via worksFor), Org → Jim + Kim (via founder array).&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-founder differentiation
&lt;/h2&gt;

&lt;p&gt;Husband and wife at the same business often have different domains of expertise. The schema captures the differentiation through &lt;code&gt;knowsAbout&lt;/code&gt; and &lt;code&gt;hasCredential&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"knowsAbout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Merchant Services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"POS Systems"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Credit Card Processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Cost Segregation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Banking"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Small Business Lending"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hasCredential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EducationalOccupationalCredential"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CSSI National Account Executive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"credentialCategory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Professional Designation"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EducationalOccupationalCredential"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Indiana University Business Graduate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"credentialCategory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bachelor's Degree, Business"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Kim, a different &lt;code&gt;knowsAbout&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#kim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"knowsAbout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ATM Placement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Merchant-Owned ATMs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Free ATM Placement Program"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Operations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Client Onboarding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Merchant Services Account Management"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both entities have full profile depth but with non-overlapping domains. The search engine can rank Jim for sales-side queries and Kim for operations-side queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this signals
&lt;/h2&gt;

&lt;p&gt;For a husband-and-wife co-founder business:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explicit relationship&lt;/strong&gt;: Google's Knowledge Graph treats the reciprocal spouse link as a verified fact rather than an inference&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disambiguation&lt;/strong&gt;: when multiple Jim Steeles exist online, the spouse link to Kim Steele provides additional triangulation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI engine clarity&lt;/strong&gt;: ChatGPT and Claude treat the explicit relationship as a citation-worthy fact when describing the business&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge Panel reconciliation&lt;/strong&gt;: Google may eventually build a Knowledge Panel for the business that names both founders correctly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Steele Solutions, the complete dual-founder graph is at &lt;a href="https://steelesolutions4u.com/entity.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/entity.json&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://schema.org/spouse" rel="noopener noreferrer"&gt;Schema.org spouse property&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/Person" rel="noopener noreferrer"&gt;Schema.org Person type&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/alternateName" rel="noopener noreferrer"&gt;Schema.org alternateName property&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Public Steele Solutions resources at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>schema</category>
      <category>seo</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The four AI citation surfaces every small business website should publish in 2026</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:53:34 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/the-four-ai-citation-surfaces-every-small-business-website-should-publish-in-2026-5beo</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/the-four-ai-citation-surfaces-every-small-business-website-should-publish-in-2026-5beo</guid>
      <description>&lt;h1&gt;
  
  
  llms.txt, aeo.json, entity.json, brand.json: the four AI citation surfaces for a small business
&lt;/h1&gt;

&lt;p&gt;In 2026, search engines and AI engines see your site differently. Google indexes HTML. ChatGPT crawls for citations. Claude probes for entity facts. Perplexity wants structured answers.&lt;/p&gt;

&lt;p&gt;Each of these engines reads different files. The four canonical AI citation surfaces are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;/llms.txt&lt;/code&gt; — natural-language identity for LLM crawlers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/aeo.json&lt;/code&gt; — Answer-Engine Optimization structured manifest&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/entity.json&lt;/code&gt; — Schema.org ＠graph as a standalone file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/brand.json&lt;/code&gt; — Brand identity, voice, and design system&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most small business sites have zero of these. The ones that do typically have one. For &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, a merchant services brokerage in Branson Missouri, all four surfaces are deployed and crawler-visible.&lt;/p&gt;

&lt;p&gt;Here is what each file does and why.&lt;/p&gt;

&lt;h2&gt;
  
  
  /llms.txt
&lt;/h2&gt;

&lt;p&gt;The proposed &lt;a href="https://llmstxt.org/" rel="noopener noreferrer"&gt;llms.txt&lt;/a&gt; standard is a natural-language identity declaration for LLM crawlers. The format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Steele Solutions&lt;/span&gt;
&lt;span class="gt"&gt;
&amp;gt; Family-run merchant services brokerage based in Branson, Missouri. Founded by Jim and Kim Steele. Serves the Ozarks region with five integrated service lines under the Business CPR framework: POS systems, credit card processing, ATM placements, business lending, and CSSI cost segregation studies.&lt;/span&gt;

&lt;span class="gu"&gt;## Services&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; POS Systems: https://steelesolutions4u.com/pos-systems/
&lt;span class="p"&gt;-&lt;/span&gt; Credit Card Processing: https://steelesolutions4u.com/credit-card-processing/
&lt;span class="p"&gt;-&lt;/span&gt; ATM Placements: https://steelesolutions4u.com/atm-placements/
&lt;span class="p"&gt;-&lt;/span&gt; Business Lending: https://steelesolutions4u.com/business-lending/
&lt;span class="p"&gt;-&lt;/span&gt; CSSI Cost Segregation: https://steelesolutions4u.com/cssi-cost-segregation/

&lt;span class="gu"&gt;## Find us on Google&lt;/span&gt;

Google Maps: https://www.google.com/maps?cid=07508619094055456934
Google Maps CID: 07508619094055456934
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Markdown format. Headers map to concept clusters. Bullet lists map to facts. LLMs are trained on documents that follow this structure, so they parse it cleanly.&lt;/p&gt;

&lt;p&gt;The llms.txt is currently honored by Anthropic's Claude and is widely scraped by other LLM training pipelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  /aeo.json
&lt;/h2&gt;

&lt;p&gt;AEO (Answer Engine Optimization) is the proposed JSON equivalent of llms.txt for structured answer-engine ingestion. Format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"site"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"steelesolutions4u.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions — Branson MO Merchant Services &amp;amp; Cost Segregation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"vertical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"merchant-services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"primary_topic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Independent merchant-services brokerage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"founded"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"founders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Co-founder, CSSI National Account Executive"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kim Steele"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Co-founder, ATM Placement Program Lead"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"locality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service_area"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Oklahoma"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kansas"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"POS Systems"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Credit Card Processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maps_cid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"07508619094055456934"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maps_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.google.com/maps?cid=07508619094055456934"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://www.google.com/maps?cid=07508619094055456934"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://cssiservices.com/sales/jim-steele/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://web.archive.org/web/2026/https://steelesolutions4u.com/"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JSON-structured, machine-parseable, includes the same facts as llms.txt but in a format that programmatic ingestion pipelines prefer.&lt;/p&gt;

&lt;h2&gt;
  
  
  /entity.json
&lt;/h2&gt;

&lt;p&gt;The Schema.org &lt;code&gt;＠graph&lt;/code&gt; as a standalone, addressable JSON-LD file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@graph"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LocalBusiness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FinancialService"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ProfessionalService"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"hasOfferCatalog"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"areaServed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#kim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WebSite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#website"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same schema is also embedded inline on every HTML page. The standalone /entity.json file gives crawlers (and AI engines) a single URL that returns the complete entity graph without HTML noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  /brand.json
&lt;/h2&gt;

&lt;p&gt;Brand identity, voice, and design system as a machine-readable manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alternateNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SteeleSolutions"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tagline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Honest merchant services from the Ozarks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"founded"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headquarters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson, MO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"telephones"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"+14172941882"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+14172311349"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"steelesolutions4u@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"website"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"colors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"primary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#1a3a52"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"accent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#3a8b9f"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fonts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"display"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fraunces"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Inter"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Direct, professional, no upsell pressure. The 'free statement audit' anchors the trust signal."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"maps_cid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"07508619094055456934"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"listings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"googleBusinessProfile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"07508619094055456934"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.google.com/maps?cid=07508619094055456934"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brand.json is consumed by design-system tooling and by AI agents that need to reproduce the brand's voice when generating content about the business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting them together
&lt;/h2&gt;

&lt;p&gt;A standard &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; block on every page references all four files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/plain"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/llms.txt"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"LLM identity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/aeo.json"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"AEO"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/ld+json"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/entity.json"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Entity graph"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/brand.json"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Brand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are crawler discovery hints. AI engine bots that read &lt;code&gt;alternate&lt;/code&gt; link headers find the files and ingest them as structured supplements to the HTML content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each file goes
&lt;/h2&gt;

&lt;p&gt;For nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/llms.txt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/sites/steelesolutions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;text/plain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/entity.json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/sites/steelesolutions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;application/ld&lt;/span&gt;&lt;span class="s"&gt;+json&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/aeo.json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/sites/steelesolutions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;application/json&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/brand.json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/sites/steelesolutions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;default_type&lt;/span&gt; &lt;span class="nc"&gt;application/json&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default_type ensures the MIME type is correct. AI engine crawlers check Content-Type before parsing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this signals
&lt;/h2&gt;

&lt;p&gt;For a brand-new small business site, the four-surface stack signals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The site is engineered with AI-engine discovery as a deliberate goal&lt;/li&gt;
&lt;li&gt;The business identity has been formally declared, not just implied through page content&lt;/li&gt;
&lt;li&gt;There is structured authority data available without HTML noise&lt;/li&gt;
&lt;li&gt;The site participates in the emerging AI citation ecosystem&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Steele Solutions, all four files are live at the site root:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://steelesolutions4u.com/llms.txt" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/llms.txt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://steelesolutions4u.com/aeo.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/aeo.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://steelesolutions4u.com/entity.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/entity.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://steelesolutions4u.com/brand.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/brand.json&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://llmstxt.org/" rel="noopener noreferrer"&gt;llms.txt proposed standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/docs/jsonld.html" rel="noopener noreferrer"&gt;Schema.org JSON-LD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Public Steele Solutions resources at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>seo</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Wikidata Q-ID chaining: anchoring a business credential to a verifiable institution</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:52:48 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/wikidata-q-id-chaining-anchoring-a-business-credential-to-a-verifiable-institution-3jme</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/wikidata-q-id-chaining-anchoring-a-business-credential-to-a-verifiable-institution-3jme</guid>
      <description>&lt;h1&gt;
  
  
  Wikidata Q-ID chaining: how to anchor a business credential to a verifiable institution
&lt;/h1&gt;

&lt;p&gt;Schema.org's &lt;code&gt;hasCredential&lt;/code&gt; field accepts a flat string for the credential name. Most sites use it that way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hasCredential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"President's Club"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is technically valid. It is also useless for entity reconciliation. The string &lt;code&gt;"President's Club"&lt;/code&gt; could be Toastmasters, an airline frequent flyer tier, or any of a thousand sales-recognition programs across every industry. Google has no way to disambiguate.&lt;/p&gt;

&lt;p&gt;The denser pattern uses &lt;code&gt;EducationalOccupationalCredential&lt;/code&gt; with &lt;code&gt;recognizedBy&lt;/code&gt; chained to an Organization that includes a Wikidata Q-ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hasCredential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EducationalOccupationalCredential"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First National Bank of Omaha President's Club"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credentialCategory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sales Performance Award"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recognizedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BankOrCreditUnion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First National Bank of Omaha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.fnbo.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://www.wikidata.org/wiki/Q5453412"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/First_National_Bank_of_Omaha"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"identifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PropertyValue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"propertyID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WikidataQID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q5453412"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Google's Knowledge Graph can traverse the chain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the credential name&lt;/li&gt;
&lt;li&gt;Identify the issuing institution&lt;/li&gt;
&lt;li&gt;Reconcile the institution to its Wikidata entity (Q5453412)&lt;/li&gt;
&lt;li&gt;Verify the institution exists in the Knowledge Graph&lt;/li&gt;
&lt;li&gt;Assign credibility to the credential because it is issued by a verified entity&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is what I built into &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt; for Jim Steele's career history. Three credentials, three Wikidata-anchored institutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;For any credential where the issuing institution is in Wikipedia or Wikidata, the chained pattern works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hasCredential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EducationalOccupationalCredential"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{degree or award name}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"credentialCategory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{Bachelor's Degree | Sales Performance Award | Certification | Professional Designation}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"recognizedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{CollegeOrUniversity | BankOrCreditUnion | Organization | ProfessionalAssociation}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{institution name}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{institution URL}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"https://www.wikidata.org/wiki/Q{QID}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/{slug}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"identifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PropertyValue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"propertyID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WikidataQID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q{QID}"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;identifier&lt;/code&gt; array with &lt;code&gt;WikidataQID&lt;/code&gt; is the explicit identifier-typed declaration. Google reads either the &lt;code&gt;sameAs&lt;/code&gt; URL or the &lt;code&gt;identifier&lt;/code&gt; value and resolves to the same entity. Including both gives crawlers redundancy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the Q-ID
&lt;/h2&gt;

&lt;p&gt;For any major institution, the Wikidata Q-ID is on the right sidebar of the Wikipedia page. Or search &lt;a href="https://www.wikidata.org/w/index.php?search=" rel="noopener noreferrer"&gt;Wikidata's entity search&lt;/a&gt; for the institution name.&lt;/p&gt;

&lt;p&gt;Examples relevant to Steele Solutions' graph:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Institution&lt;/th&gt;
&lt;th&gt;Wikidata Q-ID&lt;/th&gt;
&lt;th&gt;Wikipedia URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Indiana University Bloomington&lt;/td&gt;
&lt;td&gt;Q1079140&lt;/td&gt;
&lt;td&gt;en.wikipedia.org/wiki/Indiana_University_Bloomington&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First National Bank of Omaha&lt;/td&gt;
&lt;td&gt;Q5453412&lt;/td&gt;
&lt;td&gt;en.wikipedia.org/wiki/First_National_Bank_of_Omaha&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Indiana University Kelley School of Business&lt;/td&gt;
&lt;td&gt;Q6123576&lt;/td&gt;
&lt;td&gt;en.wikipedia.org/wiki/Kelley_School_of_Business&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema.org&lt;/td&gt;
&lt;td&gt;Q1521&lt;/td&gt;
&lt;td&gt;en.wikipedia.org/wiki/Schema.org&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a credential, the load-bearing field is &lt;code&gt;recognizedBy.identifier[].value&lt;/code&gt; containing the Q-ID. The &lt;code&gt;sameAs&lt;/code&gt; URLs are reinforcement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond credentials: alumniOf, memberOf, knowsAbout
&lt;/h2&gt;

&lt;p&gt;The same Q-ID chaining applies to other Person fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"alumniOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CollegeOrUniversity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Indiana University Bloomington"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.indiana.edu/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://www.wikidata.org/wiki/Q1079140"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/Indiana_University_Bloomington"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"memberOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CSSI Cost Segregation Services, Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cssiservices.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"America's leading engineering-based cost segregation firm. 60,000+ studies completed; $55B+ in client tax savings."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;alumniOf&lt;/code&gt; for educational institutions. &lt;code&gt;memberOf&lt;/code&gt; for professional bodies, alumni associations, trade groups. &lt;code&gt;knowsAbout&lt;/code&gt; typically takes plain strings, but can also take URLs pointing to Wikipedia articles for each topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"knowsAbout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Merchant Services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Cost Segregation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/Cost_segregation"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Wikipedia URL form is rarer but is parsed correctly by Google. It maps the topic name to its Wikipedia entity for tighter reconciliation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this buys you
&lt;/h2&gt;

&lt;p&gt;For an individual with a long career, the chained-Q-ID pattern produces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge Graph entries&lt;/strong&gt;: Google may eventually generate a Knowledge Graph card for the person, anchored by the institutional chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI engine recognition&lt;/strong&gt;: ChatGPT, Claude, and Perplexity treat Wikidata Q-IDs as verifiable third-party assertions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster trust accumulation&lt;/strong&gt;: a new domain hosting a Person entity with three Q-ID-chained credentials accumulates trust faster than one with flat-string credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disambiguation&lt;/strong&gt;: a common name (like "Jim Steele") becomes disambiguated through the unique combination of institutional Q-IDs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Jim Steele on &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, the three Q-ID-chained credentials (CSSI National Account Executive, Indiana University Business graduate, First National Bank of Omaha President's Club) form a triangulation that identifies him uniquely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification
&lt;/h2&gt;

&lt;p&gt;The Schema.org Markup Validator at &lt;a href="https://validator.schema.org/" rel="noopener noreferrer"&gt;validator.schema.org&lt;/a&gt; parses the chained pattern without errors. Google's Rich Results Test recognizes the structure.&lt;/p&gt;

&lt;p&gt;For a real-world implementation, see &lt;a href="https://steelesolutions4u.com/entity.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/entity.json&lt;/a&gt;. The Jim and Kim Steele entities use Wikidata Q-IDs throughout.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.wikidata.org/wiki/Special:Search" rel="noopener noreferrer"&gt;Wikidata Q-ID search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/EducationalOccupationalCredential" rel="noopener noreferrer"&gt;Schema.org EducationalOccupationalCredential&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/recognizedBy" rel="noopener noreferrer"&gt;Schema.org recognizedBy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Public resources at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>schema</category>
      <category>seo</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>GoodRelations payment method URIs: the underused Schema.org pattern for financial services</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:52:01 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/goodrelations-payment-method-uris-the-underused-schemaorg-pattern-for-financial-services-1f1c</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/goodrelations-payment-method-uris-the-underused-schemaorg-pattern-for-financial-services-1f1c</guid>
      <description>&lt;h1&gt;
  
  
  GoodRelations payment method URIs: the underused Schema.org pattern for financial services
&lt;/h1&gt;

&lt;p&gt;Schema.org has a built-in &lt;code&gt;paymentAccepted&lt;/code&gt; string property, and a &lt;code&gt;paymentMethod&lt;/code&gt; URL-typed property. Most sites use the first, skip the second, and lose half the entity-graph signal.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;paymentMethod&lt;/code&gt; field accepts URIs from the &lt;a href="http://purl.org/goodrelations/v1" rel="noopener noreferrer"&gt;GoodRelations vocabulary&lt;/a&gt;, which provides explicit machine-readable identifiers for every common payment instrument. For a financial services or merchant services business, the GoodRelations URIs feed directly into Google's Knowledge Graph and into AI engines (ChatGPT, Claude, Gemini, Perplexity) as structured facts.&lt;/p&gt;

&lt;p&gt;This is the pattern as it appears on &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, a Branson MO merchant services brokerage.&lt;/p&gt;

&lt;h2&gt;
  
  
  The standard mistake
&lt;/h2&gt;

&lt;p&gt;Most sites declare payment methods like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LocalBusiness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentAccepted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cash, Check, Credit Card"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A flat human-readable string. Google reads it. The Knowledge Graph parses some recognizable terms. The signal is shallow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The GoodRelations pattern
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LocalBusiness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FinancialService"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentAccepted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cash, Check, ACH, Wire, Visa, Mastercard, American Express, Discover"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#Cash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#Check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#PaymentMethodCreditCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#DirectDebit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#ByBankTransferInAdvance"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URI array is the explicit, deterministic version. Each URI is a machine-readable identifier that maps to a single payment-method concept. Google does not have to do natural-language parsing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Available GoodRelations payment-method URIs
&lt;/h2&gt;

&lt;p&gt;The full list of GoodRelations payment-method URIs (most often used):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;URI&lt;/th&gt;
&lt;th&gt;Maps to&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#Cash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Physical cash transactions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#Check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Paper or electronic check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#PaymentMethodCreditCard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generic credit card&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#DirectDebit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bank account ACH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#ByBankTransferInAdvance&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wire transfer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#ByInvoice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Net-30 invoice billing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#COD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cash on delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#GoogleCheckout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(historical)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#PayPal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(deprecated, use string)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#PaymentMethodCard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generic card payment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For specific card brands (Visa, Mastercard, etc.), the GoodRelations vocabulary defines:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;URI&lt;/th&gt;
&lt;th&gt;Brand&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#VISA&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Visa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#MasterCard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mastercard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#AmericanExpress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;American Express&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#Discover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Discover&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#JCB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JCB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http://purl.org/goodrelations/v1#DinersClub&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Diners Club&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are the canonical identifiers for each card network as far as the linked-data web is concerned.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this signals
&lt;/h2&gt;

&lt;p&gt;For a merchant services brokerage, the GoodRelations array signals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Topical relevance&lt;/strong&gt;: a business that explicitly enumerates GoodRelations URIs is participating in the structured-payments-vocabulary ecosystem. Google's Knowledge Graph treats this as a strong indicator that the business is in payment processing, not in retail or restaurants.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crawler clarity&lt;/strong&gt;: AI engines parsing the page get unambiguous payment-method facts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation pass&lt;/strong&gt;: Google's Rich Results Test recognizes GoodRelations URIs as valid &lt;code&gt;paymentMethod&lt;/code&gt; values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future-proofing&lt;/strong&gt;: Schema.org may add native enums for payment methods someday. GoodRelations is the bridge until then.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What this does not signal
&lt;/h2&gt;

&lt;p&gt;GoodRelations URIs do not currently produce rich snippets, knowledge panels, or special SERP features by themselves. The benefit is upstream — it strengthens the entity graph for Knowledge Graph reconciliation and AI-engine indexing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Steele Solutions example
&lt;/h2&gt;

&lt;p&gt;For Steele Solutions, the &lt;code&gt;paymentMethod&lt;/code&gt; array works alongside the broader Schema.org graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LocalBusiness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FinancialService"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ProfessionalService"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currenciesAccepted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentAccepted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cash, Check, ACH, Wire, Visa, Mastercard, American Express, Discover"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#Cash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#Check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#PaymentMethodCreditCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#DirectDebit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#ByBankTransferInAdvance"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priceRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$0 install, no contracts. Statement audit free."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined with the &lt;code&gt;FinancialService&lt;/code&gt; type and the 10-service &lt;code&gt;hasOfferCatalog&lt;/code&gt;, the GoodRelations URIs round out the merchant-services entity declaration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to verify
&lt;/h2&gt;

&lt;p&gt;Test the markup at &lt;a href="https://search.google.com/test/rich-results" rel="noopener noreferrer"&gt;Google's Rich Results Test&lt;/a&gt;. The &lt;code&gt;paymentMethod&lt;/code&gt; field with GoodRelations URIs should validate without warnings. The Knowledge Graph reconciliation pass happens in the background after Google indexes the page.&lt;/p&gt;

&lt;p&gt;For Steele Solutions, the complete schema is at &lt;a href="https://steelesolutions4u.com/entity.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/entity.json&lt;/a&gt;. The site implementation is at &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://purl.org/goodrelations/v1" rel="noopener noreferrer"&gt;GoodRelations vocabulary specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/paymentMethod" rel="noopener noreferrer"&gt;Schema.org paymentMethod reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/FinancialService" rel="noopener noreferrer"&gt;Schema.org FinancialService reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Public resources at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>schema</category>
      <category>seo</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Country-spanning service-area schema: 17 cities and places in one Organization graph</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:41:20 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/country-spanning-service-area-schema-17-cities-and-places-in-one-organization-graph-3361</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/country-spanning-service-area-schema-17-cities-and-places-in-one-organization-graph-3361</guid>
      <description>&lt;h1&gt;
  
  
  Country-spanning service-area schema: 17 cities and places in one Organization graph
&lt;/h1&gt;

&lt;p&gt;A merchant services brokerage in the Ozarks region serves a four-state corridor: Missouri, Arkansas, Oklahoma, and Kansas. The site needs to rank for "credit card processing Branson MO" and "ATM placement Eureka Springs AR" with the same authority signal.&lt;/p&gt;

&lt;p&gt;Schema.org gives you &lt;code&gt;areaServed&lt;/code&gt; for exactly this. Most implementations stop at one city. Here is how &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt; declares 17 distinct areas in a single Organization graph node, blending &lt;code&gt;City&lt;/code&gt;, &lt;code&gt;State&lt;/code&gt;, and &lt;code&gt;Place&lt;/code&gt; types with &lt;code&gt;containedInPlace&lt;/code&gt; chaining.&lt;/p&gt;

&lt;h2&gt;
  
  
  The flat-string mistake
&lt;/h2&gt;

&lt;p&gt;The temptation is to write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"areaServed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson, Missouri and surrounding areas"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is technically valid Schema.org. Google reads the string and infers a service area. But the inference is shallow. Google does not know which cities are in the area. The Knowledge Graph does not reconcile the cities to their Wikidata entries.&lt;/p&gt;

&lt;p&gt;The dense pattern uses an array of typed objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"areaServed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Springfield"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each city is an explicit entity. The &lt;code&gt;containedInPlace&lt;/code&gt; chain tells Google that Branson is in Missouri. The State entity gets its own Knowledge Graph reconciliation.&lt;/p&gt;

&lt;h2&gt;
  
  
  City vs Place
&lt;/h2&gt;

&lt;p&gt;Some service areas are not political units. Lake Taneycomo is a body of water. Branson Landing is a commercial district. These cannot be &lt;code&gt;City&lt;/code&gt;. Use &lt;code&gt;Place&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lake Taneycomo"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Table Rock Lake"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson Landing"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the Ozarks"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mixing &lt;code&gt;City&lt;/code&gt; and &lt;code&gt;Place&lt;/code&gt; is fine. Both inherit from &lt;code&gt;Place&lt;/code&gt; in the Schema.org type hierarchy. Google handles the mixed array correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full Steele Solutions areaServed
&lt;/h2&gt;

&lt;p&gt;The complete &lt;code&gt;areaServed&lt;/code&gt; for Steele Solutions, spanning Missouri and Arkansas with associated lake and regional entities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"areaServed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hollister"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Forsyth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kimberling City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cassville"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Springfield"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Joplin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reeds Spring"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lake of the Ozarks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bentonville"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rogers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eureka Springs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Berryville"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lake Taneycomo"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Table Rock Lake"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson Landing"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the Ozarks"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;13 cities, 4 places, 17 total areas in one declaration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why containedInPlace matters
&lt;/h2&gt;

&lt;p&gt;Without &lt;code&gt;containedInPlace&lt;/code&gt;, the City entity is ambiguous. Branson exists in Missouri but also in Colorado. Springfield exists in 35+ US states. The chained &lt;code&gt;containedInPlace&lt;/code&gt; resolves the ambiguity for Google's Knowledge Graph.&lt;/p&gt;

&lt;p&gt;The chain can go deeper. For a sub-state region:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AdministrativeArea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Taney County"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Google: Branson is in Taney County, which is in Missouri. For a service business where county boundaries matter, the deeper chain is worth the verbosity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-area landing pages
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;areaServed&lt;/code&gt; declaration is the entity-graph statement. The site also needs landing pages for each area. Steele Solutions has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/branson-mo/&lt;/li&gt;
&lt;li&gt;/locations/springfield-mo/&lt;/li&gt;
&lt;li&gt;/locations/joplin-mo/&lt;/li&gt;
&lt;li&gt;/locations/hollister-mo/&lt;/li&gt;
&lt;li&gt;/locations/forsyth-mo/&lt;/li&gt;
&lt;li&gt;/locations/kimberling-city-mo/&lt;/li&gt;
&lt;li&gt;/locations/reeds-spring-mo/&lt;/li&gt;
&lt;li&gt;/locations/lake-of-the-ozarks/&lt;/li&gt;
&lt;li&gt;/locations/bentonville-ar/&lt;/li&gt;
&lt;li&gt;/locations/rogers-ar/&lt;/li&gt;
&lt;li&gt;/locations/eureka-springs-ar/&lt;/li&gt;
&lt;li&gt;/locations/berryville-ar/&lt;/li&gt;
&lt;li&gt;/ozarks-region/ (regional hub)&lt;/li&gt;
&lt;li&gt;/locations/ (location index)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each page has its own page-level schema with the City as the WebPage &lt;code&gt;about&lt;/code&gt;. Cross-link from the homepage areaServed to each landing page where possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What ranking changes to expect
&lt;/h2&gt;

&lt;p&gt;For a brand-new domain, dense areaServed declaration produces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster discovery of per-area landing pages&lt;/li&gt;
&lt;li&gt;More query-specific impressions in GSC (e.g., separate impressions for "credit card processing Bentonville AR" vs "credit card processing Branson MO")&lt;/li&gt;
&lt;li&gt;Cleaner Knowledge Panel reconciliation&lt;/li&gt;
&lt;li&gt;AI Overview citations for region-specific queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Steele Solutions on day 7 of launch, GSC was already showing impressions for at least 3 different region+service combinations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The live example
&lt;/h2&gt;

&lt;p&gt;The complete entity graph including the 17-area &lt;code&gt;areaServed&lt;/code&gt; declaration is at &lt;a href="https://steelesolutions4u.com/entity.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/entity.json&lt;/a&gt;. The same schema is embedded inline on every page of the site.&lt;/p&gt;

&lt;p&gt;Live site: &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/&lt;/a&gt;. Service-area pages start at &lt;a href="https://steelesolutions4u.com/locations/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/locations/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://schema.org/Place" rel="noopener noreferrer"&gt;Schema.org Place hierarchy reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org/areaServed" rel="noopener noreferrer"&gt;Schema.org areaServed reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://search.google.com/test/rich-results" rel="noopener noreferrer"&gt;Google Rich Results Test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Public resources at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>schema</category>
      <category>seo</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Indexing rescue for a 7-day-old domain: 4 of 18 priority pages indexed in 6 days</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:40:35 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/indexing-rescue-for-a-7-day-old-domain-4-of-18-priority-pages-indexed-in-6-days-2gk7</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/indexing-rescue-for-a-7-day-old-domain-4-of-18-priority-pages-indexed-in-6-days-2gk7</guid>
      <description>&lt;h1&gt;
  
  
  Indexing rescue for a 7-day-old domain: how we got 4 of 18 priority pages indexed in 6 days
&lt;/h1&gt;

&lt;p&gt;A brand-new domain is in a special category for Google. The crawler discovers URLs from the sitemap, queues them for indexing, then often holds them in "Discovered, currently not indexed" status for weeks or months. The site is real. The content is fine. Google just hasn't decided to allocate the index slots yet.&lt;/p&gt;

&lt;p&gt;This is the standard new-domain experience. For &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, launched 2026-05-19 — a family-run merchant services brokerage in Branson, Missouri — we hit the same wall on day 2.&lt;/p&gt;

&lt;p&gt;Here is the indexing rescue stack that took us from 0 indexed pages to 4 of 18 priority pages indexed within 6 days.&lt;/p&gt;

&lt;h2&gt;
  
  
  The starting state
&lt;/h2&gt;

&lt;p&gt;GSC URL Inspection on day 2:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page&lt;/th&gt;
&lt;th&gt;Coverage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;/ (homepage)&lt;/td&gt;
&lt;td&gt;Submitted and indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/credit-card-processing/&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/pos-systems/&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/atm-placements/&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/business-lending/&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/cssi-cost-segregation/&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/dual-pricing/&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...12 more&lt;/td&gt;
&lt;td&gt;Discovered - currently not indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;1 of 18 indexed. Standard for a 7-day-old domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rescue stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  IndexNow to Bing and Yandex
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.indexnow.org/" rel="noopener noreferrer"&gt;IndexNow&lt;/a&gt; is a search-engine-side push API. You POST a list of URLs plus a verification key, and Bing and Yandex acknowledge with HTTP 200 within seconds.&lt;/p&gt;

&lt;p&gt;The IndexNow signal does propagate to Google indirectly. Google's Discovery layer reads multiple signals from across the search ecosystem when deciding which URLs to crawl. A URL submitted via IndexNow is more likely to get an early crawl from Googlebot than a URL that only appears in your sitemap.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s1"&gt;'https://yandex.com/indexnow'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"host":"steelesolutions4u.com",
       "key":"YOUR_KEY",
       "keyLocation":"https://steelesolutions4u.com/YOUR_KEY.txt",
       "urlList":[
         "https://steelesolutions4u.com/",
         "https://steelesolutions4u.com/credit-card-processing/"
       ]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Steele, we submitted all 26 priority URLs to Yandex within 24 hours of launch. Each submission got an HTTP 202 acknowledgment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wayback Machine archive of every URL
&lt;/h3&gt;

&lt;p&gt;The Internet Archive's Wayback Machine becomes a discovery signal for Google because Common Crawl licenses Wayback data for URL discovery. When you submit a URL to &lt;a href="https://web.archive.org/save/YOUR_URL" rel="noopener noreferrer"&gt;https://web.archive.org/save/YOUR_URL&lt;/a&gt;, the archive crawler immediately fetches and stores the page. The archive URL is permanently accessible and indexable.&lt;/p&gt;

&lt;p&gt;For Steele, we ran a Python script that submitted all 43 sitemap URLs to Wayback, paced at 5 seconds between submissions to avoid rate limiting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urllib.request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;priority_urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;save_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://web.archive.org/save/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;save_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: 43 of 43 URLs archived. The Wayback Machine snapshots for Steele Solutions are at &lt;a href="https://web.archive.org/web/2026/https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;https://web.archive.org/web/2026/https://steelesolutions4u.com/&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  GSC URL Inspection API
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://search.google.com/search-console" rel="noopener noreferrer"&gt;Google Search Console URL Inspection API&lt;/a&gt; lets you inspect any URL on your verified property. Calling &lt;code&gt;urlInspection().index().inspect()&lt;/code&gt; returns the URL's coverage state, last crawl time, and indexing verdict.&lt;/p&gt;

&lt;p&gt;The act of inspecting a URL signals discovery interest to Google. Google does not document this as a feature, but the empirical observation is: URLs that are inspected via the API show faster movement from "Discovered" to "Submitted and indexed" than URLs that are not.&lt;/p&gt;

&lt;p&gt;For Steele, we ran the inspection API across all 18 priority URLs on day 3. The inspection results helped us identify URLs that were stuck and URLs that were progressing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-site link equity
&lt;/h3&gt;

&lt;p&gt;A fresh domain has no external referring domains. Internal link equity flows only within the site. Cross-linking from existing high-DA properties accelerates discovery.&lt;/p&gt;

&lt;p&gt;For Steele Solutions, we added inbound links from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A studio portfolio: &lt;a href="https://www.thatdevpro.com/portfolio/case-studies/steele-solutions/" rel="noopener noreferrer"&gt;https://www.thatdevpro.com/portfolio/case-studies/steele-solutions/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The parent agency case studies index&lt;/li&gt;
&lt;li&gt;The hosting network's "Sites already on the network" grid&lt;/li&gt;
&lt;li&gt;A GitHub profile README's "Recent client work" section (DA 96 referring domain)&lt;/li&gt;
&lt;li&gt;A canonical Person hub at &lt;a href="https://feedthejoe.com/joseph/" rel="noopener noreferrer"&gt;https://feedthejoe.com/joseph/&lt;/a&gt; "Recent client work"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each link transfers some link equity. The Discover queue moves faster when external referrers exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema.org density
&lt;/h3&gt;

&lt;p&gt;A dense entity graph signals legitimacy. Steele Solutions has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LocalBusiness + FinancialService + ProfessionalService combined types&lt;/li&gt;
&lt;li&gt;hasOfferCatalog with 10 services, each with a URL&lt;/li&gt;
&lt;li&gt;17 areaServed entities&lt;/li&gt;
&lt;li&gt;Two Person founders with full bios, hasCredential with recognizedBy organization URIs, alumniOf with Wikidata Q-IDs&lt;/li&gt;
&lt;li&gt;15+ sameAs URLs spanning Wayback archive, Taney County public records, partner sites, and Google Maps CID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google's structured data testing tool rates the schema. AI engines weigh it. Dense schema correlates with faster index inclusion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Public verification page
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://steelesolutions4u.com/verification/" rel="noopener noreferrer"&gt;verification page&lt;/a&gt; aggregates every claim on the site with a third-party source link. Sections cover business identity, principal career history, partner network, where we appear publicly, and Taney County, Missouri public records.&lt;/p&gt;

&lt;p&gt;When Google crawls /verification/, it finds outbound citations to Wikipedia (Q1079140, Q5453412), Wikidata, the Internet Archive Wayback Machine, the CSSI directory, and the Taney County Collector. The page becomes a topical hub that demonstrates third-party verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results timeline
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Pages indexed&lt;/th&gt;
&lt;th&gt;New action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Site launched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1 (homepage)&lt;/td&gt;
&lt;td&gt;Sitemap submitted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;IndexNow + Wayback + GSC URL Inspection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;3 (homepage, /about/, /branson-mo/)&lt;/td&gt;
&lt;td&gt;Schema enrichment wave&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;4 (added /cssi-cost-segregation/)&lt;/td&gt;
&lt;td&gt;Verification page published&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;4 + 12 in "Discovered" queue&lt;/td&gt;
&lt;td&gt;Continuing IndexNow submissions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By day 7, 4 of 18 priority pages were indexed. The remaining 12 were in the Discovery queue, all submitted to Google's indexing pipeline and waiting their turn.&lt;/p&gt;

&lt;p&gt;For a 7-day-old domain, that pace is significantly faster than the typical 30-90 day baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaways
&lt;/h2&gt;

&lt;p&gt;For a new-domain indexing rescue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Submit to IndexNow within 24 hours of every URL change&lt;/li&gt;
&lt;li&gt;Archive every URL to Wayback Machine on day 1&lt;/li&gt;
&lt;li&gt;Call GSC URL Inspection API on priority URLs&lt;/li&gt;
&lt;li&gt;Build inbound links from at least 3 high-DA properties you control&lt;/li&gt;
&lt;li&gt;Dense Schema.org markup with sameAs, Wikidata Q-IDs, and partner references&lt;/li&gt;
&lt;li&gt;A /verification/ page aggregating all third-party citations in one place&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The site for the example is at &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/&lt;/a&gt;. Live verification page at &lt;a href="https://steelesolutions4u.com/verification/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/verification/&lt;/a&gt;. Public resources at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building an indexable verification page for a freshly-launched small business</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:38:34 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/building-an-indexable-verification-page-for-a-freshly-launched-small-business-2a9m</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/building-an-indexable-verification-page-for-a-freshly-launched-small-business-2a9m</guid>
      <description>&lt;h1&gt;
  
  
  Building an indexable verification page for a freshly-launched small business site
&lt;/h1&gt;

&lt;p&gt;When a small business launches a new website, Google treats it as untrusted for 30 to 90 days. New domain. No backlinks. No reviews. No knowledge panel. The site might be technically perfect, but Google won't promote it until external trust signals appear.&lt;/p&gt;

&lt;p&gt;The standard advice is: build backlinks, get reviews, sign up for directories, hope for press coverage. All slow. Some take months.&lt;/p&gt;

&lt;p&gt;There's a faster move: build a &lt;code&gt;/verification/&lt;/code&gt; page on the site itself that aggregates every verifiable third-party citation in one place. Make the website itself the authority.&lt;/p&gt;

&lt;p&gt;I built this for &lt;a href="https://steelesolutions4u.com/verification/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, a family-run merchant services brokerage in Branson, Missouri, in May 2026. Here's the pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The page structure
&lt;/h2&gt;

&lt;p&gt;The verification page is a series of tables. Each row is one claim and one third-party source URL where anyone can verify it. The format:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Claim&lt;/th&gt;
&lt;th&gt;Source description&lt;/th&gt;
&lt;th&gt;Verify URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Headquarters Branson, MO&lt;/td&gt;
&lt;td&gt;Address on every site page&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/contact/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain registered 2026-05-19&lt;/td&gt;
&lt;td&gt;ICANN WHOIS&lt;/td&gt;
&lt;td&gt;lookup.icann.org&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Business Profile CID 07508619094055456934&lt;/td&gt;
&lt;td&gt;Google Maps&lt;/td&gt;
&lt;td&gt;google.com/maps?cid=...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wayback Machine archive&lt;/td&gt;
&lt;td&gt;Internet Archive snapshot&lt;/td&gt;
&lt;td&gt;web.archive.org&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every claim links out. Anyone reading the page can click each link and confirm the claim independently. Google can crawl each outbound link and follow the citation chain to the same conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 1: business identity
&lt;/h2&gt;

&lt;p&gt;The first table covers the basics — name, address, phone, domain age, Google Business Profile CID, Wayback Machine snapshot. Each entry is verifiable through a single click.&lt;/p&gt;

&lt;p&gt;The Wayback URL is critical. It is the most permanent citation on the internet. When the Wayback Machine captures your site, that snapshot becomes a public-record timestamp of every claim on your homepage. Future crawlers can traverse to the archive and confirm exactly what your site said on the day it was archived.&lt;/p&gt;

&lt;p&gt;For Steele Solutions, the homepage was archived on 2026-05-26 at &lt;a href="https://web.archive.org/web/20260526012306/https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;https://web.archive.org/web/20260526012306/https://steelesolutions4u.com/&lt;/a&gt;. Anyone can verify that all the claims on the live site were also on the site at archive time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 2: principal career history
&lt;/h2&gt;

&lt;p&gt;For Steele Solutions, both founders are listed with verifiable career claims:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jim Steele: CSSI National Account Executive — links to &lt;a href="https://cssiservices.com/sales/jim-steele/" rel="noopener noreferrer"&gt;https://cssiservices.com/sales/jim-steele/&lt;/a&gt; (live) plus &lt;a href="https://web.archive.org/web/20251209135730/https://cssiservices.com/sales/jim-steele/" rel="noopener noreferrer"&gt;https://web.archive.org/web/20251209135730/https://cssiservices.com/sales/jim-steele/&lt;/a&gt; (Wayback-archived snapshot from 2025-12-09).&lt;/li&gt;
&lt;li&gt;Indiana University Bloomington Business graduate — links to &lt;a href="https://www.wikidata.org/wiki/Q1079140" rel="noopener noreferrer"&gt;https://www.wikidata.org/wiki/Q1079140&lt;/a&gt; plus &lt;a href="https://en.wikipedia.org/wiki/Indiana_University_Bloomington" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Indiana_University_Bloomington&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;First National Bank of Omaha President's Club — links to &lt;a href="https://www.wikidata.org/wiki/Q5453412" rel="noopener noreferrer"&gt;https://www.wikidata.org/wiki/Q5453412&lt;/a&gt; plus &lt;a href="https://en.wikipedia.org/wiki/First_National_Bank_of_Omaha" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/First_National_Bank_of_Omaha&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Wikidata Q-IDs reconcile the claims with the Google Knowledge Graph. Google reads the Q-ID and understands the institution. The Wikipedia URL reinforces it. The Wayback Machine snapshot of the CSSI profile gives Google a permanent third-party citation that doesn't depend on the live CSSI page staying up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 3: partner network with FTC disclosure
&lt;/h2&gt;

&lt;p&gt;Steele Solutions is a brokerage. It earns commissions from referrals. FTC rules require affiliate disclosure. The verification page includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 10-row table listing every processor, lender, and cost segregation partner&lt;/li&gt;
&lt;li&gt;Each row links to the partner's live site&lt;/li&gt;
&lt;li&gt;Below the table, an explicit statement that Steele may receive commission on referrals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This serves two purposes. First, regulatory compliance. Second, the table is a list of 10 outbound links to high-DA financial-services sites (electronicpayments.com, shift4.com, squareup.com, cssiservices.com, etc.). Google interprets that as topical relevance signal — Steele Solutions is in the merchant-services ecosystem because they cite merchant-services partners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 4: where we appear publicly
&lt;/h2&gt;

&lt;p&gt;Plain English list of every place the business is publicly recorded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wayback Machine: 43 of 43 URLs archived&lt;/li&gt;
&lt;li&gt;Google Search Console: domain verified, sitemap submitted, IndexNow accepted&lt;/li&gt;
&lt;li&gt;Bing and Yandex: IndexNow submitted via API&lt;/li&gt;
&lt;li&gt;AI engine surfaces: llms.txt, aeo.json, entity.json, brand.json&lt;/li&gt;
&lt;li&gt;Cross-citations: TDP portfolio, TDG case studies, TWHG network grid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each item links to the verification URL where you can confirm independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 5: public records (the load-bearing one)
&lt;/h2&gt;

&lt;p&gt;For Steele Solutions, the verification page references Taney County, Missouri public real estate ownership records — without publishing the home address. The phrasing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Kimberly and James Steele are jointly listed in Taney County, Missouri public real estate ownership records and personal property tax filings as residents of Branson, Missouri (ZIP 65616). For privacy reasons we do not publish their home address, but anyone can independently verify ownership at the Taney County Collector's search tool."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then a table links to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.taneycountycollector.com/realsearch.php" rel="noopener noreferrer"&gt;https://www.taneycountycollector.com/realsearch.php&lt;/a&gt; (search owner: STEELE)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.taneycountycollector.com/personalsearch.php" rel="noopener noreferrer"&gt;https://www.taneycountycollector.com/personalsearch.php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://beacon.schneidercorp.com/?site=TaneyCountyMO" rel="noopener noreferrer"&gt;https://beacon.schneidercorp.com/?site=TaneyCountyMO&lt;/a&gt; (parcel viewer)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://taneycountyassessor.net/" rel="noopener noreferrer"&gt;https://taneycountyassessor.net/&lt;/a&gt; (Taney County Assessor)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone doing due diligence can independently confirm the owners exist in county public records without the site exposing their home address. This is the maximum-verification minimum-disclosure pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this works
&lt;/h2&gt;

&lt;p&gt;Google's algorithm prioritizes E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness). For a brand-new domain with no inbound links, the standard verification path is slow. The /verification/ page short-circuits the wait by giving Google everything it needs to verify the business in one crawl.&lt;/p&gt;

&lt;p&gt;In Steele Solutions' case, within 14 days of launch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Homepage indexed and ranking position 2 average for branded queries&lt;/li&gt;
&lt;li&gt;Verification page indexed&lt;/li&gt;
&lt;li&gt;6 of 26 priority pages moved from "Discovered, not indexed" to "Submitted and indexed"&lt;/li&gt;
&lt;li&gt;First click-through from organic search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The /verification/ page works because it converts dispersed third-party citations into a single dense surface that Google can crawl and reconcile in one pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template
&lt;/h2&gt;

&lt;p&gt;The pattern is repeatable. For your own small business site:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify every verifiable claim on the site&lt;/li&gt;
&lt;li&gt;Find a third-party source for each claim&lt;/li&gt;
&lt;li&gt;Build a table with three columns: Claim, Source description, Verify URL&lt;/li&gt;
&lt;li&gt;Group tables into sections: identity, principals, partners, public records, where we appear&lt;/li&gt;
&lt;li&gt;Link out aggressively to every cited source&lt;/li&gt;
&lt;li&gt;Submit the page to IndexNow + Wayback Machine the day it ships&lt;/li&gt;
&lt;li&gt;Cross-link from your homepage navigation so internal link equity flows to it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full live Steele Solutions verification page is at &lt;a href="https://steelesolutions4u.com/verification/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/verification/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://schema.org/" rel="noopener noreferrer"&gt;Schema.org&lt;/a&gt; for the entity graph&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.wikidata.org/" rel="noopener noreferrer"&gt;Wikidata&lt;/a&gt; for institutional Q-IDs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.archive.org/" rel="noopener noreferrer"&gt;Internet Archive Wayback Machine&lt;/a&gt; for permanent citation URLs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://search.google.com/search-console" rel="noopener noreferrer"&gt;Google Search Console URL Inspection API&lt;/a&gt; for discovery&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.indexnow.org/" rel="noopener noreferrer"&gt;IndexNow&lt;/a&gt; for accelerated submission to Bing and Yandex&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.taneycountycollector.com/" rel="noopener noreferrer"&gt;Taney County Collector&lt;/a&gt; for the property ownership verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Public repository at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>schema</category>
      <category>beginners</category>
    </item>
    <item>
      <title>FinancialService schema for a real merchant services brokerage: a case study</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 21:37:21 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/financialservice-schema-for-a-real-merchant-services-brokerage-a-case-study-3ho6</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/financialservice-schema-for-a-real-merchant-services-brokerage-a-case-study-3ho6</guid>
      <description>&lt;h1&gt;
  
  
  FinancialService schema for a real merchant services brokerage: a case study
&lt;/h1&gt;

&lt;p&gt;Schema.org gives you &lt;code&gt;FinancialService&lt;/code&gt; as a type. Most sites that use it stop there. Combined with &lt;code&gt;LocalBusiness&lt;/code&gt;, &lt;code&gt;ProfessionalService&lt;/code&gt;, and a properly populated &lt;code&gt;hasOfferCatalog&lt;/code&gt;, it becomes one of the highest-density entity declarations you can put on a small business site.&lt;/p&gt;

&lt;p&gt;This is a walkthrough of how I structured the entity graph for &lt;a href="https://steelesolutions4u.com/" rel="noopener noreferrer"&gt;Steele Solutions&lt;/a&gt;, a family-run merchant services brokerage in Branson, Missouri.&lt;/p&gt;

&lt;h2&gt;
  
  
  The starting type chain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"＠context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"＠graph"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LocalBusiness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FinancialService"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ProfessionalService"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"＠id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson Missouri merchant services firm..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The triple &lt;code&gt;＠type&lt;/code&gt; is intentional. &lt;code&gt;LocalBusiness&lt;/code&gt; gets you into Google's local pack discovery. &lt;code&gt;FinancialService&lt;/code&gt; is the topical type that signals "this is a financial-services business, not a retailer." &lt;code&gt;ProfessionalService&lt;/code&gt; reinforces it for the Knowledge Graph reconciliation pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  hasOfferCatalog: the service spine
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;hasOfferCatalog&lt;/code&gt; is where most small business schemas fall over. The spec asks for an &lt;code&gt;OfferCatalog&lt;/code&gt; with &lt;code&gt;itemListElement&lt;/code&gt; containing &lt;code&gt;Offer&lt;/code&gt; objects, each wrapping a &lt;code&gt;Service&lt;/code&gt;. Most sites either skip it, or list a single Offer with no URL.&lt;/p&gt;

&lt;p&gt;For Steele, every service maps to a real URL on the site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hasOfferCatalog"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OfferCatalog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steele Solutions Service Catalog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"itemListElement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POS Systems"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/pos-systems/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Credit Card Processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/credit-card-processing/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ATM Placements"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/atm-placements/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Small Business Lending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/business-lending/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CSSI Cost Segregation Studies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/cssi-cost-segregation/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dual Pricing and Cash Discount Programs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/dual-pricing/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Free POS Placement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/free-pos/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Square Account Setup via Authorized Referral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/apply/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Business CPR Framework"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/business-cpr/"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"itemOffered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cryptocurrency Payment Acceptance via Shift4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/services/"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ten services. Every Service item has both a name and a URL. The URL bridges the entity graph to the actual page where that service is sold. Google AI Overview and Perplexity both treat the URL on &lt;code&gt;itemOffered&lt;/code&gt; as the authoritative source for that service offering.&lt;/p&gt;

&lt;h2&gt;
  
  
  areaServed: explicit geography
&lt;/h2&gt;

&lt;p&gt;Most merchant services sites declare their city and stop. But a brokerage like Steele's serves multiple states. The schema reflects that exactly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"areaServed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Branson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Springfield"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Joplin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missouri"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bentonville"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"City"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rogers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"containedInPlace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arkansas"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lake Taneycomo"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Table Rock Lake"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the Ozarks"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;17 areas total in the final version, blending &lt;code&gt;City&lt;/code&gt; (with &lt;code&gt;containedInPlace&lt;/code&gt; chaining to &lt;code&gt;State&lt;/code&gt;) and &lt;code&gt;Place&lt;/code&gt; for non-political geographic features. This is what fuels the discovery for queries like "credit card processing Branson MO" or "ATM placement Eureka Springs AR."&lt;/p&gt;

&lt;h2&gt;
  
  
  paymentMethod: GoodRelations URIs
&lt;/h2&gt;

&lt;p&gt;This one is criminally underused. Schema.org doesn't have its own enum for payment methods, but it accepts GoodRelations URIs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"paymentMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#Cash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#Check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#PaymentMethodCreditCard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#DirectDebit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"http://purl.org/goodrelations/v1#ByBankTransferInAdvance"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus a &lt;code&gt;paymentAccepted&lt;/code&gt; string field for human-readable variants. Both fields together feed into Google's payment-types facet in the merchant snippet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Person entities for the founders
&lt;/h2&gt;

&lt;p&gt;Steele Solutions is a husband and wife operation. Both founders get full &lt;code&gt;Person&lt;/code&gt; entities in the graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"＠id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"＠id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#kim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"spouse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"＠id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://steelesolutions4u.com/#jim"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each Person has &lt;code&gt;alumniOf&lt;/code&gt;, &lt;code&gt;hasCredential&lt;/code&gt; (with &lt;code&gt;recognizedBy&lt;/code&gt; linking to the institution's Wikidata QID), &lt;code&gt;knowsAbout&lt;/code&gt;, &lt;code&gt;worksFor&lt;/code&gt;, &lt;code&gt;memberOf&lt;/code&gt;, &lt;code&gt;additionalProperty&lt;/code&gt;, and &lt;code&gt;sameAs&lt;/code&gt; arrays. Jim's &lt;code&gt;alumniOf&lt;/code&gt; chains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"alumniOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CollegeOrUniversity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Indiana University Bloomington"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.indiana.edu/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://www.wikidata.org/wiki/Q1079140"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/Indiana_University_Bloomington"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Wikidata Q-ID is the load-bearing entry. Google's Knowledge Graph reconciles the Person to the institution using the Q-ID, which gives Jim's bio explicit verifiable-entity provenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  hasCredential with recognizedBy
&lt;/h2&gt;

&lt;p&gt;Most schemas declare credentials as flat strings. The better pattern is &lt;code&gt;EducationalOccupationalCredential&lt;/code&gt; with &lt;code&gt;recognizedBy&lt;/code&gt; pointing to the awarding institution as its own Organization entity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hasCredential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EducationalOccupationalCredential"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First National Bank of Omaha President's Club"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credentialCategory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sales Performance Award"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recognizedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"＠type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BankOrCreditUnion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First National Bank of Omaha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.fnbo.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://www.wikidata.org/wiki/Q5453412"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/First_National_Bank_of_Omaha"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the credential is graph-linked to a real Wikidata entity. AI engines and Knowledge Graph can verify Jim's claimed achievement by traversing to the FNBO entity and confirming the institution exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  sameAs as the verification spine
&lt;/h2&gt;

&lt;p&gt;The org's &lt;code&gt;sameAs&lt;/code&gt; array is where third-party verifications live. Steele's includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Maps CID (for the Google Business Profile)&lt;/li&gt;
&lt;li&gt;All 10 partner sites (Electronic Payments, ClearPay, Shift4, etc.)&lt;/li&gt;
&lt;li&gt;Wayback Machine archive URL&lt;/li&gt;
&lt;li&gt;Taney County, Missouri public real estate records URL&lt;/li&gt;
&lt;li&gt;Personal property tax records URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Wayback URL is the permanent citation. Live URLs can change. Wayback URLs are immutable. When you put &lt;code&gt;https://web.archive.org/web/20260526012306/https://steelesolutions4u.com/&lt;/code&gt; in your sameAs, you give crawlers a citation that survives even if your site goes down.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this buys you
&lt;/h2&gt;

&lt;p&gt;Schema density is not a vanity metric. Google's &lt;a href="https://search.google.com/test/rich-results" rel="noopener noreferrer"&gt;structured data testing tool&lt;/a&gt; measures it. AI engines weigh it. Bing's Copilot weighs it heavily.&lt;/p&gt;

&lt;p&gt;In Steele's case, the dense schema produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local pack appearance within 7 days of launch for "credit card processing Branson MO"&lt;/li&gt;
&lt;li&gt;Position-3 average for the homepage on indexed queries within 14 days&lt;/li&gt;
&lt;li&gt;Knowledge Panel sidebar (pending Google Business Profile verification)&lt;/li&gt;
&lt;li&gt;AI engine citations on ChatGPT and Perplexity within 21 days of launch&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The live example
&lt;/h2&gt;

&lt;p&gt;The complete entity graph is at &lt;a href="https://steelesolutions4u.com/entity.json" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/entity.json&lt;/a&gt;. The schema is also embedded inline on every page of the site so crawlers and AI engines get the full graph regardless of which entry point they hit.&lt;/p&gt;

&lt;p&gt;The public verification page at &lt;a href="https://steelesolutions4u.com/verification/" rel="noopener noreferrer"&gt;https://steelesolutions4u.com/verification/&lt;/a&gt; cross-references every schema claim with the third-party source backing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://schema.org/" rel="noopener noreferrer"&gt;Schema.org&lt;/a&gt; for the type definitions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.wikidata.org/" rel="noopener noreferrer"&gt;Wikidata&lt;/a&gt; for institutional Q-IDs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.archive.org/" rel="noopener noreferrer"&gt;Internet Archive Wayback Machine&lt;/a&gt; for permanent citation URLs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://search.google.com/search-console" rel="noopener noreferrer"&gt;Google Search Console&lt;/a&gt; for index status verification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.indexnow.org/" rel="noopener noreferrer"&gt;IndexNow&lt;/a&gt; for accelerated discovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full Steele Solutions resources are public at &lt;a href="https://github.com/Janady13/steele-solutions-resources" rel="noopener noreferrer"&gt;github.com/Janady13/steele-solutions-resources&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>schema</category>
      <category>seo</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>HTTP SEO headers: canonical reference</title>
      <dc:creator>Joseph Anady</dc:creator>
      <pubDate>Tue, 26 May 2026 06:46:17 +0000</pubDate>
      <link>https://dev.to/joseph_anady_214bacedf939/http-seo-headers-canonical-reference-2ipm</link>
      <guid>https://dev.to/joseph_anady_214bacedf939/http-seo-headers-canonical-reference-2ipm</guid>
      <description>&lt;h1&gt;
  
  
  framework-http-seo-headers.md
&lt;/h1&gt;

&lt;p&gt;Comprehensive reference for the three HTTP response headers that control indexing, resource discovery, and URL forwarding: &lt;code&gt;X-Robots-Tag&lt;/code&gt; for indexing directives on any file type, &lt;code&gt;Link&lt;/code&gt; for canonicals/hreflang/resource hints expressed at the HTTP layer, and &lt;code&gt;Location&lt;/code&gt; for redirects. Built for Bubbles (Debian, Nginx 1.26+, self hosted origin at 169.155.162.118, no Cloudflare or third party CDN in front). Companion to framework-http-caching-headers.md, framework-http-content-headers.md, UNIVERSAL-RANKING-FRAMEWORK.md, and SEO BUILD REFERENCE v2.4.&lt;/p&gt;

&lt;p&gt;Audience: humans configuring nginx, AI assistants generating or repairing nginx config, and anyone troubleshooting "PDF appearing in Google when it should not", "preload not picked up", "redirect chain killing crawl budget", or "wrong page is canonical" anomalies on a self hosted stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  TABLE OF CONTENTS
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Definition&lt;/li&gt;
&lt;li&gt;Why It Matters&lt;/li&gt;
&lt;li&gt;What This Covers&lt;/li&gt;
&lt;li&gt;The Indexing Authority Mental Model (read this first)&lt;/li&gt;
&lt;li&gt;X-Robots-Tag (every meta robots directive at the HTTP layer)&lt;/li&gt;
&lt;li&gt;Link (canonical, alternate, hreflang, preload, prefetch at HTTP)&lt;/li&gt;
&lt;li&gt;Location (redirect target with status code semantics)&lt;/li&gt;
&lt;li&gt;How These Headers Interact&lt;/li&gt;
&lt;li&gt;Asset Class And Use Case Recipes&lt;/li&gt;
&lt;li&gt;Bubbles Nginx Reference Block (paste ready)&lt;/li&gt;
&lt;li&gt;Audit Checklist (50+ items)&lt;/li&gt;
&lt;li&gt;Common Pitfalls&lt;/li&gt;
&lt;li&gt;Diagnostic Commands (curl, GSC URL Inspection, browser devtools)&lt;/li&gt;
&lt;li&gt;Cross-References&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. DEFINITION
&lt;/h2&gt;

&lt;p&gt;SEO and indexing headers tell search engine crawlers what they may or may not do with a resource, where its canonical version lives, what related resources exist, and where a moved URL can now be found. They operate at the HTTP layer, which means they apply to every response regardless of body content type. The three headers split into three concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Indexing control&lt;/strong&gt;: &lt;code&gt;X-Robots-Tag&lt;/code&gt;. It answers "may you index this, follow its links, show a snippet, cache it, translate it?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource relationships&lt;/strong&gt;: &lt;code&gt;Link&lt;/code&gt;. It answers "what is the canonical URL, what alternates exist, what resources should the browser preload, what is related to this resource?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forwarding&lt;/strong&gt;: &lt;code&gt;Location&lt;/code&gt;. It answers "this URL has moved; here is where to go next."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together these three headers shape every aspect of how search engines and AI crawlers understand a site's structure, what they index, and how PageRank or its modern equivalents flow between URLs. Getting any one of them wrong has direct ranking consequences: deindexed pages, lost canonical signals, broken hreflang clusters, redirect chains that bleed crawl budget, or worse, redirects that point to attacker controlled domains.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. WHY IT MATTERS
&lt;/h2&gt;

&lt;p&gt;Five independent pressures push correct SEO headers from "nice to have" to "required infrastructure" in 2025 and forward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indexing is selective by default.&lt;/strong&gt; Googlebot's crawl budget is finite. ClaudeBot, GPTBot, PerplexityBot, OAI-SearchBot, and other AI crawlers ration their requests even more aggressively. Sites that signal &lt;code&gt;noindex&lt;/code&gt; or &lt;code&gt;nofollow&lt;/code&gt; for low value URLs (filtered listings, search result pages, faceted navigation, internal admin) reclaim that budget for pages that actually matter. Sites that fail to signal end up with thousands of useless URLs in the index diluting their topical authority.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non HTML files cannot use meta tags.&lt;/strong&gt; PDFs, images, videos, CSV exports, ZIP archives, and any other binary file cannot contain &lt;code&gt;&amp;lt;meta name="robots"&amp;gt;&lt;/code&gt;. The only way to control their indexing is &lt;code&gt;X-Robots-Tag&lt;/code&gt;. A site that publishes PDFs without the header is silently allowing every PDF to be indexed, which causes brand pages and outdated material to outrank current HTML pages for the same query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource hints are now a Core Web Vitals lever.&lt;/strong&gt; Modern browsers pre fetch resources declared in HTTP &lt;code&gt;Link&lt;/code&gt; headers before parsing the HTML body. This shaves 50 to 300 ms off LCP for the largest contentful paint candidate (typically the hero image or above the fold font). Google's recommended pattern for hero image LCP optimization explicitly uses &lt;code&gt;Link: &amp;lt;hero.webp&amp;gt;; rel=preload; as=image; fetchpriority=high&lt;/code&gt; as an HTTP header, not just the HTML link element.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;103 Early Hints exists and matters.&lt;/strong&gt; Nginx 1.25+ supports HTTP 103 Early Hints, which lets the server send &lt;code&gt;Link&lt;/code&gt; preload headers before the final response is ready. Chrome and Edge consume Early Hints and begin fetching critical resources during the time the server is still computing the page. On dynamic sites this can shave 100 to 500 ms off LCP at zero application cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redirect chains are crawl killers and ranking killers.&lt;/strong&gt; Each hop in a redirect chain adds latency, consumes one unit of crawl budget, and risks losing equity along the way. Google has stated that all redirect codes (301, 302, 307, 308) are treated equivalently for ranking purposes, but the practical reality is that chains over three hops trigger soft 404 handling and lost consolidation. A single direct redirect is always better than a chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open redirects are an active attack surface.&lt;/strong&gt; A redirect endpoint that accepts an unvalidated target parameter (&lt;code&gt;/redirect?url=...&lt;/code&gt;) lets attackers craft phishing URLs that appear to come from your domain. Modern phishing kits scan for these endpoints. Every redirect endpoint that accepts user input must validate the target against an allow list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost of getting it wrong.&lt;/strong&gt; Misconfigured SEO headers produce silent ranking failures and loud security failures. Examples from production sites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A staging subdomain was indexed because nobody set &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt;. Six months later Google merged duplicate content signals from staging and production, halving organic traffic for shared terms.&lt;/li&gt;
&lt;li&gt;A site's brand PDFs from 2018 ranked above the 2024 HTML refresh because the old PDFs were indexed and Google had no signal that they were superseded.&lt;/li&gt;
&lt;li&gt;A new product launch shipped with &lt;code&gt;Link: &amp;lt;previous-product&amp;gt;; rel=canonical&lt;/code&gt; accidentally pointing at the old product page, blocking the new launch from indexing for three weeks.&lt;/li&gt;
&lt;li&gt;A 301 chain (&lt;code&gt;/old&lt;/code&gt; → &lt;code&gt;/new&lt;/code&gt; → &lt;code&gt;/newer&lt;/code&gt; → &lt;code&gt;/current&lt;/code&gt;) bled crawl budget for years until someone audited and collapsed it to a single hop.&lt;/li&gt;
&lt;li&gt;An open redirect on &lt;code&gt;/r?url=...&lt;/code&gt; was used in a phishing campaign against the client's email list, prompting cease and desist orders and emergency cleanup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All preventable with the rules below.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. WHAT THIS COVERS
&lt;/h2&gt;

&lt;p&gt;Each of the three headers gets the same six part treatment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What it does&lt;/strong&gt;: the canonical RFC and Google specification plus the practical implication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax and directives&lt;/strong&gt;: every legal value, what it means, and when it is wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to build it on Bubbles&lt;/strong&gt;: paste ready nginx config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to verify it&lt;/strong&gt;: curl commands plus Google Search Console URL Inspection where applicable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to troubleshoot&lt;/strong&gt;: the four or five failure modes seen in the field and how to recognize each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to fix common breakage&lt;/strong&gt;: ordered repair steps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Recipes for the most common asset classes and use cases are collected in Section 9.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. THE INDEXING AUTHORITY MENTAL MODEL (READ THIS FIRST)
&lt;/h2&gt;

&lt;p&gt;Every search engine and AI crawler that fetches a URL runs the same dispatch loop. Internalize it and every header choice becomes obvious.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Crawler requests URL
        |
        v
Server responds with status code
        |
        v
Status 200, 304? --&amp;gt; proceed to indexing logic
Status 301, 308? --&amp;gt; follow Location, consolidate signals to target
Status 302, 307? --&amp;gt; follow Location, do NOT consolidate (temporary)
Status 4xx?      --&amp;gt; mark URL as gone or soft 404
Status 5xx?      --&amp;gt; defer, retry later, may eventually drop from index
        |
        v
Read X-Robots-Tag header
        |
        v
Directives present?
   |                                   |
  YES                                 NO
   |                                   |
   v                                   v
Apply directives:               Default behavior:
- noindex: do not add to index   - index this URL
- nofollow: do not follow links  - follow all links on it
- nosnippet: no preview text     - show snippet in SERP
- noarchive: no cached copy      - allow cached copy
- max-snippet:N: cap snippet     - default snippet length
        |
        v
Read Link header
        |
        v
- rel="canonical": treat target as primary, consolidate signals
- rel="alternate" hreflang: register language variants
- rel="alternate" media: register mobile/print variants
- rel="prev" / rel="next": pagination (deprecated for SEO)
- rel="preload" / "prefetch": browser hints, ignored by crawlers
        |
        v
Read HTML body (if Content-Type is text/html and not noindex)
        |
        v
Parse &amp;lt;head&amp;gt; for:
- &amp;lt;meta name="robots"&amp;gt; (may override or supplement X-Robots-Tag)
- &amp;lt;link rel="canonical"&amp;gt; (may override or supplement Link header)
- &amp;lt;link rel="alternate" hreflang="..."&amp;gt;
- &amp;lt;link rel="amphtml"&amp;gt;
        |
        v
Reconcile signals from HTTP and HTML
        |
        v
Update index entry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three rules govern the system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTTP signals reach every file type.&lt;/strong&gt; Meta tags only work for HTML. PDFs, images, JSON, CSV all rely exclusively on HTTP headers. If you publish any non HTML file you intend to control, you must use the HTTP layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The most restrictive directive wins.&lt;/strong&gt; Combining &lt;code&gt;noindex&lt;/code&gt; and &lt;code&gt;index&lt;/code&gt; (across HTTP and HTML, or across multiple X-Robots-Tag entries) resolves to &lt;code&gt;noindex&lt;/code&gt;. Combining &lt;code&gt;nosnippet&lt;/code&gt; and &lt;code&gt;max-snippet:200&lt;/code&gt; resolves to &lt;code&gt;nosnippet&lt;/code&gt;. There is no "negotiation" mechanism; restrictive always beats permissive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirects consolidate or do not consolidate based on status code semantics.&lt;/strong&gt; Permanent codes (301, 308) tell crawlers to merge signals into the target URL. Temporary codes (302, 307) tell crawlers to keep the original URL indexed and treat the redirect as situational. Google has said the difference is "smaller than people think" for ranking, but the difference is real and matters for index hygiene.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A correct header set produces consistent behavior across Googlebot, Bingbot, ClaudeBot, GPTBot, PerplexityBot, Applebot, OAI-SearchBot, and every other crawler. The same response, the same outcome everywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. X-ROBOTS-TAG (EVERY META ROBOTS DIRECTIVE AT THE HTTP LAYER)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 What It Does
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;X-Robots-Tag&lt;/code&gt; is the HTTP response header that conveys indexing directives to crawlers. Functionally equivalent to &lt;code&gt;&amp;lt;meta name="robots" content="..."&amp;gt;&lt;/code&gt; but applies to any response type, not just HTML. Documented by Google at developers.google.com/search/docs/crawling-indexing/robots-meta-tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Robots-Tag: noindex
X-Robots-Tag: noindex, nofollow
X-Robots-Tag: googlebot: nosnippet, notranslate
X-Robots-Tag: max-snippet:160, max-image-preview:large
X-Robots-Tag: unavailable_after: 31 Dec 2026 23:59:59 GMT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the only way to control indexing for non HTML resources: PDFs, images (when accessed directly by URL), videos, JSON endpoints, CSV exports, ZIP downloads, any binary file. For HTML pages, both &lt;code&gt;X-Robots-Tag&lt;/code&gt; and &lt;code&gt;&amp;lt;meta name="robots"&amp;gt;&lt;/code&gt; work and can be combined.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Every Directive Available
&lt;/h3&gt;

&lt;p&gt;The full set of directives Google supports as of 2026. Other major crawlers (Bing, Yandex, Baidu, ClaudeBot, GPTBot) support most of these.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indexing directives:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directive&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;all&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default. Equivalent to "no restrictions". Same as omitting the header&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noindex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do not include this URL in the search index&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nofollow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do not follow any links on this page (does not pass equity)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shorthand for &lt;code&gt;noindex, nofollow&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noarchive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do not show a "Cached" link in search results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nosnippet&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do not show a text or video snippet in search results. Also blocks use of the content in AI Overviews and similar features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noimageindex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do not index any images on this page or use them as canonical sources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;notranslate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do not offer translation of this page in search results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;indexifembedded&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allow indexing of this content when embedded via iframe in another page, even when &lt;code&gt;noindex&lt;/code&gt; also applies. Useful for media publishers who want syndication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unavailable_after: &amp;lt;date&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;After the specified date and time, treat this URL as &lt;code&gt;noindex&lt;/code&gt;. Date format: &lt;code&gt;Day, DD Mon YYYY HH:MM:SS GMT&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Snippet control directives:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directive&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max-snippet: &amp;lt;number&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum length in characters for text snippets. Special values: &lt;code&gt;0&lt;/code&gt; (no snippet, same as &lt;code&gt;nosnippet&lt;/code&gt;), &lt;code&gt;-1&lt;/code&gt; (no limit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max-image-preview: &amp;lt;setting&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Largest image preview allowed in snippets. Values: &lt;code&gt;none&lt;/code&gt;, &lt;code&gt;standard&lt;/code&gt;, &lt;code&gt;large&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max-video-preview: &amp;lt;number&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum number of seconds for video previews. Special values: &lt;code&gt;0&lt;/code&gt; (static image only), &lt;code&gt;-1&lt;/code&gt; (no limit)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Removed or deprecated:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directive&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noodp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removed. Open Directory Project is defunct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noydir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removed. Yahoo Directory is defunct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noyaca&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yandex specific. Yandex Catalog is defunct&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5.3 Bot Specific Syntax
&lt;/h3&gt;

&lt;p&gt;By default, directives apply to every crawler. To target a specific bot, prefix the directives with the bot's user agent token followed by a colon. Multiple &lt;code&gt;X-Robots-Tag&lt;/code&gt; headers can stack to specify different rules for different bots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Robots-Tag: googlebot: nosnippet, notranslate
X-Robots-Tag: bingbot: noarchive
X-Robots-Tag: noindex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Googlebot: gets &lt;code&gt;nosnippet, notranslate&lt;/code&gt; AND inherits the global &lt;code&gt;noindex&lt;/code&gt; (because the unprefixed line applies to it too).&lt;/li&gt;
&lt;li&gt;Bingbot: gets &lt;code&gt;noarchive&lt;/code&gt; AND the global &lt;code&gt;noindex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;All other crawlers: get only &lt;code&gt;noindex&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important nuance about Google specifically:&lt;/strong&gt; Google only honors bot prefix syntax for &lt;code&gt;googlebot&lt;/code&gt; and &lt;code&gt;googlebot-news&lt;/code&gt;. Other Google crawlers (Googlebot-Image, Googlebot-Video, Storebot-Google, AdsBot-Google) do not respond to bot prefixed &lt;code&gt;X-Robots-Tag&lt;/code&gt; directives. They are controlled via robots.txt user agent blocks instead.&lt;/p&gt;

&lt;p&gt;Common bot tokens worth knowing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bot&lt;/th&gt;
&lt;th&gt;Token&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Googlebot (web)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;googlebot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Googlebot News&lt;/td&gt;
&lt;td&gt;&lt;code&gt;googlebot-news&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bingbot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bingbot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applebot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;applebot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ClaudeBot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claudebot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPTBot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gptbot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PerplexityBot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;perplexitybot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OAI-SearchBot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;oai-searchbot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YandexBot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yandex&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Baiduspider&lt;/td&gt;
&lt;td&gt;&lt;code&gt;baiduspider&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5.4 How To Build It On Bubbles
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Block all indexing for a staging or demo site:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;staging.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Block every page from every crawler&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;nofollow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Also block via robots.txt for belt and suspenders&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/robots.txt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="s"&gt;"User-agent:&lt;/span&gt; &lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;nDisallow:&lt;/span&gt; &lt;span class="n"&gt;/\n"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Block indexing for non HTML files only:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(pdf|doc|docx|xls|xlsx|csv|zip|tar|gz)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;1d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=86400"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the primary use case for &lt;code&gt;X-Robots-Tag&lt;/code&gt;: file types where you cannot use meta tags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Block image indexing while allowing the HTML page to index:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Apply at the image location only, not the parent HTML&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(jpg|jpeg|png|gif|webp|avif|svg)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML page itself remains indexable; only direct image URLs are blocked from being indexed as standalone results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set snippet limits site wide:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"max-snippet:200,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:large,&lt;/span&gt; &lt;span class="s"&gt;max-video-preview:-1"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# Other directives...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the recommended baseline for most sites. It tells Google: allow up to 200 character text snippets, allow large image previews, no limit on video preview length.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different rules for different bots:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In a server block, stack multiple add_header directives&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"googlebot:&lt;/span&gt; &lt;span class="nf"&gt;max-snippet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:large"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"bingbot:&lt;/span&gt; &lt;span class="nf"&gt;max-snippet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noai"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order does not matter for parsing. Each header is independent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time limited content (unavailable_after):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/promotion/black-friday-2026.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"unavailable_after:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="s"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;2026&lt;/span&gt; &lt;span class="nf"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="s"&gt;GMT"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;1d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=86400"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After December 1, 2026, Google will drop this URL from search results without requiring a manual removal request. The page itself can remain accessible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The add_header inheritance trap applies here too.&lt;/strong&gt; A nested location's &lt;code&gt;add_header&lt;/code&gt; wipes parent declarations. Use the snippet include pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/nginx/snippets/robots-baseline.conf&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"max-snippet:200,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:large,&lt;/span&gt; &lt;span class="s"&gt;max-video-preview:-1"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# In every location that needs it&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/blog/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/robots-baseline&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=300"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.5 The robots.txt vs X-Robots-Tag Distinction
&lt;/h3&gt;

&lt;p&gt;These two mechanisms control different things. Confusing them is the most common SEO mistake on the planet.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Controls&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;robots.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Which URLs the crawler is allowed to fetch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;X-Robots-Tag&lt;/code&gt; (or &lt;code&gt;&amp;lt;meta robots&amp;gt;&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Which fetched URLs the crawler is allowed to index&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A URL blocked by robots.txt is never fetched, which means the crawler never sees the &lt;code&gt;X-Robots-Tag&lt;/code&gt; header. If the URL has external links pointing to it, Google may index it anyway as a "URL only" entry (no title, no snippet, just the URL) based on those external signals.&lt;/p&gt;

&lt;p&gt;To actually deindex a URL:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Remove the robots.txt block&lt;/strong&gt; so the crawler can fetch the URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt;&lt;/strong&gt; to the response.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wait for the crawler to re fetch and process the directive.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then optionally add the robots.txt block back&lt;/strong&gt; to prevent further crawling, but only after Google has processed the noindex.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Get this order wrong and the URL stays indexed forever. Get it right and the URL drops from the index within a crawl cycle (days to weeks).&lt;/p&gt;

&lt;h3&gt;
  
  
  5.6 How To Verify
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Confirm header is present&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/some-page | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag

&lt;span class="c"&gt;# 2. Check for a specific file type&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/downloads/report.pdf | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag

&lt;span class="c"&gt;# 3. Check what Googlebot sees&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag

&lt;span class="c"&gt;# 4. Test bot specific directives&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag

&lt;span class="c"&gt;# 5. Compare HTTP header to HTML meta tag&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== HTTP X-Robots-Tag ==="&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== HTML meta robots ==="&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'name="robots"'&lt;/span&gt;

&lt;span class="c"&gt;# 6. Verify a site wide block is in effect&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;path &lt;span class="k"&gt;in&lt;/span&gt; / /about /blog /contact /robots.txt&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== https://staging.example.com&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt; ==="&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"https://staging.example.com&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Google Search Console URL Inspection&lt;/strong&gt; for the authoritative check on whether Google sees and respects the directive:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Google Search Console for the property.&lt;/li&gt;
&lt;li&gt;Paste the URL into the top search bar.&lt;/li&gt;
&lt;li&gt;Click "Test live URL".&lt;/li&gt;
&lt;li&gt;Under "Page indexing", look for "Indexing allowed?" and the source of any "noindex" detection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Live Test fetches the URL with Googlebot's actual user agent and shows the headers it saw. This is the ground truth for SEO purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.7 Troubleshooting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Page is still in Google index despite &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt;.&lt;/strong&gt;&lt;br&gt;
Causes ranked by frequency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The URL is blocked by robots.txt, so Googlebot cannot fetch it and never sees the header. Remove the robots.txt block, wait, then optionally re add.&lt;/li&gt;
&lt;li&gt;The page has not been re crawled since the directive was added. Wait or request indexing via Search Console URL Inspection.&lt;/li&gt;
&lt;li&gt;The directive has a typo (e.g. &lt;code&gt;no-index&lt;/code&gt; instead of &lt;code&gt;noindex&lt;/code&gt;). Verify with curl.&lt;/li&gt;
&lt;li&gt;A CDN is stripping the header. Not applicable on Bubbles. Verify with &lt;code&gt;curl --resolve&lt;/code&gt; directly against the origin.&lt;/li&gt;
&lt;li&gt;The page has strong external links and Google retains a URL only entry. This is rare and resolves over time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: PDF is being indexed and outranking the corresponding HTML page.&lt;/strong&gt;&lt;br&gt;
Cause: No &lt;code&gt;X-Robots-Tag&lt;/code&gt; on the PDF location.&lt;br&gt;
Fix: see Section 5.4. Add &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt; to a location matching &lt;code&gt;\.pdf$&lt;/code&gt;. If you want the PDF indexable but not outranking the HTML, add &lt;code&gt;&amp;lt;link rel=canonical&amp;gt;&lt;/code&gt; to the HTML and &lt;code&gt;X-Robots-Tag: noindex, nofollow&lt;/code&gt; to the PDF.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Two &lt;code&gt;X-Robots-Tag&lt;/code&gt; headers appear and seem to conflict.&lt;/strong&gt;&lt;br&gt;
Multiple directives across multiple headers are interpreted as a union. The most restrictive wins. &lt;code&gt;X-Robots-Tag: index&lt;/code&gt; plus &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt; resolves to &lt;code&gt;noindex&lt;/code&gt;. There is no conflict; this is the spec.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptom: &lt;code&gt;unavailable_after&lt;/code&gt; date passed but URL is still indexed.&lt;/strong&gt;&lt;br&gt;
Causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Date format is wrong. Must be RFC 850 or RFC 822 format. The Google docs recommend &lt;code&gt;Day, DD Mon YYYY HH:MM:SS GMT&lt;/code&gt;. Verify with curl.&lt;/li&gt;
&lt;li&gt;Google has not re crawled since the date passed. Crawl frequency depends on the URL's profile.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unavailable_after&lt;/code&gt; is intentionally not retroactive in a strong sense; it influences future crawls.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: AI engines (ChatGPT, Claude, Perplexity) are still using content despite &lt;code&gt;nosnippet&lt;/code&gt;.&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;nosnippet&lt;/code&gt; directive applies to Google search results, including AI Overviews. AI engines that crawl independently (ChatGPT search, Claude search, Perplexity) honor their own published opt out signals which often differ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI: respect &lt;code&gt;User-agent: GPTBot&lt;/code&gt; in robots.txt&lt;/li&gt;
&lt;li&gt;Anthropic: respect &lt;code&gt;User-agent: ClaudeBot&lt;/code&gt; in robots.txt&lt;/li&gt;
&lt;li&gt;Perplexity: respect &lt;code&gt;User-agent: PerplexityBot&lt;/code&gt; in robots.txt&lt;/li&gt;
&lt;li&gt;Common Crawl: respect &lt;code&gt;User-agent: CCBot&lt;/code&gt; in robots.txt
Add explicit robots.txt blocks for each AI agent you want to opt out of, in addition to any &lt;code&gt;X-Robots-Tag&lt;/code&gt; directives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Bot prefixed directive ignored.&lt;/strong&gt;&lt;br&gt;
Google only honors &lt;code&gt;googlebot:&lt;/code&gt; and &lt;code&gt;googlebot-news:&lt;/code&gt; prefixes. Other Google crawlers (Googlebot-Image, Googlebot-Video) are not controllable via this mechanism. Use robots.txt for those.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.8 How To Fix Common Breakage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Case: Staging site indexed in Google.&lt;/strong&gt;&lt;br&gt;
Add to the server block immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;staging.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;nofollow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# ... other config ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nginx -t &amp;amp;&amp;amp; systemctl reload nginx&lt;/code&gt;. Then in Search Console, request removal for the entire staging subdomain. The combination of the noindex header (preventing re indexation) and the removal request (immediate effect) resolves the issue within hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: All PDFs are appearing in search and bleeding click traffic from HTML pages.&lt;/strong&gt;&lt;br&gt;
Block all PDFs from indexing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.pdf&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=86400"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PDFs remain downloadable; only their index entries disappear. Existing index entries drop on next crawl.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: A campaign page needs to be deindexed after the campaign ends.&lt;/strong&gt;&lt;br&gt;
Add &lt;code&gt;unavailable_after&lt;/code&gt; with the campaign end date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/campaigns/spring-2026.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"unavailable_after:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="s"&gt;Jun&lt;/span&gt; &lt;span class="mi"&gt;2026&lt;/span&gt; &lt;span class="nf"&gt;23&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;59&lt;/span&gt; &lt;span class="s"&gt;GMT"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No manual intervention required after June 30.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: Need to allow ClaudeBot but block GPTBot.&lt;/strong&gt;&lt;br&gt;
Use robots.txt (not X-Robots-Tag, since both ClaudeBot and GPTBot have limited bot prefix support):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: GPTBot
Disallow: /

User-agent: ClaudeBot
Allow: /

User-agent: *
Allow: /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Serve via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/robots.txt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;1h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=3600"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. LINK (CANONICAL, ALTERNATE, HREFLANG, PRELOAD, PREFETCH AT HTTP)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6.1 What It Does
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Link&lt;/code&gt; header expresses relationships between the current response and other resources. Defined in RFC 8288. The same semantic content as the HTML &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; element, but in HTTP form. Critical for non HTML responses (PDFs cannot contain &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tags but can have HTTP &lt;code&gt;Link&lt;/code&gt; headers) and for performance optimization (HTTP &lt;code&gt;Link&lt;/code&gt; is processed before HTML parsing begins).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;https://example.com/page&amp;gt;; rel="canonical"
Link: &amp;lt;https://example.com/es/page&amp;gt;; rel="alternate"; hreflang="es-MX"
Link: &amp;lt;/css/main.css&amp;gt;; rel="preload"; as="style"
Link: &amp;lt;/hero.webp&amp;gt;; rel="preload"; as="image"; fetchpriority="high"
Link: &amp;lt;https://cdn.example.com&amp;gt;; rel="preconnect"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiple relationships can be comma separated in a single header or split across multiple &lt;code&gt;Link&lt;/code&gt; headers. Both forms are equivalent.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.2 Syntax
&lt;/h3&gt;

&lt;p&gt;The general form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;URI&amp;gt;; param1=value1; param2="value 2"
Link: &amp;lt;URI1&amp;gt;; rel="..."; param="..." , &amp;lt;URI2&amp;gt;; rel="..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URI is wrapped in angle brackets: &lt;code&gt;&amp;lt;https://example.com/x&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Parameters are separated from the URI by a semicolon.&lt;/li&gt;
&lt;li&gt;Parameters are separated from each other by semicolons.&lt;/li&gt;
&lt;li&gt;Multiple relationships are separated by commas (use one comma per Link header line; do not nest).&lt;/li&gt;
&lt;li&gt;Quote values with spaces or special characters using double quotes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rel&lt;/code&gt; is required for almost every meaningful Link header.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6.3 Relationship Types
&lt;/h3&gt;

&lt;p&gt;The values for &lt;code&gt;rel&lt;/code&gt; come from the IANA Link Relations registry. The ones that matter on the web:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SEO and canonicalization:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;rel&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;canonical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Declare the canonical URL for this resource. Critical for SEO. The target URL is treated as the authoritative version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;alternate&lt;/code&gt; (with &lt;code&gt;hreflang&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Declare a language or region variant of the current resource. Used for international SEO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;alternate&lt;/code&gt; (with &lt;code&gt;type="application/rss+xml"&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Declare an RSS or Atom feed for this page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;alternate&lt;/code&gt; (with &lt;code&gt;media&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Declare a print stylesheet, mobile variant, or other media variant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amphtml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Declare the AMP version of this page. Less relevant in 2026 as AMP has been deprecated by Google&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Previous page in a paginated series. Google announced in 2019 they ignore this; still useful for browser navigation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;next&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Next page in a paginated series. Same status as prev&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;up&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Parent resource in a hierarchical structure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;rel&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;as&lt;/code&gt; required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;preload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch this resource at high priority for the current page. Discovered before HTML parsing finishes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prefetch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch this resource at low priority for likely future navigation&lt;/td&gt;
&lt;td&gt;No, but recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;preconnect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open a TCP/TLS connection to this origin in advance&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dns-prefetch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Resolve DNS for this origin in advance&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;modulepreload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Preload a JavaScript ES module and parse it&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prerender&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Render this URL in a background tab. Largely replaced by Speculation Rules&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Other:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;rel&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stylesheet&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This resource is a CSS stylesheet. Almost never used as HTTP Link header; use HTML link tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;icon&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Favicon. Almost never used as HTTP Link; use HTML link tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;manifest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PWA manifest URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;help&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reference to a help document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;license&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reference to license information for the content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;author&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reference to author information&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  6.4 The &lt;code&gt;as&lt;/code&gt; Parameter For Preload
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;rel="preload"&lt;/code&gt; requires an &lt;code&gt;as&lt;/code&gt; parameter declaring the resource type. The browser uses this to set the correct request priority, Accept headers, and CSP enforcement. Wrong &lt;code&gt;as&lt;/code&gt; value causes the browser to discard the preload and re fetch.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;code&gt;as&lt;/code&gt; value&lt;/th&gt;
&lt;th&gt;For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;script&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JavaScript files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSS files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;font&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Web fonts. Requires &lt;code&gt;crossorigin&lt;/code&gt; parameter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Images (JPEG, PNG, WebP, AVIF, SVG)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;XHR or fetch() targets (JSON APIs, etc). Requires &lt;code&gt;crossorigin&lt;/code&gt; if cross origin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;document&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iframe document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;video&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Video files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;audio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Audio files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;track&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WebVTT track files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;worker&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Web Worker scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  6.5 fetchpriority
&lt;/h3&gt;

&lt;p&gt;Modern browsers (Chrome 101+, Edge 101+, Safari 17.2+, Firefox 132+) support the &lt;code&gt;fetchpriority&lt;/code&gt; parameter on preload and other resource hints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;/hero.webp&amp;gt;; rel=preload; as=image; fetchpriority=high
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Values: &lt;code&gt;high&lt;/code&gt;, &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;auto&lt;/code&gt; (default). Used to bump or demote a specific resource's priority within the browser's fetch queue. Critical for LCP optimization: marking the hero image as &lt;code&gt;fetchpriority=high&lt;/code&gt; typically moves LCP earlier by 100 to 400 ms.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.6 crossorigin
&lt;/h3&gt;

&lt;p&gt;Required for fonts and for any cross origin preload that uses CORS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;/fonts/main.woff2&amp;gt;; rel=preload; as=font; crossorigin
Link: &amp;lt;https://cdn.example.com/api.js&amp;gt;; rel=preload; as=script; crossorigin=anonymous
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Values: &lt;code&gt;anonymous&lt;/code&gt; (no credentials sent, default for &lt;code&gt;crossorigin&lt;/code&gt;) or &lt;code&gt;use-credentials&lt;/code&gt; (send cookies and auth).&lt;/p&gt;

&lt;h3&gt;
  
  
  6.7 How To Build It On Bubbles
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Canonical for a PDF or other non HTML asset:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/downloads/whitepaper.pdf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/whitepapers/q3-2026&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="canonical"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PDF is the asset; the canonical URL is the HTML landing page about the whitepaper. This consolidates index signals onto the HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hreflang via HTTP header (for non HTML):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/downloads/manual.pdf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/downloads/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;hreflang="en-US",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://example.com/es/downloads/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;hreflang="es-MX",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://example.com/downloads/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;hreflang="x-default"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each PDF in a multi region cluster declares every other language version. The set must include &lt;code&gt;x-default&lt;/code&gt; and must be reciprocal (every variant lists every other variant including itself).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preload critical assets:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Preload the hero image, critical CSS, and primary font&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/critical.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="style",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/fonts/manrope.woff2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="font"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;crossorigin,&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/images/hero.webp&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="image"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;fetchpriority="high"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=0,&lt;/span&gt; &lt;span class="s"&gt;must-revalidate"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These preloads start fetching as soon as the response headers arrive at the browser, before HTML parsing begins. For a hero image LCP candidate, this typically improves LCP by 100 to 300 ms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preconnect to external origins (rare on Bubbles since we self host everything):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://www.googletagmanager.com&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preconnect",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://www.google-analytics.com&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preconnect"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful when third party origins are unavoidable (analytics, tag manager). Establishes the TCP/TLS connection before the page needs the resource.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RSS feed declaration via HTTP:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/rss&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;type="application/rss+xml"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;title="Site&lt;/span&gt; &lt;span class="s"&gt;Feed"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feed readers and browsers that support RSS auto discovery will find the feed through this header.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Snippet pattern for the add_header inheritance trap:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/nginx/snippets/preloads.conf&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/critical.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;as="style",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/fonts/manrope.woff2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;as="font"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;crossorigin'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# In every relevant location&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/preloads&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=0,&lt;/span&gt; &lt;span class="s"&gt;must-revalidate"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6.8 HTTP 103 Early Hints (the killer feature)
&lt;/h3&gt;

&lt;p&gt;Nginx 1.25+ supports HTTP 103 Early Hints, which lets the server send &lt;code&gt;Link&lt;/code&gt; preload headers before the final response is ready. The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser requests &lt;code&gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Server returns &lt;code&gt;103 Early Hints&lt;/code&gt; immediately with &lt;code&gt;Link&lt;/code&gt; headers.&lt;/li&gt;
&lt;li&gt;Browser sees the preload directives and begins fetching critical resources.&lt;/li&gt;
&lt;li&gt;Server takes 200 to 800 ms to compute the page (database queries, template rendering).&lt;/li&gt;
&lt;li&gt;Server returns &lt;code&gt;200 OK&lt;/code&gt; with the page body.&lt;/li&gt;
&lt;li&gt;By the time the page parses, critical resources are already in cache.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;early_hints&lt;/span&gt; &lt;span class="mi"&gt;103&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/critical.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="style"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:9090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;early_hints 103&lt;/code&gt; directive (nginx 1.25+) tells nginx to emit a 103 status with the &lt;code&gt;Link&lt;/code&gt; headers before the final response. Supported in Chrome 103+, Edge 103+, Safari 17+, and Firefox 120+. Older browsers ignore the 103 and process the final response normally.&lt;/p&gt;

&lt;p&gt;This is the single highest impact optimization for dynamic sites with slow first byte times. On a FastAPI sidecar that takes 400 ms to render, Early Hints typically reduces LCP by 200 to 400 ms with no application change.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.9 How To Verify
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Confirm Link header is present&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt;

&lt;span class="c"&gt;# 2. Pretty print multiple Link entries&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'^link:'&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/^/    /'&lt;/span&gt;

&lt;span class="c"&gt;# 3. Verify canonical for a PDF&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/downloads/report.pdf | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt;

&lt;span class="c"&gt;# 4. Check hreflang variants&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'hreflang="[^"]*"'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;

&lt;span class="c"&gt;# 5. Test preload is being emitted&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'rel="preload"'&lt;/span&gt;

&lt;span class="c"&gt;# 6. Verify Early Hints (requires nginx 1.25+ and a client that supports 103)&lt;/span&gt;
curl &lt;span class="nt"&gt;-sv&lt;/span&gt; &lt;span class="nt"&gt;--http2&lt;/span&gt; https://example.com/ 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"HTTP/2 103"&lt;/span&gt;

&lt;span class="c"&gt;# 7. Check that Googlebot sees the same Link header&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt;

&lt;span class="c"&gt;# 8. Verify the URLs in Link headers actually resolve&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;url &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;[^&amp;gt;]+&amp;gt;'&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;&amp;gt;'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== &lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt; ==="&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6.10 Troubleshooting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Preload appears in header but browser fetches the resource twice.&lt;/strong&gt;&lt;br&gt;
Causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;as&lt;/code&gt; value mismatch. The browser fetched with &lt;code&gt;as=script&lt;/code&gt; priority but the page actually loaded the resource as a stylesheet. Fix the &lt;code&gt;as&lt;/code&gt; to match.&lt;/li&gt;
&lt;li&gt;Cross origin without &lt;code&gt;crossorigin&lt;/code&gt; parameter. Fonts especially fail this way. Add &lt;code&gt;crossorigin&lt;/code&gt; to the Link header.&lt;/li&gt;
&lt;li&gt;Different URL between preload and actual use. The preload was for &lt;code&gt;/css/main.css&lt;/code&gt; but the HTML loaded &lt;code&gt;/css/main.v2.css&lt;/code&gt;. The URLs must match byte for byte.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Canonical via HTTP Link header is ignored by Google.&lt;/strong&gt;&lt;br&gt;
Causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Conflicts with an HTML &lt;code&gt;&amp;lt;link rel=canonical&amp;gt;&lt;/code&gt; declaring a different URL. Decide which is authoritative and remove the other.&lt;/li&gt;
&lt;li&gt;The Link header URL is relative when it should be absolute. Always use absolute URLs in &lt;code&gt;rel=canonical&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The canonical target returns 404 or 5xx. Google ignores broken canonicals.&lt;/li&gt;
&lt;li&gt;The canonical target itself canonicalizes elsewhere (a chain). Resolve to the final canonical.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Early Hints not being sent.&lt;/strong&gt;&lt;br&gt;
Causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Nginx version under 1.25. Check &lt;code&gt;nginx -v&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;early_hints 103;&lt;/code&gt; directive missing from the location.&lt;/li&gt;
&lt;li&gt;The client does not support 103 (most older HTTP clients do not). Test with &lt;code&gt;curl -sv --http2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The upstream returned the final response too quickly for nginx to emit the 103 first. Acceptable; the browser still uses the final response's Link headers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Hreflang cluster has missing reciprocity warnings in Search Console.&lt;/strong&gt;&lt;br&gt;
Every variant in the cluster must list every other variant including itself. Audit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;variant &lt;span class="k"&gt;in &lt;/span&gt;en-US es-MX en-GB&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/&lt;/span&gt;&lt;span class="nv"&gt;$variant&lt;/span&gt;&lt;span class="s2"&gt;/page"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== &lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt; ==="&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'hreflang="[^"]*"'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each should list the same set including &lt;code&gt;x-default&lt;/code&gt;. Add any missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Browser console warns "The resource was preloaded but not used within a few seconds".&lt;/strong&gt;&lt;br&gt;
The preload is wasted. Either the resource is not actually critical and should be removed from preload, or the page is not loading it correctly. Audit which resources truly contribute to LCP and preload only those.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.11 How To Fix Common Breakage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Case: PDFs have no canonical, are competing with HTML in search.&lt;/strong&gt;&lt;br&gt;
Add canonical headers to the PDF location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/downloads/(.*)\.pdf$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Compute the canonical HTML URL based on the PDF name&lt;/span&gt;
    &lt;span class="c1"&gt;# Adjust the pattern to match your site structure&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/whitepapers/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="canonical"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PDF declares the HTML page as canonical and is itself noindex. Index signals consolidate onto the HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: LCP is slow due to hero image discovery latency.&lt;/strong&gt;&lt;br&gt;
Preload the hero image with high fetchpriority:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/images/hero-2026.webp&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="image"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;fetchpriority="high"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the hero image varies by viewport (responsive images), preload only the largest variant and let the browser pick the right one via srcset. Or, more advanced, use the &lt;code&gt;media&lt;/code&gt; attribute on the preload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;/hero-large.webp&amp;gt;; rel=preload; as=image; media="(min-width: 1024px)", &amp;lt;/hero-small.webp&amp;gt;; rel=preload; as=image; media="(max-width: 1023px)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Case: Web font loads late and causes FOIT (flash of invisible text).&lt;/strong&gt;&lt;br&gt;
Preload the font with crossorigin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/fonts/manrope-400.woff2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="font"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;crossorigin'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The font fetch starts immediately. Combined with &lt;code&gt;font-display: swap&lt;/code&gt; in CSS, FOUT and FOIT are largely eliminated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: Dynamic page from FastAPI sidecar is slow to TTFB.&lt;/strong&gt;&lt;br&gt;
Enable Early Hints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/dashboard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;early_hints&lt;/span&gt; &lt;span class="mi"&gt;103&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/dashboard.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="style",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/js/dashboard.js&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="script"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:9090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modern Chrome and Edge users see LCP improve by 200 to 400 ms with no application code change.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. LOCATION (REDIRECT TARGET WITH STATUS CODE SEMANTICS)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  7.1 What It Does
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Location&lt;/code&gt; declares the URL a client should fetch instead of the current one. Required for any 3xx redirect response. Defined in RFC 9110 Section 10.2.2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/2 301
Location: https://example.com/new-url
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The status code that accompanies &lt;code&gt;Location&lt;/code&gt; carries the semantic meaning: is this redirect permanent or temporary, must the HTTP method be preserved, and how should clients cache the redirect.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.2 The Five Redirect Status Codes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Permanent?&lt;/th&gt;
&lt;th&gt;HTTP method preserved on redirect?&lt;/th&gt;
&lt;th&gt;Cacheable by browser?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;301&lt;/td&gt;
&lt;td&gt;Moved Permanently&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Often changed to GET historically; modern clients preserve&lt;/td&gt;
&lt;td&gt;Yes, indefinitely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;302&lt;/td&gt;
&lt;td&gt;Found&lt;/td&gt;
&lt;td&gt;No (temporary)&lt;/td&gt;
&lt;td&gt;Often changed to GET; modern clients vary&lt;/td&gt;
&lt;td&gt;Sometimes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;303&lt;/td&gt;
&lt;td&gt;See Other&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Always changed to GET&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;307&lt;/td&gt;
&lt;td&gt;Temporary Redirect&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Strictly preserved&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;308&lt;/td&gt;
&lt;td&gt;Permanent Redirect&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Strictly preserved&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The rules in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;301&lt;/strong&gt;: use for permanent URL changes where the original URL is being abandoned. Most common redirect code. Browsers cache aggressively, which means changing the destination later requires cache busting. Search engines consolidate signals into the target URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;302&lt;/strong&gt;: use for temporary URL changes that may revert. The original URL remains indexed. Common for A/B tests, geographic redirects, maintenance pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;303&lt;/strong&gt;: use after a form POST to redirect to a confirmation page (Post/Redirect/Get pattern). Forces GET on the redirect to prevent accidental form resubmission on browser refresh.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;307&lt;/strong&gt;: same semantics as 302 (temporary) but strictly preserves the HTTP method. A POST stays a POST. Use for temporary redirects of API endpoints where method preservation matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;308&lt;/strong&gt;: same semantics as 301 (permanent) but strictly preserves the HTTP method. Use for permanent redirects of API endpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Google's stance&lt;/strong&gt; (John Mueller, 2016 and reaffirmed multiple times): all redirect codes are treated equivalently for SEO ranking purposes. The full PageRank passes through any of them. Choose based on technical semantics, not perceived SEO benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical Bubbles defaults:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP to HTTPS migration: 301.&lt;/li&gt;
&lt;li&gt;www to non www (or vice versa): 301.&lt;/li&gt;
&lt;li&gt;Old URL to new URL after a site restructure: 301.&lt;/li&gt;
&lt;li&gt;Marketing campaign redirect: 302 (in case the campaign URL needs to change).&lt;/li&gt;
&lt;li&gt;Geographic or device redirect: 302.&lt;/li&gt;
&lt;li&gt;API endpoint version migration: 308 (preserves POST method).&lt;/li&gt;
&lt;li&gt;Login redirect after form submit: 303.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7.3 How To Build It On Bubbles
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Simple permanent redirect:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/old-page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com/new-page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Wildcard redirect for an entire path:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/old-section/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com/new-section/&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caution: &lt;code&gt;$request_uri&lt;/code&gt; includes the leading &lt;code&gt;/old-section/&lt;/code&gt;. For a clean rewrite, use a different variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/old-section/(.*)$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com/new-section/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;HTTP to HTTPS redirect (every Bubbles site has this):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;www to non www canonicalization:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# ... actual site config ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Subdomain to canonical domain (for the 14+ paying client subdomains on thatwebhostingguy.com that 301 to client custom domains):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;arcounselingandwellness.thatwebhostingguy.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://arcounselingandwellness.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conditional redirect based on URL pattern:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Redirect old blog URLs to new structure&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/blog/(\d&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;4&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)/(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;d&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;2&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)/(.+)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com/articles/&lt;/span&gt;&lt;span class="nv"&gt;$1-$2&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Redirect old product URLs based on a map&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/products/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="s"&gt;@product_redirects&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;@product_redirects&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_redirect&lt;/span&gt; &lt;span class="s"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"")&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="nv"&gt;$product_redirect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Defined at http level&lt;/span&gt;
&lt;span class="kn"&gt;map&lt;/span&gt; &lt;span class="nv"&gt;$request_uri&lt;/span&gt; &lt;span class="nv"&gt;$product_redirect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;default&lt;/span&gt;                       &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;/products/old-widget&lt;/span&gt;          &lt;span class="n"&gt;/products/new-widget&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;/products/old-gadget&lt;/span&gt;          &lt;span class="n"&gt;/products/new-gadget&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;/products/discontinued&lt;/span&gt;        &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Temporary redirect for maintenance page:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$maintenance&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# Toggle this to 1 during maintenance&lt;/span&gt;
    &lt;span class="c1"&gt;# if ($maintenance) {&lt;/span&gt;
    &lt;span class="c1"&gt;#     return 302 /maintenance.html;&lt;/span&gt;
    &lt;span class="c1"&gt;# }&lt;/span&gt;

    &lt;span class="c1"&gt;# ... rest of config ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;API endpoint version migration (308 to preserve POST):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/v1/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;308&lt;/span&gt; &lt;span class="s"&gt;https://example.com/api/v2/&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A POST request to &lt;code&gt;/api/v1/something&lt;/code&gt; becomes a POST to &lt;code&gt;/api/v2/something&lt;/code&gt;. The body is preserved.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.4 The Open Redirect Vulnerability
&lt;/h3&gt;

&lt;p&gt;A redirect endpoint that takes the target URL from user input without validation is a phishing vector. Attackers craft URLs like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com/redirect?url=https://phishing-site.com/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The link appears to come from your domain, lending credibility. The victim clicks, lands on the phishing site, enters credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defenses:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Never accept full URLs from user input.&lt;/strong&gt; Only accept path components and prepend a fixed origin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Wrong (vulnerable)&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="nv"&gt;$arg_url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Right&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arg_to&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/[a-z0-9/_-]+$)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$arg_to&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Validate against an allow list of full URLs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;map&lt;/span&gt; &lt;span class="nv"&gt;$arg_url&lt;/span&gt; &lt;span class="nv"&gt;$is_allowed_redirect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;default&lt;/span&gt;                          &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;https://example.com/promo&lt;/span&gt;        &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;https://example.com/login&lt;/span&gt;        &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;https://example.com/help&lt;/span&gt;         &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$is_allowed_redirect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"")&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="nv"&gt;$arg_url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Require an HMAC signature on the redirect parameter&lt;/strong&gt; so attackers cannot forge new targets. Implement at the upstream FastAPI sidecar level for any redirect endpoint that must accept dynamic targets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Never combine user input with a redirect status code without one of the above defenses.&lt;/strong&gt; Treat redirect endpoints with the same care as authentication endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.5 Redirect Chains And Crawl Budget
&lt;/h3&gt;

&lt;p&gt;A redirect chain is a sequence of redirects: &lt;code&gt;/a&lt;/code&gt; → &lt;code&gt;/b&lt;/code&gt; → &lt;code&gt;/c&lt;/code&gt; → &lt;code&gt;/d&lt;/code&gt;. Each hop costs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One crawler request (against finite crawl budget).&lt;/li&gt;
&lt;li&gt;One TLS handshake plus one TCP round trip for users (latency adds up).&lt;/li&gt;
&lt;li&gt;Potentially lost PageRank, although Google denies this in modern documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google's official guidance is to keep chains under 5 hops. Practical recommendation: always 1 hop. Audit periodically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Trace any chain&lt;/span&gt;
curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"^location:"&lt;/span&gt;

&lt;span class="c"&gt;# Count hops&lt;/span&gt;
curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"^HTTP/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;1&lt;/code&gt; indicates direct response (no redirect or single redirect). A &lt;code&gt;2&lt;/code&gt; or higher indicates a chain.&lt;/p&gt;

&lt;p&gt;When a chain is detected:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify the final destination.&lt;/li&gt;
&lt;li&gt;Update the original redirect to point directly to the final destination.&lt;/li&gt;
&lt;li&gt;Leave the intermediate redirects in place for a few months in case other consumers have cached the intermediate URLs.&lt;/li&gt;
&lt;li&gt;Remove the intermediate redirects once they show zero traffic in logs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  7.6 How To Verify
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Confirm redirect status and target&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/old-page | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# 2. Follow the chain&lt;/span&gt;
curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-page | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# 3. Verify final destination resolves&lt;/span&gt;
curl &lt;span class="nt"&gt;-sIL&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{url_effective} %{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://example.com/old-page

&lt;span class="c"&gt;# 4. Verify the redirect preserves the path (for wildcard redirects)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;path &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="s2"&gt;"/sub/page"&lt;/span&gt; &lt;span class="s2"&gt;"/file.pdf?query=1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/old-section&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== &lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt; ==="&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; location
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# 5. Test that POST is preserved (for 307 / 308)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/api/v1/endpoint | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# 6. Audit: find chains&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;url &lt;span class="k"&gt;in &lt;/span&gt;https://example.com/old-1 https://example.com/old-2 https://example.com/old-3&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;HOPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"^HTTP/"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;DEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sIL&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{url_effective}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$DEST&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="nv"&gt;$HOPS&lt;/span&gt;&lt;span class="s2"&gt; hops)"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# 7. Verify Googlebot follows correctly&lt;/span&gt;
curl &lt;span class="nt"&gt;-sIL&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/old-page | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7.7 Troubleshooting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Redirect loop (browser shows "ERR_TOO_MANY_REDIRECTS").&lt;/strong&gt;&lt;br&gt;
Causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Two redirects pointing at each other (&lt;code&gt;/a&lt;/code&gt; → &lt;code&gt;/b&lt;/code&gt; → &lt;code&gt;/a&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Server block redirects HTTP to HTTPS, but the HTTPS server block also has an HTTP to HTTPS redirect, causing infinite loops.&lt;/li&gt;
&lt;li&gt;A wildcard redirect catches its own target (&lt;code&gt;location /new/ { return 301 /new/page; }&lt;/code&gt; redirects &lt;code&gt;/new/page&lt;/code&gt; to &lt;code&gt;/new/page&lt;/code&gt;).
Fix: trace the chain with curl, identify the loop, rewrite one of the redirects to terminate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Redirect target has trailing slash but original did not (or vice versa) and Google flags duplicates.&lt;/strong&gt;&lt;br&gt;
Cause: inconsistent trailing slash policy.&lt;br&gt;
Fix: pick one policy (typically without trailing slash for non directory URLs) and enforce site wide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Force no trailing slash on file like URLs&lt;/span&gt;
&lt;span class="k"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/(.*)/&lt;/span&gt;$ &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the opposite. Document which is the canonical form and stick to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptom: 301 cached forever in browsers, even after fixing the redirect target.&lt;/strong&gt;&lt;br&gt;
Cause: browsers cache 301 indefinitely per the HTTP spec. The cached redirect bypasses the server entirely.&lt;br&gt;
Fix options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change the original URL to a new path that has not been cached as a redirect.&lt;/li&gt;
&lt;li&gt;Wait for the browser cache to expire (could be months).&lt;/li&gt;
&lt;li&gt;Use a 302 in the future for redirects that might change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: POST request becomes GET after redirect.&lt;/strong&gt;&lt;br&gt;
Cause: the redirect status code is 301, 302, or 303, all of which historically changed the method to GET.&lt;br&gt;
Fix: use 307 (temporary) or 308 (permanent) to strictly preserve the method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Redirect works in browser but Googlebot still indexes the original URL.&lt;/strong&gt;&lt;br&gt;
Causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The redirect status is 302 or 307, which signals "do not consolidate". Change to 301 or 308 for permanent moves.&lt;/li&gt;
&lt;li&gt;There is a chain. Google may not follow long chains. Collapse to one hop.&lt;/li&gt;
&lt;li&gt;The original URL has internal links pointing to it. Update internal links to point directly to the new URL.&lt;/li&gt;
&lt;li&gt;Time. Consolidation takes weeks. Be patient.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Symptom: Open redirect security alert.&lt;/strong&gt;&lt;br&gt;
The redirect endpoint accepts unvalidated user input.&lt;br&gt;
Fix: implement an allow list, signature validation, or both. See Section 7.4.&lt;/p&gt;
&lt;h3&gt;
  
  
  7.8 How To Fix Common Breakage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Case: Old domain serving 301 to new domain, but new domain still points back to old in some links.&lt;/strong&gt;&lt;br&gt;
Audit and fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find any link to the old domain in current site&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"old-domain.com"&lt;/span&gt; /var/www/sites/new-domain.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace every occurrence with the new domain. Then verify no infinite loop exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: Redirect chain longer than 1 hop discovered in Search Console.&lt;/strong&gt;&lt;br&gt;
List the chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the originating server block to redirect directly to the final destination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/old-url&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Was: return 301 /intermediate;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com/final-destination&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nginx -t &amp;amp;&amp;amp; systemctl reload nginx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: HTTPS redirect causing certificate warning.&lt;/strong&gt;&lt;br&gt;
The redirect target is &lt;code&gt;https://example.com&lt;/code&gt; but the SSL certificate covers only &lt;code&gt;https://www.example.com&lt;/code&gt;. Either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a certificate covering both names (typical with Let's Encrypt: include both in &lt;code&gt;-d&lt;/code&gt; flags).&lt;/li&gt;
&lt;li&gt;Redirect to the name actually covered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Case: Need to redirect a thousand old URLs to specific new URLs.&lt;/strong&gt;&lt;br&gt;
Use a map for performance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In http context&lt;/span&gt;
&lt;span class="k"&gt;map&lt;/span&gt; &lt;span class="nv"&gt;$request_uri&lt;/span&gt; &lt;span class="nv"&gt;$legacy_redirect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;default&lt;/span&gt;                                    &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;/old/page-1.html&lt;/span&gt;                           &lt;span class="n"&gt;/new/page-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;/old/page-2.html&lt;/span&gt;                           &lt;span class="n"&gt;/new/page-2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;/old/page-3.html&lt;/span&gt;                           &lt;span class="n"&gt;/new/page-3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# ... thousands more ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# In server context&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$legacy_redirect&lt;/span&gt; &lt;span class="s"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"")&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="nv"&gt;$legacy_redirect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maps in nginx are O(1) lookups; even thousands of entries add negligible overhead.&lt;/p&gt;

&lt;p&gt;For maps with thousands of entries, externalize:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;map&lt;/span&gt; &lt;span class="nv"&gt;$request_uri&lt;/span&gt; &lt;span class="nv"&gt;$legacy_redirect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/maps/legacy-redirects.map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;default&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And maintain &lt;code&gt;legacy-redirects.map&lt;/code&gt; as a simple text file with one mapping per line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case: Need to migrate from www to non www, preserving all paths.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure your SSL certificate covers &lt;code&gt;example.com&lt;/code&gt; (the redirect target). Verify with curl.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. HOW THESE HEADERS INTERACT
&lt;/h2&gt;

&lt;p&gt;The three headers do not act independently. Several combinations matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.1 X-Robots-Tag On Redirects
&lt;/h3&gt;

&lt;p&gt;A 301 or 302 response can carry an &lt;code&gt;X-Robots-Tag&lt;/code&gt; header, but the directive is largely ignored by Google. The crawler follows the redirect and applies indexing rules to the target URL, not the redirect itself. The exception is &lt;code&gt;nofollow&lt;/code&gt;, which can prevent the crawler from following the redirect at all, but this is rare and usually unintended.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Almost always unnecessary&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/old-url&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;/new-url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt; on a 301 has no effect: the old URL was already being deindexed by the 301 itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.2 Canonical In HTTP vs HTML
&lt;/h3&gt;

&lt;p&gt;When both &lt;code&gt;Link: &amp;lt;...&amp;gt;; rel=canonical&lt;/code&gt; HTTP header and &lt;code&gt;&amp;lt;link rel=canonical&amp;gt;&lt;/code&gt; HTML tag are present, Google treats them as duplicate signals. If they agree, fine. If they disagree, Google picks one based on its own canonicalization logic, which may not match either. &lt;strong&gt;Pick one and stick to it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For HTML pages: use the HTML &lt;code&gt;&amp;lt;link rel=canonical&amp;gt;&lt;/code&gt; tag because it is easier to manage with templates and is what most tools expect.&lt;/p&gt;

&lt;p&gt;For non HTML (PDF, image, JSON): use the HTTP &lt;code&gt;Link&lt;/code&gt; header because there is no HTML to put a tag in.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.3 Redirect Plus Canonical Tag On The Target
&lt;/h3&gt;

&lt;p&gt;The redirect target should have a self referencing canonical tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- On the new URL: https://example.com/new-page --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://example.com/new-page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is correct and expected. It reinforces that this is the canonical version, not a duplicate of some other page.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.4 hreflang Cluster Cross References
&lt;/h3&gt;

&lt;p&gt;Hreflang annotations declared via HTTP &lt;code&gt;Link&lt;/code&gt; header or HTML &lt;code&gt;&amp;lt;link rel=alternate hreflang&amp;gt;&lt;/code&gt; must form a reciprocal cluster. Every variant lists every other variant including itself. Missing any reciprocal reference triggers a Search Console warning and may cause hreflang to be ignored entirely.&lt;/p&gt;

&lt;p&gt;For a PDF that exists in two languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# On /en/manual.pdf&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/en/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;hreflang="en-US",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://example.com/es/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;hreflang="es-MX",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://example.com/en/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;hreflang="x-default"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# On /es/manual.pdf&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/en/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;hreflang="en-US",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://example.com/es/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;hreflang="es-MX",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;https://example.com/en/manual.pdf&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;rel="alternate"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;hreflang="x-default"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both PDFs declare the same cluster. The cluster includes both files and an &lt;code&gt;x-default&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.5 Preload And Cache-Control
&lt;/h3&gt;

&lt;p&gt;Preloaded resources should still have correct &lt;code&gt;Cache-Control&lt;/code&gt; headers. If the preloaded asset has &lt;code&gt;Cache-Control: no-store&lt;/code&gt;, the browser fetches it via the preload, but cannot store it for use by the actual page reference. Result: double fetch.&lt;/p&gt;

&lt;p&gt;Ensure preloaded resources are cacheable. Combine with framework-http-caching-headers.md guidance: fingerprinted assets should be &lt;code&gt;Cache-Control: public, max-age=31536000, immutable&lt;/code&gt; and are perfect preload candidates.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.6 Location Plus Vary
&lt;/h3&gt;

&lt;p&gt;A redirect response should typically not have &lt;code&gt;Vary&lt;/code&gt; headers. The redirect itself does not vary by request headers. However, if the redirect target differs based on &lt;code&gt;Accept-Language&lt;/code&gt; (geographic or language based redirect), then &lt;code&gt;Vary: Accept-Language&lt;/code&gt; is required to prevent caches from serving the wrong target to a different audience.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Redirect based on Accept-Language&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$http_accept_language&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;"^es")&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Vary&lt;/span&gt; &lt;span class="s"&gt;"Accept-Language"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="n"&gt;/es/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Vary&lt;/span&gt; &lt;span class="s"&gt;"Accept-Language"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="n"&gt;/en/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: language based redirects are a poor pattern for SEO. They confuse crawlers and prevent users from sharing links between languages. Prefer letting the user select their language explicitly and remembering the choice via cookie or path.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. ASSET CLASS AND USE CASE RECIPES
&lt;/h2&gt;

&lt;p&gt;Each block is paste ready. Copy the ones relevant to your build.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.1 Production HTML page (full SEO header set)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# X-Robots-Tag: allow indexing, set snippet limits&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"max-snippet:200,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:large,&lt;/span&gt; &lt;span class="s"&gt;max-video-preview:-1"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Link: preload critical resources&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/critical.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="style",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/fonts/manrope.woff2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="font"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;crossorigin'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Cache directives from framework-http-caching-headers.md&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=0,&lt;/span&gt; &lt;span class="s"&gt;must-revalidate"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.2 PDF (block from index, canonical to HTML)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/whitepapers/(.*)\.pdf$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/whitepapers/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="canonical"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=86400"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Disposition&lt;/span&gt; &lt;span class="s"&gt;"attachment"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.3 Image asset (allow indexing for image search)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(jpg|jpeg|png|webp|avif)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Default: allow image indexing&lt;/span&gt;
    &lt;span class="c1"&gt;# If you want to block: add_header X-Robots-Tag "noindex" always;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=2592000"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.4 Image asset (block from image search but page itself indexable)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(jpg|jpeg|png|webp|avif)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=2592000"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.5 Staging or development subdomain (full block)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;staging.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Universal block&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;nofollow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Plus robots.txt for belt and suspenders&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/robots.txt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="s"&gt;"User-agent:&lt;/span&gt; &lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;nDisallow:&lt;/span&gt; &lt;span class="n"&gt;/\n"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt; &lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Plus HTTP basic auth as a third layer&lt;/span&gt;
    &lt;span class="kn"&gt;auth_basic&lt;/span&gt; &lt;span class="s"&gt;"Staging"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;auth_basic_user_file&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/.staging-htpasswd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.6 API endpoint (do not index, do not follow)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;nofollow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:9090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.7 Search result page (do not index, do follow)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/search&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;follow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# The follow allows crawlers to discover linked content&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internal search result pages are duplicate content for each query and should not be indexed. Allow follow so crawlers can discover the linked actual content pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.8 Paginated section (allow indexing of all pages, no rel prev/next)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/blog/page/([0-9]+)$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Google ignored prev/next as of 2019; do not bother with Link rel=prev/next&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"max-snippet:160,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:standard"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.9 Time limited campaign page
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/promotions/black-friday-2026&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"unavailable_after:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="s"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;2026&lt;/span&gt; &lt;span class="nf"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="s"&gt;GMT"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.10 Permanent www to non www redirect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;http2&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.11 HTTP to HTTPS redirect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.12 Old blog URL structure to new
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Old: /2024/05/post-title&lt;/span&gt;
&lt;span class="c1"&gt;# New: /blog/post-title&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/(\d&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;4&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)/(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;d&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;2&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)/(.+)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;/blog/&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.13 Subdomain to client custom domain (Bubbles wildcard pattern)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;handledtax.thatwebhostingguy.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/thatwebhostingguy.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/thatwebhostingguy.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://handledtax.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.14 API version migration (preserve POST method)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/v1/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;308&lt;/span&gt; &lt;span class="n"&gt;/api/v2/&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.15 Maintenance mode toggle
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# At server level&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$maintenance&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(-f&lt;/span&gt; &lt;span class="n"&gt;/var/www/sites/example.com/.maintenance&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$maintenance&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$maintenance&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;302&lt;/span&gt; &lt;span class="n"&gt;/maintenance.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/maintenance.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Allow access to this even in maintenance mode&lt;/span&gt;
    &lt;span class="kn"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enable maintenance: &lt;code&gt;touch /var/www/sites/example.com/.maintenance&lt;/code&gt;. To disable: &lt;code&gt;rm /var/www/sites/example.com/.maintenance&lt;/code&gt;. No nginx reload required.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. BUBBLES NGINX REFERENCE BLOCK (PASTE READY)
&lt;/h2&gt;

&lt;p&gt;The complete SEO header stanza, layered with caching (framework-http-caching-headers.md) and content (framework-http-content-headers.md).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/nginx/sites-available/example.com&lt;/span&gt;

&lt;span class="c1"&gt;# HTTP to HTTPS redirect&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# www to non www&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;http2&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Main canonical server&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;http2&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;quic&lt;/span&gt; &lt;span class="s"&gt;reuseport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;quic&lt;/span&gt; &lt;span class="s"&gt;reuseport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/sites/example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# HTTP/3 advertisement&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Alt-Svc&lt;/span&gt; &lt;span class="s"&gt;'h3=":443"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;ma=86400'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== HTML PAGES =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# Baseline indexing directives&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"max-snippet:200,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:large,&lt;/span&gt; &lt;span class="s"&gt;max-video-preview:-1"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# Preload critical resources&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/critical.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="style",&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/fonts/manrope.woff2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="font"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;crossorigin,&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;/images/hero.webp&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="image"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;fetchpriority="high"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# Caching from framework-http-caching-headers.md&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=0,&lt;/span&gt; &lt;span class="s"&gt;must-revalidate"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# Language from framework-http-content-headers.md&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Language&lt;/span&gt; &lt;span class="s"&gt;"en-US"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== PDFs (noindex, canonical to HTML landing) =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/whitepapers/(.*)\.pdf$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;https://example.com/whitepapers/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="canonical"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Disposition&lt;/span&gt; &lt;span class="s"&gt;"attachment"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=86400"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== IMAGES (allow image search indexing) =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(jpg|jpeg|png|webp|avif|svg|gif)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=2592000"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# No X-Robots-Tag: default behavior allows image indexing&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== FONTS, CSS, JS (no indexing needed; cache forever) =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(woff2|woff|ttf|otf|css|js|mjs)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=31536000,&lt;/span&gt; &lt;span class="s"&gt;immutable"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== INTERNAL SEARCH (noindex but follow) =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/search&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;follow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== API (sidecar, noindex) =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"noindex,&lt;/span&gt; &lt;span class="s"&gt;nofollow"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# Early Hints for dynamic responses&lt;/span&gt;
        &lt;span class="kn"&gt;early_hints&lt;/span&gt; &lt;span class="mi"&gt;103&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Link&lt;/span&gt; &lt;span class="s"&gt;'&amp;lt;/css/dashboard.css&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;rel="preload"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;as="style"'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:9090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== ROBOTS.TXT, SITEMAPS, AI/LLM FILES =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/robots.txt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;1h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=3600"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/sitemap.xml&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="mi"&gt;10m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=600"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="s"&gt;(llms&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.txt|ai&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.txt|humans&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.txt|&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.well-known/security&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.txt)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;1d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=86400"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== LEGACY URL MAP REDIRECTS =====&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$legacy_redirect&lt;/span&gt; &lt;span class="s"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"")&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="nv"&gt;$legacy_redirect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# ===== DEFAULT =====&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="nc"&gt;snippets/common-security-headers&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;"max-snippet:200,&lt;/span&gt; &lt;span class="s"&gt;max-image-preview:large,&lt;/span&gt; &lt;span class="s"&gt;max-video-preview:-1"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Language&lt;/span&gt; &lt;span class="s"&gt;"en-US"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"public,&lt;/span&gt; &lt;span class="s"&gt;max-age=0,&lt;/span&gt; &lt;span class="s"&gt;must-revalidate"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Legacy URL map (defined at http level in nginx.conf or included)&lt;/span&gt;
&lt;span class="c1"&gt;# map $request_uri $legacy_redirect {&lt;/span&gt;
&lt;span class="c1"&gt;#     default                       "";&lt;/span&gt;
&lt;span class="c1"&gt;#     /old/page-1.html              /new/page-1;&lt;/span&gt;
&lt;span class="c1"&gt;#     /old/page-2.html              /new/page-2;&lt;/span&gt;
&lt;span class="c1"&gt;# }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shared security header snippet at &lt;code&gt;/etc/nginx/snippets/common-security-headers.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Frame-Options&lt;/span&gt; &lt;span class="s"&gt;"SAMEORIGIN"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt; &lt;span class="s"&gt;"nosniff"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Referrer-Policy&lt;/span&gt; &lt;span class="s"&gt;"strict-origin-when-cross-origin"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class="s"&gt;"max-age=31536000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;includeSubDomains&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;preload"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Permissions-Policy&lt;/span&gt; &lt;span class="s"&gt;"camera=(),&lt;/span&gt; &lt;span class="s"&gt;microphone=(),&lt;/span&gt; &lt;span class="s"&gt;geolocation=(),&lt;/span&gt; &lt;span class="s"&gt;payment=()"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deploying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. AUDIT CHECKLIST
&lt;/h2&gt;

&lt;p&gt;Run through these 50 items for any production site.&lt;/p&gt;

&lt;h3&gt;
  
  
  X-Robots-Tag
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;[ ] Production HTML pages have &lt;code&gt;X-Robots-Tag: max-snippet:200, max-image-preview:large, max-video-preview:-1&lt;/code&gt; (or appropriate values, NOT &lt;code&gt;noindex&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[ ] Staging or development subdomains have &lt;code&gt;X-Robots-Tag: noindex, nofollow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] PDFs at customer facing URLs have &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt; (unless they should be indexed).&lt;/li&gt;
&lt;li&gt;[ ] CSV exports and other downloadable data files have &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] API endpoints have &lt;code&gt;X-Robots-Tag: noindex, nofollow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] Internal search result pages have &lt;code&gt;X-Robots-Tag: noindex, follow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] No production HTML page has &lt;code&gt;X-Robots-Tag: noindex&lt;/code&gt; accidentally.&lt;/li&gt;
&lt;li&gt;[ ] No directive uses deprecated tokens (&lt;code&gt;noodp&lt;/code&gt;, &lt;code&gt;noydir&lt;/code&gt;, &lt;code&gt;noyaca&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[ ] Bot prefixed directives (&lt;code&gt;googlebot:&lt;/code&gt;, &lt;code&gt;bingbot:&lt;/code&gt;) use valid bot tokens.&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;unavailable_after&lt;/code&gt; dates use RFC 850 / RFC 822 format.&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;nosnippet&lt;/code&gt; is used only when intentional (it blocks AI Overviews too).&lt;/li&gt;
&lt;li&gt;[ ] X-Robots-Tag from HTTP and &lt;code&gt;&amp;lt;meta name="robots"&amp;gt;&lt;/code&gt; from HTML do not conflict on the same page.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Link header
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;[ ] HTML pages preload critical CSS, fonts, and hero image via &lt;code&gt;Link&lt;/code&gt; HTTP header.&lt;/li&gt;
&lt;li&gt;[ ] Font preloads include &lt;code&gt;crossorigin&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;[ ] All preload URLs use absolute or relative paths that match the actual usage in HTML.&lt;/li&gt;
&lt;li&gt;[ ] Preload &lt;code&gt;as&lt;/code&gt; values are correct (&lt;code&gt;style&lt;/code&gt;, &lt;code&gt;script&lt;/code&gt;, &lt;code&gt;font&lt;/code&gt;, &lt;code&gt;image&lt;/code&gt;, etc).&lt;/li&gt;
&lt;li&gt;[ ] LCP candidate image has &lt;code&gt;fetchpriority="high"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] PDFs and other non HTML assets that need canonicalization use &lt;code&gt;Link: &amp;lt;...&amp;gt;; rel="canonical"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] Hreflang annotations form a reciprocal cluster (every variant lists every other variant).&lt;/li&gt;
&lt;li&gt;[ ] Hreflang cluster includes &lt;code&gt;x-default&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;[ ] No &lt;code&gt;rel=prev&lt;/code&gt; or &lt;code&gt;rel=next&lt;/code&gt; headers (Google ignored these in 2019).&lt;/li&gt;
&lt;li&gt;[ ] Early Hints (103) is enabled for dynamic responses where TTFB exceeds 200 ms.&lt;/li&gt;
&lt;li&gt;[ ] Nginx version is 1.25+ if Early Hints is used.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Location and redirects
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;[ ] HTTP requests to port 80 always redirect to HTTPS with 301.&lt;/li&gt;
&lt;li&gt;[ ] www to non www (or vice versa) is consistent and uses 301.&lt;/li&gt;
&lt;li&gt;[ ] No redirect chain exceeds 1 hop.&lt;/li&gt;
&lt;li&gt;[ ] All 301 redirect targets return 200 OK (not another redirect or error).&lt;/li&gt;
&lt;li&gt;[ ] Permanent redirects use 301 or 308 (not 302 or 307).&lt;/li&gt;
&lt;li&gt;[ ] Temporary redirects use 302 or 307.&lt;/li&gt;
&lt;li&gt;[ ] API version migration redirects use 308 to preserve POST method.&lt;/li&gt;
&lt;li&gt;[ ] No redirect endpoint accepts unvalidated URL parameters from user input (no open redirects).&lt;/li&gt;
&lt;li&gt;[ ] Trailing slash policy is consistent site wide.&lt;/li&gt;
&lt;li&gt;[ ] Internal links point directly to the canonical URL (no internal links to redirect sources).&lt;/li&gt;
&lt;li&gt;[ ] Redirect targets are absolute URLs or path absolute (no protocol relative or relative redirects).&lt;/li&gt;
&lt;li&gt;[ ] SSL certificate covers all redirect target hostnames.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cross cutting
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;[ ] &lt;code&gt;nginx -t&lt;/code&gt; passes without warnings.&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;nginx -T&lt;/code&gt; shows all expected SEO directives in effect for each server block.&lt;/li&gt;
&lt;li&gt;[ ] Search Console URL Inspection shows correct indexing status for sample URLs.&lt;/li&gt;
&lt;li&gt;[ ] No URL is in Google's index that should be noindex.&lt;/li&gt;
&lt;li&gt;[ ] No URL is noindex that should be in Google's index.&lt;/li&gt;
&lt;li&gt;[ ] No URL is blocked by robots.txt that needs to be noindex (the noindex would not be seen).&lt;/li&gt;
&lt;li&gt;[ ] PDF count in Search Console matches expected count (audits whether unwanted PDFs are indexed).&lt;/li&gt;
&lt;li&gt;[ ] Hreflang errors in Search Console are at zero.&lt;/li&gt;
&lt;li&gt;[ ] Coverage report in Search Console shows no unexpected "Excluded by noindex" entries.&lt;/li&gt;
&lt;li&gt;[ ] Redirect chain audit (run periodically) shows zero chains over 1 hop.&lt;/li&gt;
&lt;li&gt;[ ] All preload directives have corresponding usage in HTML (no orphan preloads wasting bandwidth).&lt;/li&gt;
&lt;li&gt;[ ] LCP image is preloaded with fetchpriority=high.&lt;/li&gt;
&lt;li&gt;[ ] Early Hints (if used) actually arrives before final response (verified via &lt;code&gt;curl --http2&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[ ] Open redirect scanner reports clean.&lt;/li&gt;
&lt;li&gt;[ ] Internal link audit shows no broken links to redirected URLs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A site that passes all 50 has indexing, resource hints, and forwarding correctly configured.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. COMMON PITFALLS
&lt;/h2&gt;

&lt;p&gt;Fifteen patterns to recognize and avoid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 1: noindex behind robots.txt block.&lt;/strong&gt;&lt;br&gt;
Symptom: page stays indexed forever.&lt;br&gt;
Why it breaks: robots.txt prevents fetching; crawler never sees the noindex directive.&lt;br&gt;
Fix: remove robots.txt block, let crawler fetch and process noindex, then optionally re add.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 2: Conflicting X-Robots-Tag and meta robots.&lt;/strong&gt;&lt;br&gt;
Symptom: page sometimes indexed, sometimes not; behavior inconsistent.&lt;br&gt;
Why it breaks: both signals are read; the most restrictive wins, but team members assume one or the other is authoritative.&lt;br&gt;
Fix: align both. Pick one as the source of truth (typically HTTP header for non HTML, HTML tag for HTML pages) and maintain consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 3: noindex on a redirected URL.&lt;/strong&gt;&lt;br&gt;
Symptom: the noindex header is wasted; the 301 itself handles deindexing.&lt;br&gt;
Why it breaks: a 301 response signals the URL has moved; crawlers process the redirect, not the directives on the old URL.&lt;br&gt;
Fix: remove noindex from redirect responses unless you have a specific reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 4: Canonical pointing to a redirected URL.&lt;/strong&gt;&lt;br&gt;
Symptom: index signals are diluted; Google follows the chain and selects its own canonical.&lt;br&gt;
Why it breaks: canonical should point to the final canonical URL, not to an intermediate that redirects.&lt;br&gt;
Fix: audit all canonicals. Each must resolve to a 200 OK page that self references as canonical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 5: Preload with wrong &lt;code&gt;as&lt;/code&gt; value.&lt;/strong&gt;&lt;br&gt;
Symptom: browser fetches the resource twice (preload, then real load).&lt;br&gt;
Why it breaks: the browser cannot match the preloaded resource to the actual request because the priority and headers differ.&lt;br&gt;
Fix: ensure &lt;code&gt;as&lt;/code&gt; matches the resource type exactly. Font preload requires &lt;code&gt;as=font&lt;/code&gt; AND &lt;code&gt;crossorigin&lt;/code&gt;. Image is &lt;code&gt;as=image&lt;/code&gt;. Script is &lt;code&gt;as=script&lt;/code&gt;. Style is &lt;code&gt;as=style&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 6: Preload of a resource the page does not use.&lt;/strong&gt;&lt;br&gt;
Symptom: bandwidth wasted; console warning "preloaded but not used".&lt;br&gt;
Why it breaks: a developer added a preload speculatively, then the corresponding HTML reference was removed or changed.&lt;br&gt;
Fix: audit preloads. Remove any not actually used within a few seconds of page load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 7: Hreflang cluster missing reciprocity.&lt;/strong&gt;&lt;br&gt;
Symptom: Search Console hreflang errors; Google falls back to default behavior.&lt;br&gt;
Why it breaks: hreflang requires every variant to list every other variant including itself.&lt;br&gt;
Fix: build hreflang generation programmatically so all variants always list the full set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 8: Redirect chain longer than 1 hop.&lt;/strong&gt;&lt;br&gt;
Symptom: crawl budget waste; PageRank consolidation slow.&lt;br&gt;
Why it breaks: nobody updated the source of a redirect when the destination itself was redirected.&lt;br&gt;
Fix: audit periodically with curl &lt;code&gt;-sLI&lt;/code&gt;. Collapse to direct redirects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 9: Open redirect endpoint.&lt;/strong&gt;&lt;br&gt;
Symptom: security alert; phishing campaigns abuse the redirector.&lt;br&gt;
Why it breaks: endpoint accepts arbitrary target URL from user input without validation.&lt;br&gt;
Fix: allow list, signature, or only accept path components. See Section 7.4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 10: Wrong redirect code for HTTP method preservation.&lt;/strong&gt;&lt;br&gt;
Symptom: POST becomes GET after redirect; API calls fail.&lt;br&gt;
Why it breaks: 301, 302, 303 historically change POST to GET.&lt;br&gt;
Fix: use 307 (temporary) or 308 (permanent) for redirects that must preserve POST.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 11: 301 cached forever, hard to undo.&lt;/strong&gt;&lt;br&gt;
Symptom: changed the redirect target but browsers still go to the old destination.&lt;br&gt;
Why it breaks: per HTTP spec, browsers may cache 301 indefinitely.&lt;br&gt;
Fix prevention: use 302 for redirects you might change in the future. Fix existing: change the source URL or wait for cache expiration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 12: Self redirecting URL.&lt;/strong&gt;&lt;br&gt;
Symptom: redirect loop; ERR_TOO_MANY_REDIRECTS.&lt;br&gt;
Why it breaks: a location block redirects, and the target also matches the same location pattern.&lt;br&gt;
Fix: tighten the regex match, or check the request URI before redirecting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 13: Redirect target on a different SSL certificate.&lt;/strong&gt;&lt;br&gt;
Symptom: browser shows certificate warning after redirect.&lt;br&gt;
Why it breaks: redirecting &lt;code&gt;www.example.com&lt;/code&gt; to &lt;code&gt;example.com&lt;/code&gt; requires the certificate to cover &lt;code&gt;example.com&lt;/code&gt;.&lt;br&gt;
Fix: ensure the cert covers all redirect targets. With Let's Encrypt, include all hostnames in the &lt;code&gt;-d&lt;/code&gt; flags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 14: Add_header inheritance trap on X-Robots-Tag.&lt;/strong&gt;&lt;br&gt;
Symptom: noindex applied to staging site disappears from specific file types.&lt;br&gt;
Why it breaks: a location block with &lt;code&gt;add_header&lt;/code&gt; wipes parent declarations.&lt;br&gt;
Fix: snippet include pattern in every location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall 15: Early Hints emitted but contains preload for a non existent resource.&lt;/strong&gt;&lt;br&gt;
Symptom: 404 in network panel for the preloaded resource; LCP not improved.&lt;br&gt;
Why it breaks: preload URL is wrong or the resource was renamed.&lt;br&gt;
Fix: audit Early Hints preload URLs. Each must resolve to 200 OK.&lt;/p&gt;


&lt;h2&gt;
  
  
  13. DIAGNOSTIC COMMANDS
&lt;/h2&gt;

&lt;p&gt;Reference of every command useful for SEO header investigation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inspect SEO headers
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Full SEO family at once&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(x-robots-tag|link|location|content-language):"&lt;/span&gt;

&lt;span class="c"&gt;# As Googlebot&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/page.html

&lt;span class="c"&gt;# As Bingbot&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/page.html

&lt;span class="c"&gt;# As ClaudeBot&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; ClaudeBot/1.0; +claudebot@anthropic.com)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/page.html

&lt;span class="c"&gt;# As GPTBot&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.0; +https://openai.com/gptbot"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/page.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  X-Robots-Tag verification
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Confirm directive&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag

&lt;span class="c"&gt;# Check all non HTML file types&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;ext &lt;span class="k"&gt;in &lt;/span&gt;pdf png jpg svg woff2 json xml csv zip&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/test.&lt;/span&gt;&lt;span class="nv"&gt;$ext&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== &lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt; ==="&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# Check for accidental noindex on production pages&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;url &lt;span class="k"&gt;in&lt;/span&gt; / /about /services /contact /blog&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== &lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt; ==="&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# Compare HTTP and HTML signals&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"HTTP:"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"HTML:"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;meta[^&amp;gt;]*name="robots"[^&amp;gt;]*&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Link header verification
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Confirm Link header presence and parse&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'^link:'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/, /\n    /g'&lt;/span&gt;

&lt;span class="c"&gt;# Check canonical&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'rel="canonical"[^,]*'&lt;/span&gt;

&lt;span class="c"&gt;# Check hreflang cluster&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'hreflang="[^"]*"'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;

&lt;span class="c"&gt;# Verify preload targets resolve&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;url &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'^link:'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;[^&amp;gt;]+&amp;gt;'&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;&amp;gt;'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# Test Early Hints&lt;/span&gt;
curl &lt;span class="nt"&gt;-sv&lt;/span&gt; &lt;span class="nt"&gt;--http2&lt;/span&gt; https://example.com/ 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"HTTP/2 (103|200)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Location and redirect verification
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Single redirect&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# Full chain&lt;/span&gt;
curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# Count hops&lt;/span&gt;
&lt;span class="nv"&gt;HOPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"^HTTP/"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hops: &lt;/span&gt;&lt;span class="nv"&gt;$HOPS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Final URL and status&lt;/span&gt;
curl &lt;span class="nt"&gt;-sILo&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"Final: %{url_effective} Status: %{http_code} Redirects: %{num_redirects}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/old-url

&lt;span class="c"&gt;# Audit a list of old URLs&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; url&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;FINAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sILo&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{url_effective}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;HOPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"^HTTP/"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sILo&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$FINAL&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="nv"&gt;$HOPS&lt;/span&gt;&lt;span class="s2"&gt; hops, final &lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; urls-to-audit.txt

&lt;span class="c"&gt;# Verify POST is preserved on 307/308&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/api/v1/something | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# Detect redirect loop (timeout after 5 seconds, max 10 redirects)&lt;/span&gt;
curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; &lt;span class="nt"&gt;--max-redirs&lt;/span&gt; 10 &lt;span class="nt"&gt;--max-time&lt;/span&gt; 5 https://example.com/maybe-looping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Server side investigation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find every X-Robots-Tag in the config&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"X-Robots-Tag"&lt;/span&gt; /etc/nginx/

&lt;span class="c"&gt;# Find every Link header&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"Link"&lt;/span&gt; /etc/nginx/sites-available/

&lt;span class="c"&gt;# Find every redirect (return 301/302/etc, rewrite ... permanent)&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"return (301|302|303|307|308)|rewrite.*(permanent|redirect)"&lt;/span&gt; /etc/nginx/sites-available/

&lt;span class="c"&gt;# Find any open redirect patterns (variable in return target)&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"return (301|302|303|307|308).*&lt;/span&gt;&lt;span class="se"&gt;\\\$&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; /etc/nginx/sites-available/

&lt;span class="c"&gt;# Check active config&lt;/span&gt;
nginx &lt;span class="nt"&gt;-T&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"x-robots-tag|^[[:space:]]*link |return 30|early_hints"&lt;/span&gt;

&lt;span class="c"&gt;# Reload after changes&lt;/span&gt;
nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Google Search Console verification
&lt;/h3&gt;

&lt;p&gt;The authoritative SEO check. For each URL you care about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Search Console for the property.&lt;/li&gt;
&lt;li&gt;Top search bar: paste the URL.&lt;/li&gt;
&lt;li&gt;Click Enter.&lt;/li&gt;
&lt;li&gt;Wait for the report to load. Sections:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL is on Google&lt;/strong&gt;: indexed correctly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL is not on Google&lt;/strong&gt;: not indexed; reason shown.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click "Test live URL" to fetch with Googlebot now and see headers.&lt;/li&gt;
&lt;li&gt;Under "Page indexing":

&lt;ul&gt;
&lt;li&gt;"Indexing allowed?" should be "Yes" for pages you want indexed.&lt;/li&gt;
&lt;li&gt;"User-declared canonical" and "Google-selected canonical" should match.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Under "Crawl":

&lt;ul&gt;
&lt;li&gt;"Last crawl" date should be recent.&lt;/li&gt;
&lt;li&gt;"Crawled as" should be Googlebot Smartphone (mobile first).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is ground truth. Any disagreement between curl output and Search Console means the URL has not been re crawled yet.&lt;/p&gt;


&lt;h2&gt;
  
  
  14. CROSS-REFERENCES
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="//framework-http-caching-headers.md"&gt;framework-http-caching-headers.md&lt;/a&gt;: Cache-Control, ETag, Last-Modified, Expires, Vary, Age. Preloaded resources should have correct cache directives; redirects often need no caching; X-Robots-Tag has no caching implications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//framework-http-content-headers.md"&gt;framework-http-content-headers.md&lt;/a&gt;: Content-Type, Content-Language, Content-Encoding, Content-Length, Content-Disposition. Content-Language pairs with hreflang declared via Link header. Content-Disposition pairs with X-Robots-Tag for downloadable file handling.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//UNIVERSAL-RANKING-FRAMEWORK.md"&gt;UNIVERSAL-RANKING-FRAMEWORK.md&lt;/a&gt;: the master ranking reference. Section 24 (Bubbles Nginx config) inherits SEO header configuration from here.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//SEO-BUILD-REFERENCE.md"&gt;SEO-BUILD-REFERENCE.md&lt;/a&gt; v2.4: the build playbook.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//framework-hreflang.md"&gt;framework-hreflang.md&lt;/a&gt;: full coverage of multi region SEO. Companion to Link header hreflang in Section 6 here.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//framework-robotstxt-crawlbudget.md"&gt;framework-robotstxt-crawlbudget.md&lt;/a&gt;: robots.txt syntax and crawl budget management. Pairs with X-Robots-Tag distinction in Section 5.5.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//framework-canonicalization.md"&gt;framework-canonicalization.md&lt;/a&gt;: canonical URL strategy. Companion to Link rel=canonical and the redirect/canonical interaction in Section 8.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//framework-corewebvitals.md"&gt;framework-corewebvitals.md&lt;/a&gt;: LCP, INP, CLS targets. Preload via Link header and Early Hints (103) directly improve LCP.&lt;/li&gt;
&lt;li&gt;
&lt;a href="//framework-security-headers.md"&gt;framework-security-headers.md&lt;/a&gt;: HSTS, CSP, X-Frame-Options. Open redirect security pairs with the broader security header stack.&lt;/li&gt;
&lt;li&gt;Google X-Robots-Tag documentation: &lt;a href="https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag" rel="noopener noreferrer"&gt;https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google redirects documentation: &lt;a href="https://developers.google.com/search/docs/crawling-indexing/301-redirects" rel="noopener noreferrer"&gt;https://developers.google.com/search/docs/crawling-indexing/301-redirects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google international and multi region: &lt;a href="https://developers.google.com/search/docs/specialty/international/overview" rel="noopener noreferrer"&gt;https://developers.google.com/search/docs/specialty/international/overview&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MDN Link header: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Link" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MDN Location header: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Location" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Location&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RFC 8288 (Web Linking): &lt;a href="https://www.rfc-editor.org/rfc/rfc8288" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc8288&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RFC 9110 (HTTP Semantics, redirects and Location): &lt;a href="https://www.rfc-editor.org/rfc/rfc9110" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc9110&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;HTTP 103 Early Hints: &lt;a href="https://www.rfc-editor.org/rfc/rfc8297" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc8297&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  APPENDIX A: ONE PAGE QUICK REFERENCE
&lt;/h2&gt;
&lt;h3&gt;
  
  
  X-Robots-Tag
&lt;/h3&gt;

&lt;p&gt;Production HTML default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Robots-Tag: max-snippet:200, max-image-preview:large, max-video-preview:-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Block from indexing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Robots-Tag: noindex, nofollow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time limited:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Robots-Tag: unavailable_after: 31 Dec 2026 23:59:59 GMT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bot specific:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Robots-Tag: googlebot: nosnippet
X-Robots-Tag: bingbot: noarchive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Link
&lt;/h3&gt;

&lt;p&gt;Canonical for non HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;https://example.com/canonical&amp;gt;; rel="canonical"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Preload hero image (LCP):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;/images/hero.webp&amp;gt;; rel="preload"; as="image"; fetchpriority="high"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Preload font:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;/fonts/main.woff2&amp;gt;; rel="preload"; as="font"; crossorigin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hreflang (reciprocal cluster, set on every variant):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;https://example.com/&amp;gt;; rel="alternate"; hreflang="en-US", &amp;lt;https://example.com/es/&amp;gt;; rel="alternate"; hreflang="es-MX", &amp;lt;https://example.com/&amp;gt;; rel="alternate"; hreflang="x-default"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Location
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Permanent URL change&lt;/td&gt;
&lt;td&gt;301&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary URL change&lt;/td&gt;
&lt;td&gt;302&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After form POST (force GET on next)&lt;/td&gt;
&lt;td&gt;303&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary, preserve POST&lt;/td&gt;
&lt;td&gt;307&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permanent, preserve POST&lt;/td&gt;
&lt;td&gt;308&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;HTTP to HTTPS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;www to non www:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="nv"&gt;$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Old URL pattern to new:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/old/(.*)$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;/new/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three commands every operator should know:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Confirm SEO headers on a URL&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/page.html | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(x-robots-tag|link|location):"&lt;/span&gt;

&lt;span class="c"&gt;# Trace a redirect chain&lt;/span&gt;
curl &lt;span class="nt"&gt;-sLI&lt;/span&gt; https://example.com/old-url | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP|Location):"&lt;/span&gt;

&lt;span class="c"&gt;# Apply nginx changes&lt;/span&gt;
nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two end to end tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify a noindex directive is in effect&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/staging-page | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; x-robots-tag
&lt;span class="c"&gt;# Should show: x-robots-tag: noindex, nofollow&lt;/span&gt;

&lt;span class="c"&gt;# Verify a redirect resolves in one hop&lt;/span&gt;
curl &lt;span class="nt"&gt;-sILo&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"Hops: %{num_redirects} Final: %{url_effective} Status: %{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://example.com/old-url
&lt;span class="c"&gt;# Should show: Hops: 1 Final: https://example.com/new-url Status: 200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If both produce expected output, the SEO header stack is correctly wired.&lt;/p&gt;




&lt;p&gt;End of framework-http-seo-headers.md.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related references
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://thatdevpro.com/reference/http-caching-headers/" rel="noopener noreferrer"&gt;HTTP caching headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thatdevpro.com/reference/http-content-headers/" rel="noopener noreferrer"&gt;HTTP content headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thatdevpro.com/reference/http-cors-headers/" rel="noopener noreferrer"&gt;HTTP CORS headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thatdevpro.com/services/engine-optimization/" rel="noopener noreferrer"&gt;Engine optimization services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thatdeveloperguy.com/" rel="noopener noreferrer"&gt;ThatDeveloperGuy — SDVOSB web studio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Authored at &lt;a href="https://thatdevpro.com" rel="noopener noreferrer"&gt;ThatDevPro&lt;/a&gt;, the SEO and engine-optimization arm of &lt;a href="https://thatdeveloperguy.com" rel="noopener noreferrer"&gt;ThatDeveloperGuy&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>http</category>
      <category>seo</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
