Google analytics integration.
Sentry.io integration. Vince integration. Region-scoped consent (denied-by-default in EU/EEA/UK/CH, granted elsewhere, DPDP-friendly notice)
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# Analytics Setup — mozimo.in
|
||||
|
||||
The site ships with a layered, code-complete analytics stack. This document
|
||||
covers the dashboards you must create and the steps only you can do; after
|
||||
them, everything works with no further code changes.
|
||||
|
||||
```
|
||||
Visitor browser
|
||||
├─ gtag.js (GA4) ───────────────► GA4 property (consent-mode v2 gated)
|
||||
├─ /stats/js/script.js ─┐
|
||||
└─ events /stats/api/event ── Caddy ──► Vince container (first-party)
|
||||
Server (SSR) ── errors ──────────► Sentry
|
||||
Shopify (shop.mozimo.in) ─ purchase/checkout ──► same GA4 property
|
||||
```
|
||||
|
||||
## 1. What is already wired in code
|
||||
|
||||
| Layer | Implementation |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| GA4 | Direct `gtag.js` injected in `src/app/__root.tsx` head scripts (production only, when `VITE_GA4_MEASUREMENT_ID` is set at build). `send_page_view: false` + `PageViewTracker` = exactly one `page_view` per navigation. Cross-domain linker to `shop.mozimo.in`. |
|
||||
| Consent | Google Consent Mode v2: denied-by-default in EU/EEA/UK/CH, granted elsewhere. `ConsentBanner` shows only to those visitors (timezone-detected, cookie-stored choice, `/privacy` explains everything). |
|
||||
| First-party layer | Vince (Plausible protocol), self-hosted via `ansible/roles/analytics`, proxied same-origin at `/stats/*` by Caddy — survives ad blockers, needs no consent. |
|
||||
| E-commerce events | `view_item_list`, `select_item`, `view_item`, `begin_checkout`, `search`, `generate_lead` (forms — no PII), `click`/`contact` (all outbound/tel/mailto links via `src/components/Link.tsx`), `video_start`, `page_not_found`, `web_vitals`. **`purchase` is NOT hand-coded** — Shopify reports it (step 2.2). |
|
||||
| Errors | Sentry client + server (custom entries `src/client.tsx` / `src/server.ts`), off unless DSN set. |
|
||||
|
||||
## 2. One-time dashboards (manual)
|
||||
|
||||
### 2.1 GA4 property
|
||||
|
||||
1. analytics.google.com → Admin → **Create property** (`mozimo.in`),
|
||||
currency **INR**, timezone **India**.
|
||||
2. Add a **Web** data stream for `https://mozimo.in` → copy the
|
||||
Measurement ID (`G-…`).
|
||||
3. Put it in your local `.env` as `VITE_GA4_MEASUREMENT_ID=G-…`
|
||||
(it is baked into the bundle at `docker build` by the Makefile).
|
||||
4. Data retention: Admin → Data settings → set **14 months**.
|
||||
5. Data filters: add your office IP as **Internal Traffic** (defined filter).
|
||||
6. Cross-domain: Data stream → Configure tag settings → **Configure your
|
||||
domains** → add `shop.mozimo.in`.
|
||||
7. Mark **key events**: `generate_lead`, `begin_checkout` (Admin → Events).
|
||||
8. Register **custom definitions** (dimensions): `web_vitals_metric`,
|
||||
`web_vitals_rating`, `lead_type`, `lead_topic`, `lead_budget`,
|
||||
`search_term` (dimension), `result_count`, `link_domain`, `video_title`.
|
||||
9. Admin → Product links → **Search Console** → link the existing property
|
||||
(site verification meta is already in `__root.tsx`).
|
||||
|
||||
### 2.2 Shopify → GA4 (this is what makes purchases visible)
|
||||
|
||||
1. Shopify Admin → Settings → Apps → **Google & YouTube** channel → install.
|
||||
2. Connect the same Google account and select the GA4 property from 2.1.
|
||||
3. Shopify then injects the Google tag on `shop.mozimo.in` (storefront +
|
||||
checkout) and reports `purchase`/`begin_checkout`/`add_to_cart` into the
|
||||
property. The cross-domain linker on both sides stitches sessions —
|
||||
verify a `_gl=` parameter appears when clicking _Order this_ on a
|
||||
product page.
|
||||
4. Place one real (then refunded) test order and confirm `purchase` in
|
||||
GA4 Realtime/DebugView.
|
||||
|
||||
### 2.3 Sentry
|
||||
|
||||
1. sentry.io → create project **mozimo-web** (platform: TanStack Start /
|
||||
JavaScript).
|
||||
2. Copy the DSN into your local `.env` (`VITE_SENTRY_DSN`) **and** into
|
||||
`ansible/files/.env` (`SENTRY_DSN`) — client needs it at build, server at
|
||||
runtime.
|
||||
3. Optional sourcemap upload (better stack traces): put `SENTRY_AUTH_TOKEN`,
|
||||
`SENTRY_ORG`, `SENTRY_PROJECT` in the build machine env. Builds without
|
||||
them skip Sentry's vite plugin entirely.
|
||||
4. Verify: visit any page with `?sentry-test=1`… simplest check is a thrown
|
||||
error in devtools; a visible page_view + the event landing in Sentry is
|
||||
enough for sign-off.
|
||||
|
||||
### 2.4 Vince (first-party layer)
|
||||
|
||||
1. `./deploy.sh` once (the playbook creates the container + Caddy route).
|
||||
2. Open `https://<www_host>/stats/` → register the admin account (first
|
||||
visit only). Then **Add a website** with domain `mozimo.in`.
|
||||
3. Set `VITE_PLAUSIBLE_DOMAIN=mozimo.in` in your local `.env` and redeploy —
|
||||
the script tag is injected only when this is set.
|
||||
4. Check `https://<www_host>/stats/js/script.js` returns the script (200)
|
||||
and that browsing the site populates the dashboard within seconds.
|
||||
5. With uBlock Origin enabled: visits still appear in Vince but not GA4 —
|
||||
expected and exactly why this layer exists.
|
||||
|
||||
## 3. Verifying GA4 events (DebugView)
|
||||
|
||||
Append `?debug_mode=1`… simpler: build with `VITE_GA4_DEBUG=1` in `.env`
|
||||
temporarily — every event then carries `debug_mode: true` and appears in
|
||||
GA4 Admin → DebugView (with the Tag Assistant Companion extension).
|
||||
|
||||
Walk-through: home (page_view, view_item_list _The Mozimo Edit_) →
|
||||
/chocolate → /collections/bars (view_item_list) → a product (view_item) →
|
||||
_Order this_ (begin_checkout + outbound click with `_gl`) → /contact
|
||||
submit (generate_lead) → search overlay (`search`).
|
||||
|
||||
## 4. Operational notes
|
||||
|
||||
- **Dev is always excluded** — analytics scripts only inject in production
|
||||
builds.
|
||||
- **Disabling a tool** = leaving its env var empty. Nothing breaks.
|
||||
- **Changing the GA4 property** = change the env var and redeploy.
|
||||
- Sitemap (`dist/client/sitemap.xml` from `scripts/generate-sitemap.mjs`)
|
||||
and `robots.txt` are live for Search Console; submit the sitemap once in
|
||||
Search Console → Sitemaps.
|
||||
- Phase 2 (in-container cart) should add `add_to_cart`, `view_cart`,
|
||||
`remove_from_cart` via the same helpers in `src/lib/analytics.ts`.
|
||||
Reference in New Issue
Block a user