← back to Consulting Designerwallcoverings Com
attribution prep (DTD-A): per-channel UTM+coupon scheme (data/attribution-scheme.json), attribution-spec + gtag theme-install docs, inert G-XXXX gtag snippet; GA4 property + gtag-install gated to pending-approval
a4ad6c614058c21e65261646314c860ef5f0487f · 2026-07-26 15:30:19 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Files touched
A data/attribution-scheme.jsonA docs/attribution-spec.mdA docs/gtag-theme-install.mdA snippets/gtag.html
Diff
commit a4ad6c614058c21e65261646314c860ef5f0487f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 26 15:30:19 2026 -0700
attribution prep (DTD-A): per-channel UTM+coupon scheme (data/attribution-scheme.json), attribution-spec + gtag theme-install docs, inert G-XXXX gtag snippet; GA4 property + gtag-install gated to pending-approval
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
data/attribution-scheme.json | 160 +++++++++++++++++++++++++++++++++++++++++++
docs/attribution-spec.md | 135 ++++++++++++++++++++++++++++++++++++
docs/gtag-theme-install.md | 58 ++++++++++++++++
snippets/gtag.html | 65 ++++++++++++++++++
4 files changed, 418 insertions(+)
diff --git a/data/attribution-scheme.json b/data/attribution-scheme.json
new file mode 100644
index 0000000..c6f0840
--- /dev/null
+++ b/data/attribution-scheme.json
@@ -0,0 +1,160 @@
+{
+ "_meta": {
+ "title": "Designer Wallcoverings — per-channel UTM + coupon attribution scheme",
+ "purpose": "Attribution-before-optimization (DTD verdict A). Every link a DW social/marketing channel emits carries a deterministic UTM stamp, and every offer carries a per-channel coupon code, so both click-path AND redemption-path conversions map back to the originating channel in GA4 + Shopify — even when link params are stripped (dark social, in-app browsers).",
+ "engagement": "DW consulting engagement, TK-19",
+ "authored": "2026-07-26",
+ "authored_by": "yolo-worker (SAFE-ONLY prep, no live writes)",
+ "destination_store": "designer-laboratory-sandbox.myshopify.com (LIVE Designer Wallcoverings Shopify store — legacy misnomer, treat as production)",
+ "storefront_domain": "www.designerwallcoverings.com",
+ "ga4_status": "Property provisioned for the main store per dw-analysis.json; measurement ID (G-XXXX) not yet rolled out. This scheme + the gtag snippet + the two pending-approval memos close that gap.",
+ "channels_connected": 7
+ },
+
+ "utm_convention": {
+ "case": "lowercase-kebab for campaign/content/term; lowercase for source/medium",
+ "encoding": "URL-encode all values; no spaces, no uppercase, no punctuation other than hyphen",
+ "params": {
+ "utm_source": "the channel key (facebook, instagram, tiktok, youtube, bluesky, threads, linkedin). One canonical token per platform — never 'fb', 'ig', 'yt' in the URL; the short forms are only used inside coupon codes.",
+ "utm_medium": "the traffic class. Controlled vocabulary: 'social' (organic feed/post), 'social-bio' (link-in-bio / profile link), 'social-story' (stories/reels/shorts swipe-ups), 'paid-social' (boosted/paid placements), 'social-dm' (direct-message / outreach links). Paid uses 'paid-social' so GA4 default-channel-grouping files it under Paid Social, not Organic Social.",
+ "utm_campaign": "campaign slug: <yyyy>-<qN>-<theme>, e.g. 2026-q3-elitis-launch, 2026-q3-staged-draft-drip, always-on-brand. Reuse the same slug across channels for one campaign so GA4 can compare channels within a campaign.",
+ "utm_content": "creative / placement variant for A/B and post-level attribution: <format>-<descriptor>, e.g. reel-grasscloth-bedroom, carousel-thibaut-5, pin-damask-hero. Optional but recommended.",
+ "utm_term": "reserved for paid keyword/audience on paid-social only; omit for organic."
+ },
+ "builder_template": "https://www.designerwallcoverings.com/{path}?utm_source={source}&utm_medium={medium}&utm_campaign={campaign}&utm_content={content}",
+ "notes": [
+ "Shopify preserves UTM params through to checkout and records them on the order (landing_site + referring params), so GA4 (client-side) AND Shopify (server-side order) both capture the same stamp.",
+ "For the ~50 sister-site microsite fleet used as a discovery network, add utm_source=<microsite-slug>&utm_medium=referral-microsite when they link into the flagship store — kept out of this file's per-channel table but same convention.",
+ "Always link to a canonical https://www.designerwallcoverings.com/... URL (not a myshopify.com URL) so cookies + GA4 hostname stay consistent."
+ ]
+ },
+
+ "coupon_convention": {
+ "why": "Link-based UTM is lost on dark social, pasted links, and in-app browsers that strip query strings. A unique per-channel discount code is a second, redemption-based attribution path: the code itself names the channel at checkout, independent of any URL param.",
+ "format": "DW-<CHANNELCODE>-<OFFER>",
+ "channel_codes": {
+ "facebook": "FB",
+ "instagram": "IG",
+ "tiktok": "TT",
+ "youtube": "YT",
+ "bluesky": "BS",
+ "threads": "TH",
+ "linkedin": "LI"
+ },
+ "offer_tokens": {
+ "SAMPLE": "free / discounted memo sample offer",
+ "10": "10% off order",
+ "15": "15% off order",
+ "TRADE": "to-the-trade design-pro incentive (LinkedIn / B2B lean)"
+ },
+ "examples": ["DW-IG-10", "DW-TT-SAMPLE", "DW-LI-TRADE", "DW-YT-15"],
+ "rules": [
+ "One code per (channel x offer) so redemptions bucket cleanly by channel.",
+ "Codes are created as Shopify discount codes — GATED, drafted in pending-approval, never created live by this prep pass.",
+ "Report redemptions from Shopify Admin > Discounts, cross-referenced with GA4 coupon (item-level 'coupon' param on purchase events) for a two-source check.",
+ "Keep offer economics identical across channels within a campaign so channel comparison isn't confounded by a richer offer on one platform."
+ ]
+ },
+
+ "channels": [
+ {
+ "key": "facebook",
+ "label": "Facebook Pages",
+ "connected": true,
+ "accounts": 80,
+ "profile": "https://www.facebook.com/DesignerWallcoverings/",
+ "utm_source": "facebook",
+ "utm_medium_default": "social",
+ "utm_medium_paid": "paid-social",
+ "coupon_code": "DW-FB-10",
+ "notes": "80 connected Pages (sister-site fleet). For per-Page attribution, extend utm_content with the page slug, e.g. utm_content=post-<pageslug>-<creative>. Meta strips fbclid but preserves utm_* on outbound link clicks."
+ },
+ {
+ "key": "instagram",
+ "label": "Instagram",
+ "connected": true,
+ "accounts": 34,
+ "profile": "https://www.instagram.com/designerwallcoverings/",
+ "utm_source": "instagram",
+ "utm_medium_default": "social-bio",
+ "utm_medium_story": "social-story",
+ "utm_medium_paid": "paid-social",
+ "coupon_code": "DW-IG-10",
+ "notes": "Primary click path is link-in-bio (social-bio) since feed posts aren't clickable; Stories/Reels use social-story. In-app browser frequently strips query params — the DW-IG-10 coupon is the reliable fallback attribution here. 34 accounts: use utm_content to carry the account handle if multi-account posting."
+ },
+ {
+ "key": "tiktok",
+ "label": "TikTok",
+ "connected": true,
+ "accounts": 1,
+ "profile": "https://www.tiktok.com/@designerwallcoverings",
+ "utm_source": "tiktok",
+ "utm_medium_default": "social-bio",
+ "utm_medium_paid": "paid-social",
+ "coupon_code": "DW-TT-SAMPLE",
+ "notes": "TikTok in-app browser is aggressive about stripping params — coupon attribution (DW-TT-SAMPLE) is essential. If TikTok Shop is later connected, that becomes its own server-side attribution surface separate from this UTM path."
+ },
+ {
+ "key": "youtube",
+ "label": "YouTube",
+ "connected": true,
+ "accounts": 1,
+ "profile": "https://www.youtube.com/@DesignerWallcoverings",
+ "utm_source": "youtube",
+ "utm_medium_default": "social",
+ "utm_medium_story": "social-story",
+ "utm_medium_paid": "paid-social",
+ "coupon_code": "DW-YT-15",
+ "notes": "Description links + pinned-comment links carry full UTM (YouTube preserves query strings). Shorts use social-story. Good candidate for utm_content=video-<slug> for per-video attribution."
+ },
+ {
+ "key": "bluesky",
+ "label": "Bluesky",
+ "connected": true,
+ "accounts": 1,
+ "profile": "",
+ "utm_source": "bluesky",
+ "utm_medium_default": "social",
+ "coupon_code": "DW-BS-10",
+ "notes": "Bluesky link cards preserve UTM. No paid surface — organic 'social' only. Low volume expected; still stamp so it's measurable rather than lumped into 'direct/unknown'."
+ },
+ {
+ "key": "threads",
+ "label": "Threads",
+ "connected": true,
+ "accounts": 1,
+ "profile": "",
+ "utm_source": "threads",
+ "utm_medium_default": "social",
+ "coupon_code": "DW-TH-10",
+ "notes": "Meta property; UTM preserved on outbound clicks but the Threads in-app browser can strip params, so DW-TH-10 backstops. Keep utm_source=threads distinct from facebook/instagram so Meta channels are separable in GA4."
+ },
+ {
+ "key": "linkedin",
+ "label": "LinkedIn",
+ "connected": true,
+ "accounts": 1,
+ "profile": "https://www.linkedin.com/company/designerwallcoverings/",
+ "utm_source": "linkedin",
+ "utm_medium_default": "social",
+ "utm_medium_paid": "paid-social",
+ "coupon_code": "DW-LI-TRADE",
+ "notes": "B2B / to-the-trade lean — offer token is TRADE (design-pro incentive) rather than a consumer % off. LinkedIn preserves UTM cleanly. Ideal for utm_campaign=always-on-trade + utm_content=article-<slug>."
+ }
+ ],
+
+ "ga4_events_to_configure": {
+ "note": "Enhanced measurement covers page_view, scroll, outbound click, site search, video, file download automatically. The commerce events below must be sent by the Shopify theme's dataLayer/gtag and then marked as key events (conversions) in GA4 Admin. Configuration is GATED (memo a); this list is the spec for that config.",
+ "standard_ecommerce": ["view_item", "add_to_cart", "begin_checkout", "add_shipping_info", "add_payment_info", "purchase"],
+ "dw_custom": ["request_sample", "sample_added_to_cart", "trade_account_signup", "email_signup", "quote_request"],
+ "key_events_conversions": ["purchase", "request_sample", "begin_checkout", "trade_account_signup", "email_signup"],
+ "coupon_capture": "On the purchase event, pass the item-level/coupon field with the redeemed discount code (e.g. DW-IG-10) so GA4 attributes revenue to the channel by coupon, matching the coupon_convention above."
+ },
+
+ "reporting_views": [
+ "GA4 Traffic acquisition, grouped by Session source / medium — validates the utm_source/utm_medium taxonomy is landing correctly.",
+ "GA4 Free-form exploration: Session source/medium (dimension) x Key events + Purchase revenue (metrics) — the core social-to-revenue attribution table across all 7 channels.",
+ "Shopify Admin > Discounts: redemptions per DW-<CHANNEL>-<OFFER> code — the redemption-path cross-check.",
+ "Campaign roll-up: filter by utm_campaign to compare channels head-to-head within one campaign (e.g. 2026-q3-elitis-launch across FB/IG/TT/YT/LI)."
+ ]
+}
diff --git a/docs/attribution-spec.md b/docs/attribution-spec.md
new file mode 100644
index 0000000..b95a552
--- /dev/null
+++ b/docs/attribution-spec.md
@@ -0,0 +1,135 @@
+# Designer Wallcoverings — Attribution Spec
+
+**Engagement:** DW consulting engagement (TK-19)
+**Date:** 2026-07-26
+**Status:** SPEC / PREP ONLY — no GA4 property created, no live theme touched, no Shopify discount created. Those steps are gated for Steve's approval (see `~/.claude/yolo-queue/pending-approval/`).
+**Machine-readable companion:** [`data/attribution-scheme.json`](../data/attribution-scheme.json)
+**Guiding decision:** DTD verdict **A — attribution before optimization**. You cannot optimize a channel mix you cannot measure; instrument first, then optimize.
+
+---
+
+## 1. The problem this solves
+
+DW has **7 connected marketing channels** (Facebook, Instagram, TikTok, YouTube, Bluesky, Threads, LinkedIn) driving traffic to the flagship **LIVE Shopify store** (`designer-laboratory-sandbox.myshopify.com`, served at `www.designerwallcoverings.com`). Today none of that traffic is attributable to revenue: the GA4 property is provisioned but **no measurement ID is installed**, and links carry no consistent UTM stamp. Every social conversion currently lands in "Direct / unknown."
+
+Two attribution paths close the gap, and we run **both** because each fails where the other survives:
+
+| Path | Mechanism | Survives | Fails when |
+|------|-----------|----------|------------|
+| **Click path (UTM)** | `utm_*` query params on every outbound link, read by GA4 | Description links, bio links, link cards | In-app browsers / dark social strip query strings |
+| **Redemption path (coupon)** | Unique per-channel Shopify discount code | Any checkout, params stripped or not | Customer doesn't use a code |
+
+Together they give a two-source triangulation: GA4 says "this session came from Instagram," Shopify says "this order redeemed `DW-IG-10`."
+
+---
+
+## 2. UTM taxonomy
+
+Every link a DW channel emits to the store is stamped:
+
+```
+https://www.designerwallcoverings.com/{path}
+ ?utm_source={source}
+ &utm_medium={medium}
+ &utm_campaign={campaign}
+ &utm_content={content}
+```
+
+**Rules**
+- **Lowercase** `source`/`medium`; **lowercase-kebab** for `campaign`/`content`. No spaces, no punctuation but hyphens. URL-encode everything.
+- Always link to a canonical `www.designerwallcoverings.com/...` URL — never a raw `*.myshopify.com` URL — so GA4 hostname and cookies stay consistent.
+- Reuse **one `utm_campaign` slug across channels** for a single campaign so GA4 can compare channels within it.
+
+### `utm_source` — one canonical token per channel
+
+`facebook` · `instagram` · `tiktok` · `youtube` · `bluesky` · `threads` · `linkedin`
+
+(The short forms `fb`/`ig`/`yt` are **only** used inside coupon codes, never in URLs.)
+
+### `utm_medium` — controlled vocabulary
+
+| Value | Use |
+|-------|-----|
+| `social` | Organic feed / post |
+| `social-bio` | Link-in-bio / profile link (IG, TikTok primary path) |
+| `social-story` | Stories / Reels / Shorts |
+| `paid-social` | Boosted / paid placement — files under **Paid Social** in GA4's default channel grouping, not Organic |
+| `social-dm` | Direct-message / outreach links |
+
+### `utm_campaign` — slug format
+
+`<yyyy>-<qN>-<theme>` — e.g. `2026-q3-elitis-launch`, `2026-q3-staged-draft-drip`, or `always-on-brand` for evergreen.
+
+### `utm_content` — creative / placement variant (optional, recommended)
+
+`<format>-<descriptor>` — e.g. `reel-grasscloth-bedroom`, `carousel-thibaut-5`, `video-<slug>`. For multi-account channels (FB = 80 Pages, IG = 34 accounts) carry the account/page slug here for per-account attribution.
+
+### `utm_term`
+
+Reserved for paid keyword/audience on `paid-social` only. Omit for organic.
+
+---
+
+## 3. Per-channel table
+
+| Channel | `utm_source` | Default `utm_medium` | Coupon code | Notes |
+|---------|-------------|----------------------|-------------|-------|
+| Facebook (80 Pages) | `facebook` | `social` | `DW-FB-10` | Per-Page: carry page slug in `utm_content`. |
+| Instagram (34 accts) | `instagram` | `social-bio` | `DW-IG-10` | Feed posts unclickable → bio link is primary; in-app browser strips params, coupon is the reliable fallback. |
+| TikTok | `tiktok` | `social-bio` | `DW-TT-SAMPLE` | Aggressive param stripping → coupon essential. |
+| YouTube | `youtube` | `social` | `DW-YT-15` | Description + pinned-comment links carry full UTM; Shorts → `social-story`. |
+| Bluesky | `bluesky` | `social` | `DW-BS-10` | Organic only, no paid surface. Low volume but still measurable vs "direct." |
+| Threads | `threads` | `social` | `DW-TH-10` | Meta property; keep source distinct from FB/IG so Meta channels separate in GA4. |
+| LinkedIn | `linkedin` | `social` | `DW-LI-TRADE` | B2B / to-the-trade lean → TRADE incentive instead of consumer % off. |
+
+**Microsite fleet (~50 sister sites):** when they link into the flagship, stamp `utm_source=<microsite-slug>&utm_medium=referral-microsite`. Same convention, out of the per-channel table.
+
+---
+
+## 4. Coupon scheme
+
+**Format:** `DW-<CHANNELCODE>-<OFFER>`
+
+- **Channel codes:** FB · IG · TT · YT · BS · TH · LI
+- **Offer tokens:** `SAMPLE` (memo sample), `10` / `15` (% off), `TRADE` (design-pro incentive)
+- **One code per (channel × offer)** so redemptions bucket cleanly by channel.
+- Keep offer economics **identical across channels within a campaign** so channel comparison isn't confounded.
+- Codes are Shopify discount codes — **GATED**, drafted for approval, never created by this prep pass.
+- Report from **Shopify Admin → Discounts** (redemptions per code) cross-referenced with GA4's item-level `coupon` param on `purchase`.
+
+---
+
+## 5. GA4 events & key events
+
+**Automatic (enhanced measurement):** `page_view`, `scroll`, outbound `click`, `view_search_results`, `video_*`, `file_download`.
+
+**Commerce events the Shopify theme must send** (via gtag / dataLayer): `view_item`, `add_to_cart`, `begin_checkout`, `add_shipping_info`, `add_payment_info`, `purchase`.
+
+**DW custom events:** `request_sample`, `sample_added_to_cart`, `trade_account_signup`, `email_signup`, `quote_request`.
+
+**Mark as Key Events (conversions):** `purchase`, `request_sample`, `begin_checkout`, `trade_account_signup`, `email_signup`.
+
+**Coupon capture:** on `purchase`, pass the redeemed discount code in the `coupon` field so GA4 attributes revenue to the channel by coupon, matching §4.
+
+> Event configuration is part of the **gated** GA4 setup (memo a). This section is the spec that setup implements.
+
+---
+
+## 6. Reporting views
+
+1. **GA4 → Reports → Acquisition → Traffic acquisition**, grouped by *Session source / medium* — validates the taxonomy is landing correctly.
+2. **GA4 → Explore → Free form:** *Session source/medium* × *Key events + Purchase revenue* — the core social-to-revenue table across all 7 channels.
+3. **Shopify Admin → Discounts:** redemptions per `DW-<CHANNEL>-<OFFER>` — redemption-path cross-check.
+4. **Campaign roll-up:** filter by `utm_campaign` to compare channels head-to-head within one campaign.
+
+---
+
+## 7. What's gated (not done here)
+
+This spec is prep. The following are drafted to `~/.claude/yolo-queue/pending-approval/` and require Steve's go:
+
+- **`attribution-ga4-property.md`** — create the GA4 property + web data stream, obtain the `G-XXXX` measurement ID, configure key events. (Checks for the already-provisioned property first — idempotent.)
+- **`attribution-gtag-install.md`** — install the gtag snippet (`snippets/gtag.html`) into the LIVE Shopify theme once the real measurement ID exists.
+- **Shopify discount codes** — creating the seven `DW-*` codes is a live Shopify write and would be drafted separately when Steve wants the coupon path armed.
+
+Local rebuild + commit only. **No deploy** — deploy of the portal is noted in the GA4 memo.
diff --git a/docs/gtag-theme-install.md b/docs/gtag-theme-install.md
new file mode 100644
index 0000000..9ded0ea
--- /dev/null
+++ b/docs/gtag-theme-install.md
@@ -0,0 +1,58 @@
+# gtag → Shopify theme insertion instructions
+
+**Snippet file:** [`snippets/gtag.html`](../snippets/gtag.html)
+**Target:** the LIVE Designer Wallcoverings Shopify theme (`designer-laboratory-sandbox.myshopify.com`).
+**Status:** GATED. Editing the live theme is customer-facing and production. Do **not** perform these steps autonomously — they are drafted in `~/.claude/yolo-queue/pending-approval/attribution-gtag-install.md` for Steve's approval. This file is the exact runbook that memo references.
+
+> ⚠️ **Prerequisite:** the real `G-XXXX` measurement ID must exist first (from the gated GA4-property step). Installing the placeholder `G-XXXX` collects nothing. Do GA4 property → get ID → replace placeholder → then install.
+
+---
+
+## Option A — Shopify's native GA4 integration (preferred, lowest risk)
+
+Shopify has a first-party GA4 connection that wires purchase + checkout events server-side without editing `theme.liquid`:
+
+1. Shopify Admin → **Online Store → Preferences → Google Analytics** (or **Settings → Customer events**).
+2. Paste the **`G-XXXX`** measurement ID into the Google Analytics 4 field / connect the Google & YouTube channel's GA property.
+3. This auto-sends `page_view`, `view_item`, `add_to_cart`, `begin_checkout`, and `purchase` with the standard ecommerce schema.
+4. Add any **DW custom events** (`request_sample`, `trade_account_signup`, `email_signup`) as a **Custom pixel** under Settings → Customer events, or via theme event handlers.
+
+**Why preferred:** survives theme updates, no Liquid edit, purchase event carries the order's discount code in `coupon` automatically. Use this unless a custom `<head>` tag is specifically required.
+
+---
+
+## Option B — manual gtag in `theme.liquid` (when a raw tag is required)
+
+1. **Back up first.** Shopify Admin → Online Store → Themes → ⋯ → **Duplicate** the live theme (so there's a one-click rollback). Do not edit the only copy.
+2. Themes → ⋯ → **Edit code** → open `layout/theme.liquid`.
+3. Paste the entire contents of `snippets/gtag.html` **inside `<head>`**, immediately after the `<meta charset>` / `<meta name="viewport">` lines and **before** any other `<script>`.
+ - Alternatively, add the file as a snippet named `gtag` and include it with `{% render 'gtag' %}` at the top of `<head>`.
+4. **Replace both `G-XXXX` occurrences** with the real measurement ID.
+5. **Save.** Shopify recompiles the theme immediately (this is live the moment you save).
+6. Confirm `cookie_domain` matches the storefront apex (`designerwallcoverings.com`).
+
+---
+
+## Verification (either option)
+
+1. **GA4 DebugView:** GA4 Admin → DebugView. Load `www.designerwallcoverings.com` with the GA Debugger extension (or `?_gl=` debug) → confirm `page_view` arrives in real time.
+2. **Realtime report:** GA4 → Reports → Realtime → confirm your session with the correct property.
+3. **Tag presence:** `curl -s https://www.designerwallcoverings.com/ | grep -o 'G-[A-Z0-9]\{8,\}'` → returns the real ID, not `G-XXXX`.
+ - Or run the analytics skill's verifier: `bash ~/.claude/skills/analytics/scripts/verify_rollout.sh`.
+4. **UTM round-trip:** open a stamped link (`?utm_source=instagram&utm_medium=social-bio&utm_campaign=test`) → GA4 Realtime → confirm source/medium = instagram / social-bio.
+5. **Coupon round-trip (after codes exist):** place a test order with `DW-IG-10` → confirm the `coupon` field appears on the `purchase` event and the redemption shows in Shopify Admin → Discounts.
+
+---
+
+## Rollback
+
+- **Option A:** clear the measurement ID field / disconnect the GA property. Instant.
+- **Option B:** Themes → publish the duplicated backup theme, OR remove the pasted block from `theme.liquid` and Save.
+
+---
+
+## Notes
+
+- The placeholder `snippets/gtag.html` is intentionally inert (`G-XXXX`) so it can live in the repo without collecting data or risking a wrong-property leak.
+- Enhanced measurement (scroll, outbound click, site search, video, file download) is toggled **in the GA4 web data stream settings**, not in this snippet.
+- Never commit the real measurement ID as the only copy in a public place; it's low-sensitivity but keep the repo's committed snippet on the placeholder and substitute at install time.
diff --git a/snippets/gtag.html b/snippets/gtag.html
new file mode 100644
index 0000000..8f7b6e0
--- /dev/null
+++ b/snippets/gtag.html
@@ -0,0 +1,65 @@
+{%- comment -%}
+ Designer Wallcoverings — GA4 gtag.js snippet
+ ============================================
+ PLACEHOLDER measurement ID: G-XXXX ← replace with the real ID from the GA4 property
+ (obtained via the gated `attribution-ga4-property` step) BEFORE this goes live.
+
+ Placement: paste the block below as high in the <head> of `layout/theme.liquid`
+ as possible (immediately after the <meta charset> / <meta viewport> lines,
+ before other scripts). See docs/gtag-theme-install.md for exact instructions.
+
+ This snippet loads gtag and sends the automatic page_view. Enhanced measurement
+ (scroll, outbound click, site search, video, file download) is toggled ON in the
+ GA4 web data stream — no extra code needed for those.
+
+ The Shopify ecommerce events (view_item / add_to_cart / begin_checkout / purchase)
+ and the DW custom events (request_sample, trade_account_signup, email_signup) are
+ sent separately — see the commented reference block at the bottom of this file and
+ docs/attribution-spec.md §5. Do NOT hardcode order data here; Shopify's checkout /
+ Customer Events (web pixel) is the correct surface for purchase-level events.
+{%- endcomment -%}
+
+<!-- Google tag (gtag.js) — GA4 -->
+<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>
+<script>
+ window.dataLayer = window.dataLayer || [];
+ function gtag(){dataLayer.push(arguments);}
+ gtag('js', new Date());
+
+ gtag('config', 'G-XXXX', {
+ // Preserve UTM params through internal navigation so source/medium survives to checkout.
+ 'linker': { 'accept_incoming': true },
+ // DW store hostname — keeps attribution consistent across www + checkout.
+ 'cookie_domain': 'designerwallcoverings.com'
+ });
+</script>
+<!-- End Google tag -->
+
+{%- comment -%}
+ ─────────────────────────────────────────────────────────────────────────────
+ REFERENCE ONLY — commerce + custom events (do not enable until GA4 is live).
+ These illustrate the event shape from §5 of the attribution spec. In Shopify,
+ prefer the Customer Events / web-pixel surface for purchase so the coupon field
+ is populated from the real order discount code (DW-<CHANNEL>-<OFFER>).
+
+ // Product page:
+ gtag('event', 'view_item', {
+ currency: 'USD',
+ value: {{ product.price | divided_by: 100.0 }},
+ items: [{ item_id: '{{ product.selected_or_first_available_variant.sku }}',
+ item_name: {{ product.title | json }} }]
+ });
+
+ // Purchase (from checkout / web pixel) — note the coupon field for channel attribution:
+ gtag('event', 'purchase', {
+ transaction_id: '{{ order.name }}',
+ value: {{ order.total_price | divided_by: 100.0 }},
+ currency: 'USD',
+ coupon: '{{ order.discount_applications.first.title }}', // e.g. DW-IG-10
+ items: [ /* line items */ ]
+ });
+
+ // DW custom event example (sample request button handler):
+ // gtag('event', 'request_sample', { item_id: SKU, item_name: TITLE });
+ ─────────────────────────────────────────────────────────────────────────────
+{%- endcomment -%}
← 2a832f2 Traffic & Search Reality section: GSC 28d totals, 51% organi
·
back to Consulting Designerwallcoverings Com
·
TK-17 Phase 0: per-line GO/NO-GO decision sheet for the 22,9 f0b7063 →