← back to The Ai Factory

GA_CONSOLIDATION.md

76 lines

# GA4 Fleet Consolidation — Process Plan

**Started:** 2026-04-30
**Owner:** Steve
**Process .md per `feedback_suggest_process_md.md`**

---

## Goal

Bring every GA4 property visible to `steve@designerwallcoverings.com` under **one** GA account.

## Locked decisions

| # | Decision | Value | Why |
|---|---|---|---|
| Q1 | Move vs recreate | **recreate** | Fast, scriptable. Lose history; new G-IDs everywhere. |
| Q2 | Scope | **literal — all properties, business + personal** | Steve: "yes all under steve@dw" (2026-04-30) |
| Q3 | Target account | **`371997142` (IntelligentHome)** *(working assumption — flag if wrong)* | Default from URL Steve shared; renameable later |
| Q4 | Inventory auth | **oneshot-adc** | Env-var-scoped to a single audit run; no `_auth.py` change. SA-per-account is too slow for the audit's purpose. |

Decisions still owed before **Phase 4** (the destructive phase):
- **Q3 confirm/replace** — is IntelligentHome really where everything should land, or should we create a fresh "Steve Personal" account?
- **DW + studentdebtcrisis carve-outs** — analytics SKILL.md operating rule #1 already excludes these from injection. For *consolidation*, treat any DW-Shopify or SDCC GA property as DO-NOT-MOVE on sight.
- **Cleanup policy for OLD properties** in source accounts after recreate: delete / archive / leave-dormant?

## Phases

### Phase 1 — Permission *(in progress)*
- Inventory uses **oneshot ADC** (Steve's identity) → no per-account SA grants needed.
- Service account stays on the bench unless we hit a write where SA scoping is preferred.

### Phase 2 — Inventory *(blocked on Phase 1)*
- `GA_USE_USER_AUTH=1 python3 ~/.claude/skills/analytics/scripts/audit_fleet.py`
- Output: full grouped JSON of every account / property / web stream visible.

### Phase 3 — Plan *(after inventory)*
- Build a per-property table in this file: `KEEP_IN_PLACE / RECREATE_IN_TARGET / ARCHIVE / MERGE`.
- Pre-flag DW-Shopify GA + SDCC + any client/partner properties as `KEEP_IN_PLACE`.
- Steve reviews the table line-by-line before Phase 4.

### Phase 4 — Execute (recreate path) *(human-gated, batched)*
- For each `RECREATE_IN_TARGET` property:
  1. Use Admin API (`create_property.py`) to create new property in account `371997142`.
  2. Add web data stream with same `default_uri` as source.
  3. Capture new `G-XXXXXXXX` measurement ID into a recreated→source mapping JSON.
- **Never auto-execute the full batch.** Steve approves each batch (5–10 properties) explicitly.

### Phase 5 — Verify
- Re-run `audit_fleet.py`.
- Diff against the Phase 3 plan: every `RECREATE_IN_TARGET` property must now exist in target account; sources untouched.

### Phase 6 — Re-tag *(mandatory because we recreated)*
- For every recreated property, find the live site(s) using the OLD `G-XXXXXXXX`.
- Use `inject_gtag.py --measurement-id <new-G-ID>` to push the new ID.
- Respect SKILL.md operating rule #5: **never auto-replace UA-XXXXX tags.** Flag, don't replace.

### Phase 7 — Cleanup *(human-gated)*
- Source accounts now have stranded properties + a paper trail of empty accounts.
- For each source account: `KEEP / DELETE_PROPERTY / DELETE_ACCOUNT`. Steve approves.

## Standing-rules check (from /best-practices, 2026-04-30)

- ✅ `feedback_suggest_process_md.md` — this file
- ✅ `feedback_ask_before_doing.md` — Phase 3 + Phase 4 + Phase 7 are explicitly Steve-gated, not auto-executed
- ✅ `feedback_dns_donotouch.md` (analytics SKILL.md rule #1) — DW-Shopify GA + SDCC carved out as `KEEP_IN_PLACE`
- ✅ Auth scope — ADC is env-var-only on a single read-only command, not a default change
- ✅ `feedback_no_cloud_agents.md` — all of this runs locally on Mac Studio 2

## Sharp edges to remember

- **Recreate = new G-IDs.** Every site needs gtag re-deployed. If any site is hardcoded with a measurement ID we can't reach, it's stranded.
- **Recreate ≠ delete.** Old properties stay in source accounts until Phase 7. During the gap, both old and new emit, which can double-count if any site still has the old gtag while the new one is also injected. Sequence: create new → switch gtag → confirm new is receiving → only then delete old.
- **GA Admin API rate limits** are tight (10 writes/sec per project). Batch sizes of 5–10 with 90s gaps between batches is the safe rhythm.
- **Search Console / Ads / BigQuery export links** on any source property break on recreate. Inventory must capture which properties have these.