Why I’m building MockShop, the stack behind it, and how to run it locally or with Docker to validate GA4/Matomo/ODP/Optimizely implementations.
Note: MockShop has been renamed to shop404. Names and examples below may still refer to MockShop while I update docs.
Most analytics and experimentation work happens on real sites with real constraints. That’s great for context—but not so great when you need a safe, repeatable environment to design data models, validate tagging, or run parity checks across tools.
Enter MockShop: my in‑progress, private demo store that combines a simple ecommerce flow and a multi‑step donation wizard. It’s designed to exercise “just enough” complexity to hit real‑world cases without dragging you into framework internals or complicated backends.
Status: private, WIP (not yet released). If you’re curious or want early access, reach out.
Why I’m building this
- Repeatable QA: Stand up a clean, consistent environment for analytics and tag manager validation.
- Parity testing: Compare GA4 and Matomo side‑by‑side using the same events and journeys.
- Consent‑aware demos: Show how Consent Mode (GTM) and
_paq.requireConsent
(Matomo) shape data collection. - Experimentation scaffolding: Drop in Optimizely Web snippets to prototype activations and measure impact.
- Teaching tool: A concrete playground for workshops and onboarding analysts/engineers.
What’s inside
- Ecommerce flow: products grid → product details → cart → checkout → order confirmation.
- Donation wizard (SPA): amount → details → payment → review → success.
- Monthly vs one‑time nudge; optional persistent monthly default stored per device.
- Client‑side validation with
donation_step
error markers (great for funnels).
- Analytics helpers: unified pushes to
window.dataLayer
(GA4/GTM) andwindow._mtm
(Matomo Tag Manager).- GA4 ecommerce item structure with category hierarchy (
item_category..item_category5
). - List context for impressions (
item_list_name
,item_list_id
,items[].index
). - Currency/purchase mapping; optional
tax
/shipping
.
- GA4 ecommerce item structure with category hierarchy (
- Matomo Content Tracking on the Learn/Resources section:
- Automatic impressions + visible impressions, explicit interaction events on CTAs/teasers.
- SPA safety with
trackContentImpressionsWithinNode(document)
.
- Consent banner with categories (analytics, marketing, experimentation).
- GTM always loads; Consent Mode v2 governs behavior.
- Matomo uses
_paq.requireConsent
and consent events from_mtm
.
- Runtime config via
/config.json
: injects GTM ID, MTM container URL, Optimizely Web snippet, and ODP SDK URL.
Stack & approach
- Frontend: Vite + React + Tailwind (fast dev loop, clear component boundaries, minimal ceremony).
- No backend database: It’s a mock—so everything you need for analytics is client‑side, and runtime configuration comes from
/config.json
. - Docker‑first deploy: The production image serves static assets and a tiny runtime that emits
/config.json
from environment variables. - Indexing locked down by default: robots and meta tags block crawlers in demo builds.
Key events & data layer MockShop emits a focused set of events you’d expect from a modern shop and a donation flow:
page_view
: on route changes/pages.view_item_list
: impressions withitem_list_name
,item_list_id
, and per‑itemindex
.view_item
: product detail.add_to_cart
: add to cart (always includeecommerce.currency
).begin_checkout
: checkout start (withecommerce.currency
).purchase
: order confirmation (includestransaction_id
,value
,currency
, optionaltax
/shipping
).donation_step
: donation wizard step with metadata (e.g.,step
, optionalamount
,interval
,error
).
GA4 mapping notes
- Items use GA4 naming (
item_id
,item_name
,price
,quantity
,item_category..item_category5
). - Impressions include list context (
item_list_name
,item_list_id
,index
). - Currency is included on cart/checkout/purchase.
- For funnels, donation steps annotate errors and context.
Matomo mapping notes
- Tag via Matomo Tag Manager and consume the same
ecommerce
object and custom events from_mtm
. - Parity: GA4’s single‑item
add_to_cart
vs Matomo’supdate_cart
(FULL CART). MockShop emitsupdate_cart
on add/remove/quantity change and again atbegin_checkout
. - Content tracking: blocks marked with
matomoTrackContent
anddata-content-*
attributes; SPA pages trigger scans explicitly.
Consent behavior
- GTM: Consent Mode v2 defaults are denied; user choice updates the model. GTM still loads but honors consent.
- Matomo:
_paq.requireConsent
is queued; consent events from the banner drive allow/deny behavior. MTM triggers can key off_mtm
consent events.
Local development Prereqs: Node 18+.
- Install and run
npm install
npm run dev
# App serves at http://localhost:5173
- Configure tags in dev
- Edit
public/config.json
to setGTM_ID
,MATOMO_TAG_MANAGER_CONTAINER_URL
, and optional Optimizely/ODP URLs. - Do not commit secrets—
public/config.json
in dev is your scratchpad.
- Build/preview
npm run build
npm run preview
Docker (local build)
docker build -t mockshop .
docker run -p 8080:3000 \
-e GTM_ID=GTM-XXXXXXX \
-e MATOMO_TAG_MANAGER_CONTAINER_URL=https://matomo.example.com/js/container_ABC123.js \
-e OPTIMIZELY_WEB_SNIPPET_URL=https://cdn.optimizely.com/js/PROJECT_ID.js \
-e ODP_SDK_URL=https://cdn.foqt.com/v1/odp.js \
mockshop
# App is at http://localhost:8080, and /config.json reflects env vars
Quick tips for credible testing
- Use small, realistic volumes; you’re validating logic, not load‑testing.
- Keep
transaction_id
unique on purchases; includecurrency
consistently. - For impressions, always include list context; for category hierarchies, prefer a path array you can map to GA4 fields and Matomo variables.
- For consent, test both “analytics on” and “analytics off” paths and verify behavior in GTM Preview and MTM Preview.
Roadmap highlights (WIP)
- Test harness to snapshot emitted payloads and compare against expectations (GA4 & Matomo parity checks).
- Optional Optimizely variations to demo activation patterns (URL, audience, attributes).
- Lightweight sample catalog tweaks to cover variant/option cases.
Current status & access MockShop is a private repo while I round off edges and docs. I’ll publish when it’s stable and properly documented. If you’d like early access for analytics QA or training work, ping me.