# StorePulse Audits

Dated one-pagers that turn a scrape round into a **defensible finding**. Four genres
live here; keep them distinct:

- **Sector / data audits** — what the snapshot data says about the DACH bio market
  (this section's focus). First entry: [`2026-06-05-seo-geo-ai-readiness.md`](2026-06-05-seo-geo-ai-readiness.md).
- **Competitive mechanics audits** — a live read of competitor storefronts (UX / AI-commerce
  mechanics), not scrape data. First: [`2026-06-06-fabular-vs-alfies-gurkerl-mechanics.md`](2026-06-06-fabular-vs-alfies-gurkerl-mechanics.md)
  — Fresh Haven (fabular ref) vs Alfies vs Gurkerl, with forwardable HTML companions in
  both languages ([`EN`](2026-06-06-fabular-vs-alfies-gurkerl-mechanics.html) ·
  [`DE`](2026-06-06-fabular-vs-alfies-gurkerl-mechanics-de.html), MD stays EN). The
  generator emits both: `python3 docs/audits/_gen-mechanics-briefing.py` from repo root.
  Latest in this genre: [`2026-06-06d-fabular-mcp-audit.md`](2026-06-06d-fabular-mcp-audit.md)
  — live read of the fabular demo's new **MCP server** (`/api/mcp`): it works (9 tools,
  agent-transactable), gaps are productization-readiness (session isolation, `isError`,
  1970-epoch MHD dates). Spec claims verified against the live MCP spec. Carries a
  same-day **Recheck (delta)** section: 3 of 4 punch-list items fixed within hours; the
  durable-session blocker remains (broader on re-probe). Briefing companion below.
- **Link-preview / social-sharing audit** — how a shared link renders (WhatsApp / OG / Twitter
  cards) across the three Isarland-context storefronts:
  [`2026-06-06e-social-sharing-link-preview-audit.md`](2026-06-06e-social-sharing-link-preview-audit.md).
  Headline inverts homepage↔product: the demo (`fabular.pages.dev`) has the richest tags but **no
  `og:image` anywhere** (logo-only, Twitter-only → imageless in WhatsApp); the live `isarland.de`
  carries real product photos but the homepage image 404s, product meta is **mis-keyed to the wrong
  product**, and the layer is UA-gated; the CTO build (`webshop.…workers.dev`) has the cleanest tags
  but serves a **200px image from the staging host**. **Internal / formative** (real prospect +
  named dev) — MD only, no forwardable HTML. Observed vs. inferred split per platform-renderer claim.
  **Re-check (2026-06-07), widened to SEO + GEO, in the Weiling _Schnittstellenreview_ form**
  (spec-vs-reality, Kritisch/Funktional/Strukturell, count-everything):
  [`2026-06-07-fabular-schnittstellenreview-social-seo-geo.md`](2026-06-07-fabular-schnittstellenreview-social-seo-geo.md).
  Headline: the `2026-06-06e` `og:image` fix landed in the **tags** but `/opengraph-image` serves an
  **empty body** (200, 0 bytes — verified curl HTTP/1.1+2 _and_ browser `fetch().blob().size`), so cards
  stay imageless for a new reason. +2 SEO findings — **153 sitemap product URLs (~7%) 404** (raw-umlaut
  slugs; 17/17 dead vs 43/43 ASCII alive), and a **3-way product count** (meta "40" / llms.txt "150+" /
  sitemap 2141). GEO axis positive (16/16 AI bots allowed). Shipped on
  [`social-share-briefing.pages.dev`](https://social-share-briefing.pages.dev) (44up-CI visuals, PIN-gated),
  which is now an **audit switcher** — sticky dated tabs (one panel at a time, deep-linkable via `#<id>`,
  ←/→ + J/K keys) plus an **"Alle · Drucken"** toggle that reveals all panels for print-to-PDF / cross-read.
  Tabs are driven by the `AUDITS` registry at the top of the generator (anti-drift seed the feed's `ENTRIES`
  can later read). The switcher = a **document tabset** (read one audit), deliberately *not* a second feed —
  the Observatory feed stays the discovery stream and links **in** to `#<id>` here. Regenerate via
  `python3 docs/audits/_gen-social-sharing-briefing.py`.
- **Engineering / security audits** — repo health, build, deps, pipeline. These predate
  this section and live flat in `docs/`: [`../AUDIT-2026-05-31.md`](../AUDIT-2026-05-31.md),
  [`../SECURITY-AUDIT-2026-05-29.md`](../SECURITY-AUDIT-2026-05-29.md).
- **Forwardable briefings** — a measurement turned into a self-contained, 44up-CI-styled
  HTML one-pager you can send to a partner (fonts embedded → renders offline, print-to-PDF
  ready). First: [`2026-06-06-fabular-digital-health-briefing.html`](2026-06-06-fabular-digital-health-briefing.html)
  (regenerate via `venv/bin/python docs/audits/_gen-fabular-briefing.py` from repo root).
  Also: [`2026-06-06d-fabular-mcp-audit.html`](2026-06-06d-fabular-mcp-audit.html) — the MCP /
  agentic-commerce briefing (DE; regenerate via `python3 docs/audits/_gen-fabular-mcp-briefing.py`).
  Same data discipline as the markdown audits, but presentation-grade and externally addressed.
  Brand: **44up** (the Observatory's own report) — never the recipient's CI.
  Convention: when FloTo asks for "an audit" → MD **and** this shareable HTML in the same pass;
  "internal audit" → MD only.
- **Engaging-surface family (MCP audit, Skinner-nudge + Kahneman, one content set, 3 forms):**
  - [`…-mcp-directions.html`](2026-06-06d-fabular-mcp-directions.html) — decision aid: 3 directions side by side (`_gen-mcp-directions.py`).
  - [`…-mcp-blend.html`](2026-06-06d-fabular-mcp-blend.html) — **the blend**: hero (A) → full-bleed live feed (B) → dossier (C) → earned end-reward; Dalí ray spine + `1970→2026-06-08` time-resolve (`_gen-mcp-blend.py`).
  - [`…-mcp-feed.html`](2026-06-06d-fabular-mcp-feed.html) — **B standalone**: widened Observatory live-feed, rows link to the audit (`_gen-mcp-feed.py`). Seed for the 44up.io feed.
  - [`…-mcp-briefing-ac.html`](2026-06-06d-fabular-mcp-briefing-ac.html) — **A+C standalone**: the pure audit briefing, no feed band (`_gen-mcp-briefing-ac.py`).
  - **Every one meets the standing bar** (FloTo): keyboard nav (real `<button>`/`<a>`, skip-link, J/K, focus ring), links that resolve, sources NEVER missing. Verify functionally, not by element-count.
- **The Observatory feed** — [`observatory-feed.html`](observatory-feed.html) (`_gen-observatory-feed.py`): aggregates **all** audits into one live 44up.io stream — masthead + aperture/Dalí ray, keyboard-operable filter chips (Alle/Fabular/Isarland/Roster/Benchmark), color-coded signal dots, each entry sourced + linked to its real `.md`/`.html`, "Du bist auf dem Stand" + Know-Thyself CTA. Prototype lives here (relative links to sibling audits); **portable to 44up-at**. Add a new audit = one `ENTRIES` dict in the generator.
  - **Two outputs, two audiences (ADR 0011 per-audience scoping).** The generator emits `observatory-feed.html` (internal prototype, **all** audits, from `ENTRIES`) **and** `forwardable-feed.html` (from a **separate, explicitly-curated `FORWARDABLE` list** — not a filter over `ENTRIES`, so nothing internal leaks by omission). The forwardable feed is the front-door deployed PIN-gated to `social-share-briefing.pages.dev` for the **shop/build team** (Christoph, Harald, Nils, Lu): 7 fabular audits (Runtime-Befund · Schnittstellenreview · Social-Sharing · MCP · Digital-Health · Mechanics · Round 2), the social-sharing two **deep-linking into the switcher `#<id>`**. **Excludes** the roster (cross-sector competitive) + the standalone Isarland audit (live prospect). Every deployed page carries the gate (no un-gated direct-URL bypass). Add a forwardable audit = one `FORWARDABLE` dict + co-deploy its briefing file.

File naming: `YYYY-MM-DD-<slug>.md` (or `.html` for briefings). One page. Sources mandatory.

---

## The method (sector / data audit)

A reusable seven-step approach, distilled from the 2026-06-05 SEO/GEO audit. The point
is not "print the numbers" — it's to get from *a score* to *the one lever that moves it*,
with every claim reproducible.

1. **Refresh the measurement first.** Run the relevant scraper round (`--all --force`)
   so the audit sits on current data, not a stale month. Record N scored / N failed.
2. **Decompose the composite.** A single score hides mechanics. Split it into orthogonal
   axes with explicit weights (here: SEO 70 / GEO 30 out of the `ai_readiness` WEIGHTS),
   in a reusable DuckDB script under `pipeline/` (ADR 0004 convention) — not a one-off
   query. The script *is* a citable source.
3. **Segment by a structural dimension.** Group by platform / cohort / city to find
   *where the variance lives*. "Sector avg 79" tells you nothing; "fab4minds 27 vs
   Shopify 99" tells you everything.
4. **Trace to a single lever.** Push past the symptom list to one root cause (here:
   client-side vs server-side rendering — the "JS-wall"). One cause that explains
   multiple bad signals beats six independent findings.
5. **Verify the outlier empirically — before concluding.** When a number jumps or a
   cohort looks extreme, *prove it* with a direct probe, don't trust one scrape:
   - the Fabular 78→100 swing → direct fetch of `/sitemap.xml`, `/llms.txt`, 404 behavior;
   - the fab4minds SEO 3.6 → `store_a11y` `img/form/h1 = 0` across **all 14** tenants.
   See [[feedback_test_before_concluding]]. A scraper false-negative is the default
   suspect, not the finding.
6. **Cite reproducible sources.** Every number gets a source: the script, the
   `table @ month`, the ADR, the probe command. An audit nobody can re-run is an opinion.
7. **State the strategic "so what."** End on the actionable lever and who it's for
   (here: prerender tenant shops → all three health dimensions move; a fab4minds pitch point).

**Source-citation rules** (mirrors the engineering audits' file:line discipline):
- Code/method → `path:symbol` or `path` + ADR number.
- Data → `table @ snapshot_month`, with the producing command.
- External claim → the probe command + date (data drifts; date it).
- Never cite a single scrape for a load-bearing number without a confirming probe.
