# Worked example: Acme Outdoor

All names, numbers and IDs are fictional. Acme Outdoor sells on `www.example.com`, uses GTM container `GTM-XXXXXXX`, GA4 web stream `G-XXXXXXXXXX`, a CMP in advanced consent mode, a third-party payment page on `pay.example.net`, and an order backend that sends `purchase` by Measurement Protocol. A partner, Example Co, publishes a gift guide that runs inside ChatGPT.

## 1. Symptom record and denominator

- Report: Traffic acquisition, Session default channel group, default channel group, Blended reporting identity, metric Sessions and Key events (purchase), property timezone, no filters.
- First change: 2026-09-15. Releases that week: a new CMP version (09-15) and a backend change to the purchase sender (09-16). GA4 change history shows no Admin changes in September.
- Baseline week 2026-09-01 to 09-07 against affected week 2026-09-22 to 09-28, both completed and processed, both inside the 14-month retention setting:
  - Unassigned sessions 1,200 to 4,800.
  - Total sessions 59,800 to 60,900.
  - Unassigned purchases 30 to 410, total purchases 1,450 to 1,470.
- The count rose, not just the share: 4,800 is far above the previous 8 weeks' range of 1,100 to 1,350. Purchases in Unassigned rose about 14 times, so this is ranked high.

## 2. Artifacts and channel group

- A dashboard showed `(not set)` for Source / medium on `page_view`. That is event scope on a non-key event, so `(not set)` is by design. Removed from the investigation.
- No thresholding, sampling or `(other)` message on the affected report.
- The rise appears in Session default channel group itself; Acme has no custom group yet. Not a group defect.

## 3. Split by underlying fields

Unassigned, affected week, session scope:

- `acme_news / newsletter`: 2,100 sessions, 18 purchases. Landing page + query string carries `utm_source=acme_news&utm_medium=newsletter`, so it came from UTMs. Taxonomy branch, cause A.
- `chatgpt / ai`: 350 sessions, 6 purchases. Example Co tagged the links in its ChatGPT gift guide this way; the landing URLs carry the UTMs. The visits came from the partner's placement, so this is cause A with an AI context note, not cause J: the source should name the publisher, not the assistant.
- `(not set) / (not set)`: 2,350 sessions, 386 purchases. No `utm_` parameters on the landing URLs. Collection branch.

## 4. Cause tree on the collection branch

QC for 2026-09-21 to 09-29 and 2026-08-31 to 09-08: every day present, the one web stream present, no excluded events. Acme runs advanced consent mode and behavioural modelling is not active, so each day's `events_not_denied` was compared with GA4's Event count: within 1% on every day. `events_denied` was recorded separately at 7% to 9% of the raw export, which is why raw `events` sat above the API figure. The export can be used as evidence.

Q4a for the affected week: denied rows carry a `user_pseudo_id`, a new one per session, and a `ga_session_id`, so Q4b can judge the `No` state.

Q1 for the `(not set)` sessions:

- 1,970 sessions on `www.example.com` with `has_session_start = false`, `has_page_view = true`, first event `page_view`. Q4b puts 1,930 of them in sessions whose first and last consent state is `Yes`, and the share of `Yes` sessions without `session_start` rose from 0.4% in the baseline week to 4.1%. The `No` share did not move. That is the signature of `default` used where `update` belongs. Tag Assistant on the new CMP version shows `gtag('consent', 'default', ...)` called again when the visitor accepts. Cause D, sequence error. 6 purchases.
- 380 sessions with `has_session_start = false`, `has_page_view = false`, first event `purchase`, no hostname. Landing page `(not set)` for these.

Q0 shows the backend's session IDs under `ga_session_id` in `int_value`, so the one-key queries apply. Q3 for `purchase`, affected week:

- Rows sent from a page: 1,090 events, 1,090 orders, 1,012 distinct pseudo IDs (0.93 IDs per order).
- Pageless rows: 380 events, 380 orders, 1 distinct pseudo ID (0.003 IDs per order), 380 with a session ID, 0 joined to a browser session, 1 distinct session pair.
- The backend change on 09-16 hard-coded one client ID and generated a new session ID from the order time. Each order therefore created its own session with no `session_start` and no page. Cause E.

Ruled out, with evidence:

- B: published newsletter links, real clicks through the email platform's wrapper and the CMP keep all UTMs to the landing URL. No missing URL parameter diagnostic.
- C: Google tag is on Initialization; consent default fires before it on Consent Initialization.
- F: Q5a shows `pay.example.net` as the session source of about 140 sessions in both weeks, credited to Referral, not Unassigned. Q5b shows return `page_view` events from `pay.example.net` without `ignore_referrer`, and an exploration shows 22 purchases a week with event-scoped Source / medium `pay.example.net / referral`. Logged as a separate finding (unwanted referral candidate), not part of this spike. The unfiltered Q5b found 3 bank authentication hosts a month, so listing them is enough; no `ignore_referrer` draft.
- G: Q2 shows no sessionless web events. Denied rows carry session IDs (Q4a), so nothing in `No` is sessionless. The backend events carry session IDs but no `session_start`, which is cause E.
- H: Landing page `(not set)` is fully explained by the 380 backend sessions.
- I: campaign present on all UTM pairs in Q7.
- J: no assistant host appears in Referral beyond those GA4 already labels `ai-assistant`; the `chatgpt / ai` row is the partner's tagging (cause A).
- K: Direct sessions flat across the two weeks; Q9 shows no events from hostnames Acme does not own.

## 5. Fix order and drafts

Tiers first, then purchases affected within a tier.

1. E, tier 2 (380 purchases a week): the checkout page reads the client ID and session ID from the Google tag and stores them on the order; the backend sends them with the purchase. Orders paid more than 24 hours after the session started (bank transfers) are sent with the stored client ID and no session ID, and are documented as expected sessionless events. The interim option of pausing the backend purchases was rejected: Unassigned would fall and so would purchases. The ticket notes that Google recommends the Data Manager API for a full sender rebuild.
2. D, tier 2 (6 purchases, 1,970 sessions a week): CMP configuration change so acceptance calls `update`. Draft to the CMP owner; privacy owner confirms the consent model is unchanged.
3. F, tier 4 (separate finding, 22 purchases a week): `pay.example.net` drafted as an unwanted referral for the stream owner.
4. A, tier 5, newsletter (18 purchases a week): template changed to `acme_news / email` from the 2026-10-01 send. It is a link-template-only change touching more purchases than D, so it shipped alongside the tier 2 releases rather than after them. History: a custom channel group "Reporting channels" copies the default channels and adds one condition to Email: Source exactly matches `acme_news` AND Medium exactly matches `newsletter`. No rule touches `(not set)`. Recorded in `decisions.md` with the default group kept for comparison.
5. A, tier 5, partner (6 purchases a week): Example Co retags its links as `example_co / referral`, with `utm_campaign=partner_gift_guide` and `utm_content=chatgpt_app`. The source names the publisher that sent the visit, and the ChatGPT placement stays visible in content. No AI channel was added to "Reporting channels". If one is added later, it uses the two-condition rule in [channel-rules.md](channel-rules.md#ai-assistant-channel-in-a-custom-group), which `example_co / referral` does not match. The 350 historical sessions a week are annotated, not reclassified.

Each item went to its owner as a draft and was approved before release. Releases: 2026-09-30 (backend, CMP) and 2026-10-01 (newsletter, partner links, unwanted referral).

## 6. Confirmation

Before any run, Acme's analyst read the data filters: an internal traffic filter on the office IP range, Active, and a developer traffic filter, Active. So the sequence checks were debug runs in Tag Assistant, and the confirmation runs used a normal browser profile on a mobile network outside the office range, with no Tag Assistant connection. Rows that buy were run by Acme's QA lead with written approval, on an agreed test product. For each run the client ID was read on the landing page and the UTC time of the first click recorded. The transaction IDs were refunded and excluded downstream by `transaction_id`.

- T1, accept banner, land from a tagged newsletter link, buy by card: Q8 for the recorded client ID shows one `session_start`, `page_view` first, session `acme_news / email`, and the purchase in the same session with the same pseudo ID.
- T2, deny banner, same path: Q8 by time window, landing URL and `analytics_storage = 'No'` finds cookieless events including the browser `purchase`, with `collected_traffic_source` `acme_news / email` on the landing `page_view`. Their `user_pseudo_id` differs from T1's and does not appear in the tester's next session. The backend does not send `purchase` for denied orders. Documented as consented-away.
- T5, saved acceptance, pay on `pay.example.net` and return within 30 minutes: no new `session_start` (as expected), the return `page_view` carries `ignore_referrer`, and the purchase's event-scoped Source / medium is `acme_news / email`.

Completed week 2026-10-06 to 10-12 against the affected week, with QC passing for those days:

- Unassigned sessions 4,800 to 1,150 (baseline 1,200). Unassigned purchases 410 to 34.
- Total purchases 1,470 to 1,480. Purchases held.
- Total sessions in the UI 60,900 to 60,500. UI session totals are approximate, and a 400-session change is under 1% of the total, so the analyst counted exact sessions in the export (distinct `user_pseudo_id` plus `ga_session_id`, same days, all consent states): a fall of 388. Over the same weeks, Q1 sessions whose first event is a pageless `purchase` fell from 380 to 0. The drop is the sessions the backend had been creating, so it is the expected effect of the fix, not data loss.
- Q3 pageless rows: 392 events, 392 orders, 371 distinct pseudo IDs, 352 with a session ID, 352 joined to a browser session, 11 distinct session pairs. The 40 without a session ID are late bank-transfer orders.
- Q1: sessions without `session_start` on `www.example.com` fell from 1,970 to 45; Q4b's `Yes` share without `session_start` is back to 0.4%.
- Q5b: return events from `pay.example.net` without `ignore_referrer` fell to zero.

What the record says about history: weeks from 2026-09-15 to 2026-09-29 keep inflated Unassigned and about 380 extra sessions a week. Collection fixes do not rewrite them; the custom group only corrects the newsletter pair. The incident record was saved in the team's analytics folder and a dated summary added to `decisions.md` after approval.
