From Wayfair to AI Agents
Status: Living reference · Scope: The thirty-year arc from "tax follows the seller's warehouse" to "an AI agent quotes your French price under a purchase mandate" — and why one missing lang attribute now degrades your legal exposure, your accessibility score, and your machine-index score at the same time.
Tags: #Wayfair · #GDPR · #Omnibus · #EAA · #ShopifyMarkets · #GraphQL · #AEO · #AgenticCommerce · #SemanticComponents · #PrivacyByDesign
The summer of 2018
Three things happened within eight weeks of each other:
- 25 May 2018 — the GDPR became enforceable. Privacy obligations now attach to where the buyer is, not where the server is.
- 21 June 2018 — the U.S. Supreme Court decided South Dakota v. Wayfair, overruling the 1992 physical-presence rule. Sales tax obligations now attach to where the buyer is, not where the warehouse is.
- 18 July 2018 — the European Commission fined Google €4.34 billion over Android, the largest antitrust penalty in EU history. Default settings and pre-installed choices became enforceable conduct.
Different courts, different continents, different bodies of law — one principle: jurisdiction moved from the seller's location to the buyer's context. Everything in this article is downstream of that move.
Wayfair: the day compliance became a per-transaction computation
Before Wayfair, a merchant collected sales tax only where it had a physical presence. After it, "economic nexus" — South Dakota's threshold was $100,000 in sales or 200 transactions — meant a merchant selling into the United States faces 12,000+ overlapping tax jurisdictions, each with its own rates, holidays, and category rules.
No human bookkeeper can do that. The practical consequence of Wayfair was not a tax rule; it was an architectural mandate: the correct legal treatment of a sale must be computed per transaction, from the buyer's context, by software. Tax engines became infrastructure. Every regulation since has assumed that infrastructure exists.
Google's EU decade: what buyer-context enforcement costs
The EU spent the same years establishing what it costs to get buyer context wrong — on two tracks.
Antitrust — defaults and self-preferencing are conduct:
| Year | Case | Fine |
|---|---|---|
| 2017 | Shopping — self-preferencing its own comparison service in results | €2.42B |
| 2018 | Android — tying Search/Chrome to the Play license | €4.34B (upheld at ~€4.125B, 2024) |
| 2019 | AdSense — exclusivity clauses on third-party sites | €1.49B (annulled 2024) |
| 2025 | Ad-tech — favoring its own exchange across the buying chain | €2.95B |
Privacy — consent quality is measurable, and language is part of quality:
| Year | Authority | Fine | For |
|---|---|---|---|
| 2019 | CNIL (FR) | €50M | Opaque, non-specific ads consent — the first major GDPR fine |
| 2020 | CNIL (FR) | €100M | Cookies placed before consent |
| 2022 | CNIL (FR) | €150M | Refusing cookies harder than accepting them |
| 2022 | LG München I | €100 | Embedding Google Fonts from Google's servers — visitor IP transmitted pre-consent |
The Munich figure is symbolic; its effect was not. It established that a single third-party asset request is a data transfer requiring a legal basis — the reason first-party, self-hosted delivery is now the default posture for fonts, scripts, and media.
Read the two tables together and the lesson is one sentence: what you show the buyer by default, and what you fire before the buyer consents, are both enforceable — in the buyer's jurisdiction, judged in the buyer's language.
The field checklist: five things that get you flagged in the EU
The case law above compresses into five operational flags — each one visible to a regulator (or an automated audit) from the outside of your storefront:
| # | Flag | Legal anchor | What triggers it |
|---|---|---|---|
| 1 | Geo-fencing | Geo-blocking Regulation (EU) 2018/302 | Blocking EU visitors or auto-rerouting them to a "local" site without their consent; discriminating on price, payment, or delivery terms by nationality or location. Blocking EU IPs to dodge GDPR doesn't work either — obligations follow whom you target, not whom you admit |
| 2 | Fonts | GDPR Art. 6 · LG München I (2022) | Any third-party font CDN request (fonts.googleapis.com) fires the visitor's IP to a US provider before consent. Self-host, first-party, no exceptions |
| 3 | YouTube | ePrivacy / GDPR consent | A standard embed drops trackers on page load, pre-consent. Required posture: nocookie domain + click-to-load facade, loaded on consent and unloaded on revocation |
| 4 | Unlogged consent | GDPR Art. 7(1) | The burden of proof is the controller's: consent you cannot demonstrate — text shown, language, timestamp, mechanism — legally never happened. A working banner with no consent record is a liability with a UI |
| 5 | Omnibus without provenance | Directive (EU) 2019/2161 / Art. 6a PID | Every price reduction must display the lowest price of the prior 30 days — per market. That requires timestamped, location-scoped price history you can produce on demand; a single global price field cannot answer it |
Note what the five have in common: none is about intent, all are about infrastructure. Each is either computed correctly per buyer-context — or it's a flag.
Shopify's answer: one store, many jurisdictions
Wayfair asked "which rules apply to this sale?" The modern storefront must answer it on every page view. Shopify's Markets architecture is the commercial implementation, in three layers:
| Layer | Component | What it holds |
|---|---|---|
| Presentation | Horizon (successor to Dawn) | Theme blocks defined once and reused; all strings in locale files; currency/date formatting, subfolder URLs, and hreflang from market context; localized content via metafields and metaobjects instead of duplicated templates |
| Context | GraphQL | @inContext(country, language) returns market-correct prices, availability, and translations in one request; translations, markets, catalogs, and price lists exist only in GraphQL — the globalization data model is invisible to REST |
| Truth | Catalogs | A price list + a publication scoped to a market: per-market pricing in local currency, per-market assortment, resolved server-side |
The Dawn→Horizon shift matters here because Dawn's section-private blocks meant per-market changes multiplied across templates; Horizon's theme-level blocks and design tokens mean market adaptation is configuration, not forking. One product, one store, many lawful presentations — the Wayfair mandate, generalized from tax to price, disclosure, and language.
This is also where EU price law lands: the Omnibus Directive's "lowest price in the prior 30 days" disclosure is a per-market fact. It lives naturally in a per-market catalog; it is unanswerable from a single global price field.
i18n: one layer, scored three ways
Internationalization is where the legal, accessibility, and machine planes turn out to be the same plumbing.
Compliance. GDPR consent is valid only if informed — regulators read that as "comprehensible in the user's language." France's Loi Toubon, Québec's Bill 96, and Korean e-commerce disclosure rules mandate local language outright. The Cyber Resilience Act requires user documentation in a language the destination market easily understands. An English-only consent modal in Lyon is challengeable consent.
Accessibility. WCAG 3.1.1 requires <html lang> to match the served language — it selects the screen reader's speech engine, so a French page declared lang="en" is read in garbled phonetics. WCAG 3.1.2 covers inline language switches; ALT text in the wrong language fails the "alternative for that user" bar. Since 28 June 2025, the European Accessibility Act makes WCAG-level conformance a legal requirement for EU e-commerce — the accessibility score and the compliance posture are now the same number.
Machine-readability. hreflang, lang, and locale-keyed JSON-LD (inLanguage, local priceCurrency, stable @ids) are how answer engines select the correct locale variant of a page. Miss them and the English variant — with the wrong price context — gets served against a French query.
One false declaration degrades all three at once. A translated page still declaring its source language is worse than an untranslated one: the declaration is now a lie, and humans, screen readers, and machines all believe it.
The road to AI: the buyer's context gets a literal reader
LLM-based automation is the Wayfair principle taken to its endpoint. The buyer's context is no longer inferred by a human squinting at a page — it is read, verbatim, by software acting for the buyer. Four roles, four exposures:
The agent as reader. A shopping agent or answer engine grounds on declared signals, not vibes. If your locale variants are undeclared or contradictory, the agent quotes the wrong market's price or terms to its user — and you published the ambiguity, so you carry the misrepresentation. A machine-index score is best read as: how safely can an agent act on this page without guessing?
The agent as writer. Machine-translated legal and consent copy is still your legal statement — in Québec and France, the local-language version can be the binding one. Auto-translated content needs provenance (what model, from what canonical) and human sign-off on legal surfaces. A chatbot that can only explain returns in English is arguably non-compliant customer service in a mandated-language market.
The agent as auditor. The same declarations that let agents shop let them audit: declared-vs-actual language mismatch detection, cross-locale parity checks ("does the French policy assert the same rights as the English canonical? does the Omnibus notice exist in every EEA locale?"). These checks scale past any human review — but only over honest declarations; broken plumbing makes the auditor unreliable too.
The agent as transactor. When an agent purchases under a mandate, the human's authorization was captured on some consent surface in some language. The defensible audit record is not "the user consented" but "the user consented to this text, in this language " — locale belongs in the consent event itself.
Semantic components vs. compiled utility CSS: what the agent can actually read
If agents ground on declarations, then the markup itself is context — and the two dominant ways of building UI hand an LLM radically different context.
Hardcoded / utility-compiled markup (Tailwind-style classes, hashed CSS-modules, purged build artifacts) describes appearance: class="flex gap-2 text-sm font-medium" tells a machine how something looks and nothing about what it is. The class names are build outputs — renamed, purged, or reordered on every compile — so nothing in the DOM is a stable contract. An agent reading that page gets pixels-as-text: it must infer "this is the price, that is the add-to-cart" from visual adjacency, which is exactly the guessing that produces wrong-market quotes. And the inference is expensive — forty utility classes per node bloat the accessibility tree and burn context-window tokens to convey zero semantics.
Structured semantic components — BEM-namespaced components (uk-card, uk-price), custom elements (<product-card>), Horizon's theme blocks — make the DOM self-describing. The element's name is its role; roles map cleanly onto JSON-LD and ARIA landmarks, so the human view, the accessibility tree, and the machine plane stay one structure instead of three reconstructions. Design tokens (var(--brand-primary)) complete the separation: look lives in the token layer, meaning lives in the markup, and rebranding or re-theming never disturbs what an agent parses.
This is what makes global context automation tractable: across twenty locales, the semantic skeleton is invariant — only text, price, and lang change per market. An agent (or an auditor) that learned the structure once can read every market variant, and a cross-locale parity check diffs content against a stable frame. With per-market compiled utility soup there is no frame — every locale is a fresh inference problem. Semantic structure is to the AI era what the tax engine was to Wayfair: the layer that lets correctness be computed instead of guessed.
Implementation note: JSON-LD belongs in the content model, not the page
Schema.org is the shared vocabulary all of this grounds on — the agreed type system (Product, Offer, FAQPage, TechArticle) that search engines, answer engines, and shopping agents parse without negotiation. The mistake is treating JSON-LD as page decoration, hand-written per template and drifting from day one. Model it instead: each content type in your CMS maps to a schema.org type, and each field maps to a property — a Products collection carries the fields that become Product.name, Offer.price, priceCurrency, availability; an FAQ collection becomes FAQPage/Question/Answer pairs. A render step then serializes the item into its <script type="application/ld+json"> block, so the structured data is a build output of the model — it cannot disagree with the visible content, because both are projections of the same record. Three rules make it agent-grade: give every entity a stable @id (the identity agents join on across pages and markets — connect related entities into one @graph rather than emitting islands); emit locale context per market variant (inLanguage, the market's priceCurrency) from the same market record that drives the page; and never put anything in JSON-LD that isn't rendered on the page — mismatched structured data is treated as spam by crawlers and as ground truth by LLMs, the worst of both.
Seen this way, JSON-LD and Shopify's catalogs are the same move on two planes: both are machine-inference-optimized structures. The catalog pre-computes "what is the lawful price and assortment in this market" so no one derives it; JSON-LD pre-computes "what does this page assert, in which language, at which price" so no one infers it. Every layer this article has covered — lang, hreflang, semantic components, consent events with locale, timestamped price history — is the same optimization applied somewhere else: replace inference with declaration, because the reader is now a machine that will act on whichever it gets.
None of this is new, either. robots.txt (what machines may read), YAML front matter in markdown (what this document is — title, description, canonical, date — the contract every static-site pipeline builds on), and JSON-LD (what this page asserts) were the original "machine index score" of content, decades before anyone scored it. llms.txt is just robots' successor for the agent era, and a modern docs pipeline that diffs front matter against its CMS records is computing that score continuously. The agent era didn't invent the declaration layer — it raised the price of neglecting it.
Design and content privacy in the AI era
The same forces sharpen privacy from a banner problem into a design discipline — because agents don't just read your declared context, they republish it.
Design-side: first-party by default, consent-gated by construction.
- No third-party asset fires before consent. The Munich Google Fonts ruling made a single font request a data transfer; the durable answer is self-hosted fonts, first-party compiled CSS, and no CDN calls on the critical path. What never leaves your origin never needs a legal basis.
- Embeds are consent-scoped, not just consent-delayed. A privacy-facade pattern (e.g. YouTube via nocookie, loaded on consent, unloaded on revocation) treats consent as a live state, not a one-time gate — which is what "withdrawal as easy as giving" actually requires in the DOM.
- Consent is an event bus, not a cookie banner. Analytics, pixels, and — critically — agent permissions (mandates, entitlements) ride one gated channel, so "what is this page allowed to do right now" is a single queryable state instead of scattered script conditions.
Content-side: the machine plane is an egress channel.
- Curate what agents may read. JSON-LD, llms.txt, and the KB are deliberate publications to machines; treat them with release discipline. Everything else in the DOM is also readable — ALT text, hidden fields, HTML comments, data attributes — so internal notes, emails, and tokens must never appear there. An agent will quote what a human would have skimmed past.
- One canonical page per topic. Duplicate or drifted variants don't just split SEO — they hand an LLM contradictory ground truth, and the agent's answer inherits whichever variant it retrieved. Canon is now a correctness property, not an editorial preference.
- Minimize, then structure. Data minimization applies to content: publish the market-relevant fact (price, availability, rights) in structured form and resist leaking operational detail into public surfaces. What you structure well, agents cite correctly; what you over-publish, they redistribute.
- Bind policy to data, not to doors. Login walls govern humans; agents arrive through APIs and context windows. Permissions attached to the data itself (consent-scoped fields, entitlement-gated responses, redacted-by-default logs) travel with the data wherever an agent carries it.
The through-line
1994: mail-order catalogs, tax where the warehouse is. 2018: Wayfair and the GDPR move jurisdiction to the buyer; the Android fine makes defaults enforceable. 2018–2025: the EU prices out bad consent in billions, and per-market truth becomes a data-model requirement (Catalogs, Omnibus, EAA). 2026: the buyer sends software, and the software reads your declarations literally.
Every era's rule is the same rule, tightened: the sale is governed by the buyer's context, and the seller's infrastructure must compute that context correctly — first for the tax office, then for the regulator, then for the screen reader, and now for the agent. The merchants that treated localization, consent, and structured data as one system are the ones for whom agentic commerce is a channel, not a liability.
Related: Cybersecurity for AI — the CRA, firmware, and why the CISO/CTO/DPO are personally exposed; the consent-gated, server-side data plane this article assumes.