← back to Domain Landings
TK-10631: backfill 84 existing GA4 measurement IDs into domains.json + corrected create script
c4037fee6675ffab07124a762ecc84a0a9f9ea5a · 2026-09-03 14:25:03 -0700 · Steve Abrams
Live re-verification corrected the scope from 150 to 94 real targets, then a
cross-account stream index showed 84 of those 94 ALREADY have a purpose-built
GA4 property in accounts/15714274 - they were simply never wired into
data/domains.json. Only 10 domains genuinely need a new property.
Also fixes two defects in the previously staged create_all_ga4.py:
- scope: targeted 150 domains, of which 20 already served a gtag and 29 are
not landers at all (28 serve the shared Trade Lines page)
- dedupe: indexed the APPS account only, so 19 of those 20 (which live in
accounts/15714274) would NOT have deduped -> ~19 duplicate properties,
including duplicates of the do-not-touch Shopify tag G-53F1QBZSG0
Local + reversible: no Google write, no deploy. Read-back verified.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NeANPg68rvqrsCZidci85
Files touched
M data/domains.jsonA ops/tk10631/backfill_existing_ga4.pyA ops/tk10631/create_verified_ga4.pyA ops/tk10631/live_classification.jsonA ops/tk10631/verified_targets.txt
Diff
commit c4037fee6675ffab07124a762ecc84a0a9f9ea5a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 3 14:25:03 2026 -0700
TK-10631: backfill 84 existing GA4 measurement IDs into domains.json + corrected create script
Live re-verification corrected the scope from 150 to 94 real targets, then a
cross-account stream index showed 84 of those 94 ALREADY have a purpose-built
GA4 property in accounts/15714274 - they were simply never wired into
data/domains.json. Only 10 domains genuinely need a new property.
Also fixes two defects in the previously staged create_all_ga4.py:
- scope: targeted 150 domains, of which 20 already served a gtag and 29 are
not landers at all (28 serve the shared Trade Lines page)
- dedupe: indexed the APPS account only, so 19 of those 20 (which live in
accounts/15714274) would NOT have deduped -> ~19 duplicate properties,
including duplicates of the do-not-touch Shopify tag G-53F1QBZSG0
Local + reversible: no Google write, no deploy. Read-back verified.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NeANPg68rvqrsCZidci85
---
data/domains.json | 168 +++++++++++++++----------------
ops/tk10631/backfill_existing_ga4.py | 70 +++++++++++++
ops/tk10631/create_verified_ga4.py | 131 ++++++++++++++++++++++++
ops/tk10631/live_classification.json | 188 +++++++++++++++++++++++++++++++++++
ops/tk10631/verified_targets.txt | 94 ++++++++++++++++++
5 files changed, 567 insertions(+), 84 deletions(-)
diff --git a/data/domains.json b/data/domains.json
index 69ac7d5..9b8adb0 100644
--- a/data/domains.json
+++ b/data/domains.json
@@ -82,7 +82,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-MMQ89WC0RD"
},
"aaatreetrimming.com": {
"domain": "aaatreetrimming.com",
@@ -99,7 +99,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-WJ63B4DRQY"
},
"abramsatlas.com": {
"domain": "abramsatlas.com",
@@ -133,7 +133,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-1WJX3YBBMC"
},
"abramsdirectory.com": {
"domain": "abramsdirectory.com",
@@ -150,7 +150,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-4LX3PT6N3B"
},
"abramsguide.com": {
"domain": "abramsguide.com",
@@ -167,7 +167,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-6MHT7SS1HX"
},
"abramsindex.com": {
"domain": "abramsindex.com",
@@ -184,7 +184,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-NPTG2HW53E"
},
"abramsindustries.com": {
"domain": "abramsindustries.com",
@@ -201,7 +201,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-DW2XSEK295"
},
"abramsintel.com": {
"domain": "abramsintel.com",
@@ -235,7 +235,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-0EGWNS9JSP"
},
"abramslive.com": {
"domain": "abramslive.com",
@@ -252,7 +252,7 @@
"bg": "#1a1a1f",
"accent": "#e0533d"
},
- "ga4": ""
+ "ga4": "G-6X8KH5Y78Y"
},
"abramslocal.com": {
"domain": "abramslocal.com",
@@ -269,7 +269,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-9FTX49GJ31"
},
"abramsmaps.com": {
"domain": "abramsmaps.com",
@@ -286,7 +286,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-7Q5TJ7L9VR"
},
"abramsmarkets.com": {
"domain": "abramsmarkets.com",
@@ -303,7 +303,7 @@
"bg": "#10233b",
"accent": "#4aa3df"
},
- "ga4": ""
+ "ga4": "G-ZK86YBVNYJ"
},
"abramsos.com": {
"domain": "abramsos.com",
@@ -320,7 +320,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-E7S8DEQ1W8"
},
"abramsprotection.com": {
"domain": "abramsprotection.com",
@@ -337,7 +337,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-W5QJFDM15P"
},
"abramsspace.com": {
"domain": "abramsspace.com",
@@ -354,7 +354,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-SNDF85EP99"
},
"abramsterminal.com": {
"domain": "abramsterminal.com",
@@ -371,7 +371,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-VCCYZ0VQLX"
},
"abramsvc.com": {
"domain": "abramsvc.com",
@@ -388,7 +388,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-33JDJE0JGM"
},
"allnewsdaily.com": {
"domain": "allnewsdaily.com",
@@ -422,7 +422,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-17LCF8VDRB"
},
"asseeninhotels.com": {
"domain": "asseeninhotels.com",
@@ -524,7 +524,7 @@
"bg": "#141019",
"accent": "#d4af37"
},
- "ga4": ""
+ "ga4": "G-E4SWTN4VQN"
},
"bestdocumentaryfilms.com": {
"domain": "bestdocumentaryfilms.com",
@@ -541,7 +541,7 @@
"bg": "#1a1a1f",
"accent": "#e0533d"
},
- "ga4": ""
+ "ga4": "G-KJ85CT7RBQ"
},
"beverlyandhills.com": {
"domain": "beverlyandhills.com",
@@ -558,7 +558,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-39DX7RM73W"
},
"beverlyhillsbutler.com": {
"domain": "beverlyhillsbutler.com",
@@ -592,7 +592,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-EKSBQ4ELWD"
},
"beverlyhillsvideos.com": {
"domain": "beverlyhillsvideos.com",
@@ -677,7 +677,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-408Q9XG6R5"
},
"boulevardbutler.com": {
"domain": "boulevardbutler.com",
@@ -711,7 +711,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-SSTTLGEP2D"
},
"cannabisofthemonthclub.com": {
"domain": "cannabisofthemonthclub.com",
@@ -728,7 +728,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-FFHGX6NSE2"
},
"carmelpaints.com": {
"domain": "carmelpaints.com",
@@ -745,7 +745,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-6WC40774MR"
},
"carmelriverwater.com": {
"domain": "carmelriverwater.com",
@@ -762,7 +762,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-X6EYW2DSXW"
},
"carmelvalleywater.com": {
"domain": "carmelvalleywater.com",
@@ -779,7 +779,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-G0E45H1NMT"
},
"cfafabrics.com": {
"domain": "cfafabrics.com",
@@ -847,7 +847,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-9WE8G182EL"
},
"customdigitalwallcoverings.com": {
"domain": "customdigitalwallcoverings.com",
@@ -864,7 +864,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-B63YBSRT2R"
},
"customdigitalwalls.com": {
"domain": "customdigitalwalls.com",
@@ -881,7 +881,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-0JV4GNDYNT"
},
"cypresawards.com": {
"domain": "cypresawards.com",
@@ -915,7 +915,7 @@
"bg": "#141019",
"accent": "#d4af37"
},
- "ga4": ""
+ "ga4": "G-ZG89R97XQZ"
},
"designerlaboratory.com": {
"domain": "designerlaboratory.com",
@@ -966,7 +966,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-8Y6R7114P0"
},
"designerswallcovering.com": {
"domain": "designerswallcovering.com",
@@ -1017,7 +1017,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-JVMJRNGTSM"
},
"designerwallpaints.com": {
"domain": "designerwallpaints.com",
@@ -1034,7 +1034,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-M5B29GMETZ"
},
"designerwalltiles.com": {
"domain": "designerwalltiles.com",
@@ -1051,7 +1051,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-NK2K6WYHPB"
},
"designtradereps.com": {
"domain": "designtradereps.com",
@@ -1068,7 +1068,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-YQT4F17LZY"
},
"designtradesalesreps.com": {
"domain": "designtradesalesreps.com",
@@ -1085,7 +1085,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-CK2NG90DQ5"
},
"designwallcoverings.com": {
"domain": "designwallcoverings.com",
@@ -1119,7 +1119,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-DC8LPETH9G"
},
"dsgntv.com": {
"domain": "dsgntv.com",
@@ -1170,7 +1170,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-57CVXWRWBS"
},
"etciemurals.com": {
"domain": "etciemurals.com",
@@ -1204,7 +1204,7 @@
"bg": "#1a1a1f",
"accent": "#e0533d"
},
- "ga4": ""
+ "ga4": "G-85QBEK40VQ"
},
"fentucci.com": {
"domain": "fentucci.com",
@@ -1238,7 +1238,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-LNRK2L0W8Z"
},
"fireratedwallcovering.com": {
"domain": "fireratedwallcovering.com",
@@ -1306,7 +1306,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-ZNQR8RHDFG"
},
"handscreenedwallpaper.com": {
"domain": "handscreenedwallpaper.com",
@@ -1323,7 +1323,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-9CLVL8CYR6"
},
"hempofthemonthclub.com": {
"domain": "hempofthemonthclub.com",
@@ -1340,7 +1340,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-BWE061BNND"
},
"herbsmadeinchina.com": {
"domain": "herbsmadeinchina.com",
@@ -1357,7 +1357,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-0G2WC89BPX"
},
"hospitalityfabrics.net": {
"domain": "hospitalityfabrics.net",
@@ -1374,7 +1374,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-9G1J183KR1"
},
"hospitalitymurals.com": {
"domain": "hospitalitymurals.com",
@@ -1391,7 +1391,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-JRXCBCQFPT"
},
"hospitalitysalesagency.com": {
"domain": "hospitalitysalesagency.com",
@@ -1425,7 +1425,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-8NGN60T23R"
},
"hospitalitysalesreps.com": {
"domain": "hospitalitysalesreps.com",
@@ -1442,7 +1442,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-7VWZCRW3BC"
},
"hospitalitywalls.com": {
"domain": "hospitalitywalls.com",
@@ -1459,7 +1459,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-B8Z1G4X5QS"
},
"inflationfears.com": {
"domain": "inflationfears.com",
@@ -1476,7 +1476,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-M5GM2GVBFN"
},
"interiordesignershowroom.com": {
"domain": "interiordesignershowroom.com",
@@ -1510,7 +1510,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-DQZ5QMHZZK"
},
"joshdultz.com": {
"domain": "joshdultz.com",
@@ -1561,7 +1561,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-Z1M3MMGVXL"
},
"latke.ai": {
"domain": "latke.ai",
@@ -1578,7 +1578,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-83EBGEH9WG"
},
"luxurymurals.com": {
"domain": "luxurymurals.com",
@@ -1595,7 +1595,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-9CLEWR9CNT"
},
"malibuwallpaper.com": {
"domain": "malibuwallpaper.com",
@@ -1629,7 +1629,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-XR5TWZ04G8"
},
"marijuanaofthemonthclub.com": {
"domain": "marijuanaofthemonthclub.com",
@@ -1646,7 +1646,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-2QCK4JH2CQ"
},
"mohairvelvet.com": {
"domain": "mohairvelvet.com",
@@ -1663,7 +1663,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-PT81YV9WMX"
},
"montereywallpaper.com": {
"domain": "montereywallpaper.com",
@@ -1697,7 +1697,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-9Y0ZCJB68K"
},
"nataliaabrams.com": {
"domain": "nataliaabrams.com",
@@ -1782,7 +1782,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-B12GFM176P"
},
"nybutler.com": {
"domain": "nybutler.com",
@@ -1799,7 +1799,7 @@
"bg": "#0e1b2a",
"accent": "#c9a24b"
},
- "ga4": ""
+ "ga4": "G-0MPWM7ZKHZ"
},
"petitionyour.com": {
"domain": "petitionyour.com",
@@ -1850,7 +1850,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-T7XLB2MTKW"
},
"printmurals.com": {
"domain": "printmurals.com",
@@ -1884,7 +1884,7 @@
"bg": "#0b1220",
"accent": "#5b8def"
},
- "ga4": ""
+ "ga4": "G-S2E865XE2H"
},
"protestdaily.com": {
"domain": "protestdaily.com",
@@ -2054,7 +2054,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-LKREDWSD73"
},
"theatrewallpaper.com": {
"domain": "theatrewallpaper.com",
@@ -2071,7 +2071,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-9E9ZN8SJ4J"
},
"thecannabisnews.com": {
"domain": "thecannabisnews.com",
@@ -2088,7 +2088,7 @@
"bg": "#1a1a1f",
"accent": "#e0533d"
},
- "ga4": ""
+ "ga4": "G-LRPHXRFWXN"
},
"thedesignerlaboratory.com": {
"domain": "thedesignerlaboratory.com",
@@ -2105,7 +2105,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-FQ5YN3YCJW"
},
"thehotelwallpaper.com": {
"domain": "thehotelwallpaper.com",
@@ -2139,7 +2139,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-8D8JPSL6ZY"
},
"thesetdecorator.com": {
"domain": "thesetdecorator.com",
@@ -2173,7 +2173,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-MGC0VC4BCZ"
},
"traditionalwhimsy.com": {
"domain": "traditionalwhimsy.com",
@@ -2207,7 +2207,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-NCLC2M3JX5"
},
"unitedstateswallpaper.com": {
"domain": "unitedstateswallpaper.com",
@@ -2241,7 +2241,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-C9RL9RF48M"
},
"urthfriendly.com": {
"domain": "urthfriendly.com",
@@ -2258,7 +2258,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-6MW411RPZW"
},
"valleybutler.com": {
"domain": "valleybutler.com",
@@ -2275,7 +2275,7 @@
"bg": "#0e1b2a",
"accent": "#c9a24b"
},
- "ga4": ""
+ "ga4": "G-ZKQYLWSQ3Q"
},
"venturacorridor.com": {
"domain": "venturacorridor.com",
@@ -2309,7 +2309,7 @@
"bg": "#1a1a1f",
"accent": "#e0533d"
},
- "ga4": ""
+ "ga4": "G-V3Q1Z97W6E"
},
"venturaeats.com": {
"domain": "venturaeats.com",
@@ -2326,7 +2326,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-Y0NPLMY7YT"
},
"vintagebh.com": {
"domain": "vintagebh.com",
@@ -2343,7 +2343,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-2D3MQ4CHJS"
},
"wallpaperexports.com": {
"domain": "wallpaperexports.com",
@@ -2394,7 +2394,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-2D236ML7NV"
},
"wallpaperny.com": {
"domain": "wallpaperny.com",
@@ -2428,7 +2428,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-YF0E8J7LCS"
},
"wallpaperpurchasing.com": {
"domain": "wallpaperpurchasing.com",
@@ -2479,7 +2479,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-6MRGWKY7EF"
},
"wc01wallcoverings.com": {
"domain": "wc01wallcoverings.com",
@@ -2513,7 +2513,7 @@
"bg": "#1c1614",
"accent": "#b8865f"
},
- "ga4": ""
+ "ga4": "G-8CFEY91Z5M"
},
"weedofthemonthclub.com": {
"domain": "weedofthemonthclub.com",
@@ -2530,7 +2530,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-PNJW40XF0M"
},
"wintergamesrentals.com": {
"domain": "wintergamesrentals.com",
@@ -2547,7 +2547,7 @@
"bg": "#0f1e17",
"accent": "#7bb274"
},
- "ga4": ""
+ "ga4": "G-EN67FKGK32"
},
"zayde.ai": {
"domain": "zayde.ai",
@@ -2564,7 +2564,7 @@
"bg": "#15171c",
"accent": "#9aa7b4"
},
- "ga4": ""
+ "ga4": "G-1EESWFBXTD"
},
"67calc.com": {
"domain": "67calc.com",
diff --git a/ops/tk10631/backfill_existing_ga4.py b/ops/tk10631/backfill_existing_ga4.py
new file mode 100644
index 0000000..5999d60
--- /dev/null
+++ b/ops/tk10631/backfill_existing_ga4.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+"""TK-10631: backfill data/domains.json with GA4 measurement IDs for domains
+that ALREADY have a purpose-built GA4 property (stream default_uri host ==
+the domain). No Google write, no deploy — local, reversible via git.
+
+Only fills domains that are (a) in the verified live-target list, (b) currently
+have an empty `ga4`, and (c) have exactly one existing stream keyed to that host.
+"""
+import argparse, json
+from urllib.parse import urlparse
+from google.oauth2 import service_account
+from google.analytics.admin import AnalyticsAdminServiceClient
+
+KEY = "/Users/macstudio3/.config/ga-analytics-agent/service-account.json"
+ap = argparse.ArgumentParser()
+ap.add_argument("--targets", required=True)
+ap.add_argument("--apply", action="store_true", help="write the file (default: preview)")
+a = ap.parse_args()
+
+creds = service_account.Credentials.from_service_account_file(
+ KEY, scopes=["https://www.googleapis.com/auth/analytics.readonly"])
+c = AnalyticsAdminServiceClient(credentials=creds)
+
+idx = {}
+for s in c.list_account_summaries():
+ for p in s.property_summaries:
+ try:
+ for st in c.list_data_streams(parent=p.property):
+ w = st.web_stream_data
+ if w and w.default_uri and w.measurement_id:
+ h = urlparse(w.default_uri).netloc.lower()
+ h = h[4:] if h.startswith("www.") else h
+ if h:
+ idx.setdefault(h, (s.account, p.property, w.measurement_id))
+ except Exception:
+ pass
+
+cfg = json.load(open("data/domains.json"))
+targets = [d.strip() for d in open(a.targets) if d.strip()]
+fills, missing = {}, []
+for d in targets:
+ if cfg.get(d, {}).get("ga4"):
+ continue
+ if d in idx:
+ fills[d] = idx[d]
+ else:
+ missing.append(d)
+
+for d, (acct, prop, mid) in sorted(fills.items()):
+ print(f" {d:34s} <- {mid:15s} {prop} ({acct})")
+print(f"\n{len(fills)} to fill, {len(missing)} have no existing property "
+ f"(need creation): {missing}")
+
+if not a.apply:
+ print("\nPREVIEW ONLY — pass --apply to write data/domains.json")
+ raise SystemExit(0)
+
+for d, (_, _, mid) in fills.items():
+ cfg[d]["ga4"] = mid
+json.dump(cfg, open("data/domains.json", "w"), indent=2)
+open("data/domains.json", "a").write("\n")
+
+# read-back verify
+rb = json.load(open("data/domains.json"))
+bad = [d for d, (_, _, mid) in fills.items() if rb[d].get("ga4") != mid]
+assert not bad, f"read-back MISMATCH: {bad}"
+assert len(rb) == len(cfg), "domain count changed!"
+print(f"\nOK: wrote + read-back-verified {len(fills)} measurement IDs. "
+ f"{sum(1 for v in rb.values() if v.get('ga4'))}/{len(rb)} domains now tagged.")
+print("NOT deployed — customer-facing deploy remains gated.")
diff --git a/ops/tk10631/create_verified_ga4.py b/ops/tk10631/create_verified_ga4.py
new file mode 100644
index 0000000..7fbe0e2
--- /dev/null
+++ b/ops/tk10631/create_verified_ga4.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+"""TK-10631 (corrected scope, 2026-09-03): create GA4 properties ONLY for the
+domains that live verification proved actually need one.
+
+Supersedes create_all_ga4.py, which had TWO defects found by live re-verification:
+
+ 1. SCOPE — it targeted all 150 domains in data/domains.json lacking a `ga4`
+ field. Live sweep showed only 94 of those are untagged live landers.
+ 20 already serve a gtag, 29 are not landers at all (28 serve the shared
+ "Trade Lines" DW page), 7 are 401/403/TLS-broken.
+
+ 2. DEDUPE — it indexed existing data streams in the APPS account ONLY
+ (`if s.account != APPS_ACCOUNT: continue`). 19 of the 20 already-tagged
+ domains have their property in accounts/15714274 (DesignerWallcoverings.com)
+ or accounts/136095445, so an APPS-only index would NOT have deduped them
+ and the run would have minted ~19 duplicate properties — including
+ duplicates for domains that 301 to designerwallcoverings.com and inherit
+ the do-not-touch Shopify tag G-53F1QBZSG0.
+
+This version indexes EVERY account the service account can see, and drives from
+a verified target file rather than from the absence of a `ga4` key.
+
+GATED: create_property is an external Google-account write. Run only on
+explicit approval. Creates properties ONLY; does NOT touch data/domains.json
+and does NOT deploy anything (both remain separately gated).
+
+Usage:
+ python3 ops/tk10631/create_verified_ga4.py --targets ops/tk10631/verified_targets.txt --dry-run
+ python3 ops/tk10631/create_verified_ga4.py --targets ops/tk10631/verified_targets.txt --apply
+"""
+import argparse, json, sys, time
+from urllib.parse import urlparse
+
+from google.oauth2 import service_account
+from google.analytics.admin import AnalyticsAdminServiceClient
+from google.analytics.admin_v1alpha.types import Property, DataStream
+
+KEY = "/Users/macstudio3/.config/ga-analytics-agent/service-account.json"
+APPS_ACCOUNT = "accounts/371997142" # Steve Abrams APPS — where new props are created
+SCOPES = ["https://www.googleapis.com/auth/analytics.edit",
+ "https://www.googleapis.com/auth/analytics.readonly"]
+DOMAINS_JSON = "data/domains.json"
+
+ap = argparse.ArgumentParser()
+ap.add_argument("--targets", required=True, help="newline-delimited verified target domains")
+ap.add_argument("--out", default="/tmp/tk10631_verified_results.json")
+g = ap.add_mutually_exclusive_group(required=True)
+g.add_argument("--dry-run", action="store_true", help="index + plan only, no writes")
+g.add_argument("--apply", action="store_true", help="perform the gated create")
+args = ap.parse_args()
+
+cfg = json.load(open(DOMAINS_JSON))
+targets = [d.strip() for d in open(args.targets) if d.strip() and not d.startswith("#")]
+unknown = [d for d in targets if d not in cfg]
+if unknown:
+ sys.exit(f"ABORT: {len(unknown)} target(s) not in {DOMAINS_JSON}: {unknown[:5]}")
+print(f"{len(targets)} verified targets (of {len(cfg)} domains in {DOMAINS_JSON})")
+
+creds = service_account.Credentials.from_service_account_file(KEY, scopes=SCOPES)
+client = AnalyticsAdminServiceClient(credentials=creds)
+
+# --- dedupe index across EVERY visible account (fix #2) ---
+print("Indexing existing web streams across ALL visible accounts...")
+existing_by_domain, n_props, n_accts = {}, 0, set()
+for s in client.list_account_summaries():
+ n_accts.add(s.account)
+ for p in s.property_summaries:
+ n_props += 1
+ try:
+ for st in client.list_data_streams(parent=p.property):
+ w = st.web_stream_data
+ if w and w.default_uri and w.measurement_id:
+ host = urlparse(w.default_uri).netloc.lower()
+ host = host[4:] if host.startswith("www.") else host
+ if host:
+ existing_by_domain.setdefault(host, {
+ "account": s.account, "property": p.property,
+ "measurement_id": w.measurement_id})
+ except Exception as e:
+ print(f" WARN: streams unreadable for {p.property}: {e}", file=sys.stderr)
+print(f"Indexed {n_props} properties across {len(n_accts)} accounts "
+ f"-> {len(existing_by_domain)} domain->stream mappings")
+
+todo = [d for d in targets if d not in existing_by_domain]
+skip = [d for d in targets if d in existing_by_domain]
+if skip:
+ print(f"\nSKIP (already have a stream somewhere) — {len(skip)}:")
+ for d in skip:
+ e = existing_by_domain[d]
+ print(f" {d:34s} {e['measurement_id']:15s} {e['account']}")
+print(f"\nWOULD CREATE {len(todo)} propert{'y' if len(todo)==1 else 'ies'} in {APPS_ACCOUNT}")
+
+if args.dry_run:
+ json.dump({"targets": targets, "would_create": todo,
+ "skip_existing": {d: existing_by_domain[d] for d in skip}},
+ open(args.out, "w"), indent=2)
+ print(f"\nDRY RUN — no writes performed. Plan written to {args.out}")
+ sys.exit(0)
+
+results = {d: {**existing_by_domain[d], "created": False} for d in skip}
+created = 0
+for i, domain in enumerate(todo, 1):
+ name = cfg[domain].get("title") or domain
+ try:
+ prop = Property(parent=APPS_ACCOUNT,
+ display_name=f"{name} ({domain})"[:100],
+ time_zone="America/Los_Angeles", currency_code="USD",
+ industry_category="SHOPPING")
+ pn = client.create_property(property=prop).name
+ st = client.create_data_stream(parent=pn, data_stream=DataStream(
+ type_=DataStream.DataStreamType.WEB_DATA_STREAM,
+ display_name=f"{name} Web"[:100],
+ web_stream_data=DataStream.WebStreamData(default_uri=f"https://{domain}")))
+ mid = st.web_stream_data.measurement_id
+ ok = any(s2.web_stream_data and s2.web_stream_data.measurement_id == mid
+ and domain in s2.web_stream_data.default_uri and mid.startswith("G-")
+ for s2 in client.list_data_streams(parent=pn))
+ print(f"[{i}/{len(todo)}] CREATED {domain:34s} {pn} mid={mid} readback_ok={ok}")
+ results[domain] = {"account": APPS_ACCOUNT, "property": pn,
+ "measurement_id": mid, "created": True, "readback_ok": ok}
+ created += 1
+ except Exception as e:
+ print(f"[{i}/{len(todo)}] FAILED {domain:34s} {e}", file=sys.stderr)
+ results[domain] = {"error": str(e), "created": False}
+ time.sleep(0.6)
+
+json.dump(results, open(args.out, "w"), indent=2)
+have = sum(1 for r in results.values() if r.get("measurement_id"))
+print(f"\nSUMMARY: {have}/{len(targets)} have a measurement_id ({created} newly created).")
+print(f"Results -> {args.out}")
+print("NOTE: data/domains.json NOT modified and nothing deployed — both remain gated.")
diff --git a/ops/tk10631/live_classification.json b/ops/tk10631/live_classification.json
new file mode 100644
index 0000000..06f6210
--- /dev/null
+++ b/ops/tk10631/live_classification.json
@@ -0,0 +1,188 @@
+{
+ "true_targets": [
+ "90210rentals.com",
+ "aaatreetrimming.com",
+ "abramsatlas.com",
+ "abramscivic.com",
+ "abramsdirectory.com",
+ "abramsguide.com",
+ "abramsindex.com",
+ "abramsindustries.com",
+ "abramsintel.com",
+ "abramsintelligence.com",
+ "abramslive.com",
+ "abramslocal.com",
+ "abramsmaps.com",
+ "abramsmarkets.com",
+ "abramsos.com",
+ "abramsprotection.com",
+ "abramsspace.com",
+ "abramsterminal.com",
+ "abramsvc.com",
+ "asknonna.ai",
+ "bestactorawards.com",
+ "bestdocumentaryfilms.com",
+ "beverlyandhills.com",
+ "beverlyhillspaints.com",
+ "bleachfriendly.com",
+ "borninbh.com",
+ "bubbie.ai",
+ "cannabisofthemonthclub.com",
+ "carmelpaints.com",
+ "carmelriverwater.com",
+ "carmelvalleywater.com",
+ "commercialwalls.com",
+ "customdigitalwallcoverings.com",
+ "customdigitalwalls.com",
+ "cypresawards.org",
+ "designerschat.com",
+ "designerswallpapers.com",
+ "designerwallpaints.com",
+ "designerwalltiles.com",
+ "designtradereps.com",
+ "designtradesalesreps.com",
+ "dsgn.tv",
+ "ephedrafreeherbs.com",
+ "fauxnewslive.com",
+ "filthyrichliving.com",
+ "freethedegree.org",
+ "handmadewallpapers.com",
+ "handscreenedwallpaper.com",
+ "hempofthemonthclub.com",
+ "herbsmadeinchina.com",
+ "hospitalityfabrics.net",
+ "hospitalitymurals.com",
+ "hospitalitysalesagents.com",
+ "hospitalitysalesreps.com",
+ "hospitalitywalls.com",
+ "inflationfears.com",
+ "interiordesignreps.com",
+ "joshdultz.com",
+ "lasjardineras.com",
+ "latke.ai",
+ "luxurymurals.com",
+ "marijuanabuyersexchange.com",
+ "marijuanaofthemonthclub.com",
+ "mohairvelvet.com",
+ "mymemosamples.com",
+ "nataliaabrams.com",
+ "nationalvotingday.org",
+ "notvrequired.com",
+ "nybutler.com",
+ "potofthemonthclub.com",
+ "protectyourspec.com",
+ "protestdaily.com",
+ "steveabramsdesigns.com",
+ "studentstrikes.org",
+ "summergamesrentals.com",
+ "theatrewallpaper.com",
+ "thecannabisnews.com",
+ "thedesignerlaboratory.com",
+ "thesalesreps.com",
+ "tradeonlytextiles.com",
+ "treetrimmingguys.com",
+ "upperonepercent.com",
+ "urthfriendly.com",
+ "valleybutler.com",
+ "venturadelivers.com",
+ "venturaeats.com",
+ "vintagebh.com",
+ "wallpapernashville.com",
+ "wallpapernyc.com",
+ "wc-01.com",
+ "wc01wallpaper.com",
+ "weedofthemonthclub.com",
+ "wintergamesrentals.com",
+ "zayde.ai"
+ ],
+ "already_tagged": {
+ "818butler.com": "G-3SEWRYMQJS",
+ "allnewsdaily.com": "G-FDKEFWHB70",
+ "beverlyhillsbutler.com": "G-3M3QK2W0CR",
+ "beverlyhillsvideos.com": "G-DM3D9RP630",
+ "bhbutler.com": "G-BGGE0FBZ43",
+ "boulevardbutler.com": "G-920MM8GTF8",
+ "cypresawards.com": "G-BF6ZTZEKCF",
+ "commercialsalesreps.com": "G-PRJ51PTW5G",
+ "800wallpaper.com": "G-53F1QBZSG0",
+ "1800wallpapers.com": "G-53F1QBZSG0",
+ "fentucci.com": "G-J2SL8P5KDL",
+ "nodailyworries.com": "G-6QLWL5XQNE",
+ "interiordesignershowroom.com": "G-DH9G5HL7YJ",
+ "petitionyour.com": "G-1X9K3FVVQL",
+ "designerlaboratory.com": "G-53F1QBZSG0",
+ "thesetdecorator.com": "G-JBKJE0WLL8",
+ "designwallcoverings.com": "G-53F1QBZSG0",
+ "dwlosangeles.com": "G-53F1QBZSG0",
+ "designerswallcovering.com": "G-53F1QBZSG0",
+ "designerswallcoverings.com": "G-53F1QBZSG0"
+ },
+ "not_a_lander": [
+ "asseeninhotels.com",
+ "asseeninla.com",
+ "asseeninmovies.com",
+ "asseeninshowrooms.com",
+ "barwallpaper.com",
+ "blankstocklining.com",
+ "cfafabrics.com",
+ "classawallcovering.com",
+ "designermagnetics.com",
+ "handmadewallcovering.com",
+ "hospitalitysalesagency.com",
+ "naturalwalltextures.com",
+ "malibuwallpaper.com",
+ "montereywallpaper.com",
+ "printmurals.com",
+ "restaurantfabrics.com",
+ "restaurantmurals.com",
+ "sheltermagazines.com",
+ "roomsettings.com",
+ "thehotelwallpaper.com",
+ "traditionalwhimsy.com",
+ "unitedstateswallpaper.com",
+ "wallpaperexports.com",
+ "venturacorridor.com",
+ "wallpaperpurchasing.com",
+ "wallpaperny.com",
+ "wallpaperfromthe80s.com",
+ "wallpaperweekly.com",
+ "wc01wallcoverings.com"
+ ],
+ "broken": [
+ [
+ "1800wallcoverings.com",
+ "401",
+ "https"
+ ],
+ [
+ "etciemurals.com",
+ "401",
+ "https"
+ ],
+ [
+ "fireratedwallcovering.com",
+ "401",
+ "https"
+ ],
+ [
+ "lacountyeats.com",
+ "403",
+ "https"
+ ],
+ [
+ "specifywallpaper.com",
+ "401",
+ "https"
+ ],
+ [
+ "stevenabramsphotography.com",
+ "401",
+ "https"
+ ],
+ [
+ "petitionyour.org",
+ "301",
+ "http-only"
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/ops/tk10631/verified_targets.txt b/ops/tk10631/verified_targets.txt
new file mode 100644
index 0000000..a442250
--- /dev/null
+++ b/ops/tk10631/verified_targets.txt
@@ -0,0 +1,94 @@
+90210rentals.com
+aaatreetrimming.com
+abramsatlas.com
+abramscivic.com
+abramsdirectory.com
+abramsguide.com
+abramsindex.com
+abramsindustries.com
+abramsintel.com
+abramsintelligence.com
+abramslive.com
+abramslocal.com
+abramsmaps.com
+abramsmarkets.com
+abramsos.com
+abramsprotection.com
+abramsspace.com
+abramsterminal.com
+abramsvc.com
+asknonna.ai
+bestactorawards.com
+bestdocumentaryfilms.com
+beverlyandhills.com
+beverlyhillspaints.com
+bleachfriendly.com
+borninbh.com
+bubbie.ai
+cannabisofthemonthclub.com
+carmelpaints.com
+carmelriverwater.com
+carmelvalleywater.com
+commercialwalls.com
+customdigitalwallcoverings.com
+customdigitalwalls.com
+cypresawards.org
+designerschat.com
+designerswallpapers.com
+designerwallpaints.com
+designerwalltiles.com
+designtradereps.com
+designtradesalesreps.com
+dsgn.tv
+ephedrafreeherbs.com
+fauxnewslive.com
+filthyrichliving.com
+freethedegree.org
+handmadewallpapers.com
+handscreenedwallpaper.com
+hempofthemonthclub.com
+herbsmadeinchina.com
+hospitalityfabrics.net
+hospitalitymurals.com
+hospitalitysalesagents.com
+hospitalitysalesreps.com
+hospitalitywalls.com
+inflationfears.com
+interiordesignreps.com
+joshdultz.com
+lasjardineras.com
+latke.ai
+luxurymurals.com
+marijuanabuyersexchange.com
+marijuanaofthemonthclub.com
+mohairvelvet.com
+mymemosamples.com
+nataliaabrams.com
+nationalvotingday.org
+notvrequired.com
+nybutler.com
+potofthemonthclub.com
+protectyourspec.com
+protestdaily.com
+steveabramsdesigns.com
+studentstrikes.org
+summergamesrentals.com
+theatrewallpaper.com
+thecannabisnews.com
+thedesignerlaboratory.com
+thesalesreps.com
+tradeonlytextiles.com
+treetrimmingguys.com
+upperonepercent.com
+urthfriendly.com
+valleybutler.com
+venturadelivers.com
+venturaeats.com
+vintagebh.com
+wallpapernashville.com
+wallpapernyc.com
+wc-01.com
+wc01wallpaper.com
+weedofthemonthclub.com
+wintergamesrentals.com
+zayde.ai
← f5789c1 TK-10631: stage expanded GA4 create script for all 150 remai
·
back to Domain Landings
·
TK-10631: re-target GA4 create at accounts/15714274 per DTD 47e1773 →