← back to Ga Allsites
_ga4_audit.py
54 lines
import json
import pathlib
import re
import ssl
import urllib.request
from concurrent.futures import ThreadPoolExecutor
def slug(s):
x=s.lower().replace(" - ga4","").replace("&","and"); return "".join(c for c in x if c.isalnum())
def dslug(d): return "".join(c for c in d.rsplit(".",1)[0].lower() if c.isalnum())
data=json.loads(pathlib.Path("cache/data.json").read_text())
ga4={slug(r["property"]) for r in data["rows"]}
port=json.loads(pathlib.Path("cache/_portfolio_domains.json").read_text())["union"]
missing=[d for d in port if not any(dslug(d)==g or dslug(d) in g or g in dslug(d) for g in ga4 if g)]
ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
PARK=re.compile(r"(domain (is )?for sale|buy this domain|parked|godaddy\.com/domainsearch|afternic|sedoparking|this domain may be for sale|hugedomains|dan\.com|is coming soon|website coming soon|under construction|default web page|welcome to nginx|apache2 ubuntu default)",re.IGNORECASE)
GA4=re.compile(r"(G-[A-Z0-9]{6,}|googletagmanager\.com/gtag/js|gtag\('config'|UA-\d{4,})")
def probe(d):
url=f"https://{d}/"
try:
req=urllib.request.Request(url,headers={"User-Agent":"Mozilla/5.0 (audit)"})
r=urllib.request.urlopen(req,timeout=12,context=ctx)
final=r.geturl(); html=r.read(200000).decode("utf-8","ignore"); code=r.getcode()
except Exception as e:
return (d,"DEAD",str(e)[:40],False,"")
off = dslug(d) not in dslug(final.split("//")[-1].split("/")[0])
has_ga4=bool(GA4.search(html))
if PARK.search(html) or len(html)<400:
cls="PARKED"
elif off:
cls="REDIRECT"
else:
cls="LIVE"
return (d,cls,f"{code}",has_ga4,final if off else "")
with ThreadPoolExecutor(max_workers=20) as ex:
res=list(ex.map(probe,missing))
from collections import defaultdict
buckets=defaultdict(list)
for d,cls,info,ga,final in res:
key = "LIVE_HAS_GA4" if (cls=="LIVE" and ga) else cls
buckets[key].append((d,info,final))
print("=== GA4 AUDIT of the 162 no-match domains ===")
for k in ["LIVE","LIVE_HAS_GA4","REDIRECT","PARKED","DEAD"]:
print(f" {k:14} {len(buckets.get(k,[]))}")
install=[d for d,_,_ in buckets.get("LIVE",[])]
pathlib.Path("cache/_ga4_install_list.json").write_text(json.dumps(sorted(install)))
print(f"\n>>> INSTALL LIST (live site, genuinely no GA4): {len(install)}")
for d in sorted(install): print(" ",d)
if buckets.get("LIVE_HAS_GA4"):
print(f"\n(already has a tag, just name-mismatched — no action: {len(buckets['LIVE_HAS_GA4'])})")
for d,_,_ in sorted(buckets["LIVE_HAS_GA4"])[:20]: print(" ~",d)