[object Object]

← back to Ga Allsites

GA4 cleanup: deleted Momentum DW property; goodquestion.ai + nosara blocked by SA permission on APPS account 371997142

1ad646331482694ace24fddde97e812742f19cc2 · 2026-08-17 16:33:24 -0700 · Steve Abrams

Files touched

Diff

commit 1ad646331482694ace24fddde97e812742f19cc2
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 17 16:33:24 2026 -0700

    GA4 cleanup: deleted Momentum DW property; goodquestion.ai + nosara blocked by SA permission on APPS account 371997142
---
 delete_orphan_ga4.py  | 18 ++++++++++++++++++
 gtm/rollout-status.md | 11 +++++++++++
 2 files changed, 29 insertions(+)

diff --git a/delete_orphan_ga4.py b/delete_orphan_ga4.py
new file mode 100644
index 0000000..d667ffc
--- /dev/null
+++ b/delete_orphan_ga4.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+"""Delete the 3 GA4 properties Steve approved (soft-delete, recoverable ~35 days)."""
+import pathlib
+from google.analytics.admin import AnalyticsAdminServiceClient
+KEY = pathlib.Path.home()/".config"/"ga-analytics-agent"/"service-account.json"
+TARGETS = [
+ ("G-9K93LH6GH1", "properties/548357651", "Momentum DW (momentum.designerwallcoverings.com)"),
+ ("G-QG3DGNYWZX", "properties/535741032", "goodquestion (goodquestion.ai)"),
+ ("G-JZRGWSY1F6", "properties/535735055", "nosarabeachfrontrentals (nosarabeachfrontrentals.com)"),
+]
+c = AnalyticsAdminServiceClient.from_service_account_file(str(KEY))
+for mid, prop, label in TARGETS:
+    try:
+        r = c.delete_property(name=prop)   # soft-delete -> Trash, recoverable ~35d
+        state = getattr(r, "state", None)
+        print(f"  ✅ DELETED {prop}  [{mid}]  {label}  (state={state})")
+    except Exception as e:
+        print(f"  ❌ FAILED  {prop}  [{mid}]  {label}: {type(e).__name__}: {str(e)[:120]}")
diff --git a/gtm/rollout-status.md b/gtm/rollout-status.md
index 0d4ec78..adb6f83 100644
--- a/gtm/rollout-status.md
+++ b/gtm/rollout-status.md
@@ -179,3 +179,14 @@ The only true fact stands: the BARE domains momentumdw.com/goodquestion.com aren
 actually measures them. not-owned-exclusions.json corrected accordingly.
 LESSON: verify a GA4 property by its data-stream URI, never by its display NAME. The DOMAIN_MATCH dry-run
 gate is what prevented a 3-property destructive delete.
+
+## CYCLE 15 — Steve approved deleting all 3; 1 done, 2 blocked by SA permission
+Steve chose "delete all 3" (with full disclosure it removes live analytics; soft-delete = 35d recoverable).
+Result:
+  - ✅ DELETED: Momentum DW (properties/548357651, acct steveabramsdesigns.com) — SA has Editor there.
+  - ❌ 403 PermissionDenied: goodquestion (properties/535741032) + nosarabeachfrontrentals (properties/535735055)
+    — both in the "Steve Abrams APPS" account (371997142) where the SA lacks delete rights.
+TO FINISH THE OTHER 2, either:
+  (a) Steve grants analytics-agent@dw-ga4-attribution.iam.gserviceaccount.com the "Editor" role on GA4 account
+      371997142 (Admin > Account Access Management), then re-run delete_orphan_ga4.py; OR
+  (b) Steve deletes them by hand in GA4 UI (Admin > Property Settings > Move to Trash Can).

← 34f211e ABORT orphan-GA4 deletion: dry-run proved all 3 are legit (D  ·  back to Ga Allsites  ·  chore: lint (14 autofix) + light refactor of session GA4 scr 277b943 →