v0.11.0 — Tag Manager, demographics & audit-friendly reads
AdLoop v0.11.0 — Tag Manager, demographics, and audit-friendly reads
The biggest release since 0.9: 15 new tools (46 → 61), three of them community-contributed. AdLoop now sees your entire tracking stack — codebase, Google Tag Manager, and GA4 — in one audit, and can manage demographic and geographic targeting with the same preview-first safety as everything else.
🏷️ Google Tag Manager integration (12 new tools)
Contributed by @illia-sapryga (#29). Eleven read tools covering accounts, containers, tags, triggers, variables, workspaces, and version history — plus the headline act:
audit_event_coverage — a three-way join your GTM Preview mode can't do: codebase events ↔ live GTM tags ↔ GA4 actual fires, with a per-event status matrix (12 distinct statuses) and auto-generated insights. It answers "is every conversion actually being captured, and where are the gaps?" in a single call. It flags paused tags that should be live, active tags that never fire, events reaching GA4 from sources GTM doesn't control (gtm_paused_but_firing), and surfaces dynamic {{Event}} and Custom HTML tags for manual review.
Setup: enable the Tag Manager API v2 in your Google Cloud project and grant your OAuth user (or service account) Read access on the container. Upgrading OAuth users must re-authorize once — the GTM scope is new, so delete ~/.adloop/token.json and run any tool to re-consent. If you forget, the new INSUFFICIENT_SCOPES structured error will tell you exactly that.
👥 Demographic targeting (2 new tools)
Contributed by @chrmoller (#38). get_demographic_targeting lists age/gender/parental-status/income criteria on any ad group or campaign; draft_demographic_targeting proposes changes — exclusion-first by default, through the standard preview → confirm_and_apply flow.
The guard rails do real work here: excluding UNDETERMINED warns you that it blocks every user Google can't classify (often 30%+ of impressions, more under EU consent), campaign-level positive targeting is rejected at preview time (the API only supports exclusions there), and income buckets are correctly documented as percentiles, not currency — the pitfall everyone hits.
📍 Negative geo exclusions
Contributed by @thiagoc7 (#39, closes #46). add_negative_locations excludes cities or regions from a campaign while keeping broader positive targets — "target the state of São Paulo but not São Paulo city" is now a one-preview change. Existing negative geo criteria already survive positive-target replacements (since v0.9); now you can add them too.
📉 Compact mode — audits without the context flood
From #45 (thanks @luison for the measured report): get_campaign_performance, get_keyword_performance, get_search_terms, and get_ad_performance now accept compact=true. Instead of every row you get account totals, breakdowns, the top-10 rows, and pre-computed offender lists: zero-conversion spenders, low-quality-score keywords, ready-made negative-keyword candidates (5+ clicks, zero conversions), thin RSAs, and single-ad ad groups. Responses are ~90% smaller on real accounts, and the compression is deterministic — no summarizer that can drop the one finding that matters.
🧭 Audience compatibility insights
From #44 (thanks @luison): get_audience_performance now warns inline when results include Search campaigns — custom segments (custom_audience) can never be attached to Search, only Display, Video, Demand Gen, and PMax-as-signals. An empty custom_audience join on a Search campaign is expected, not missing data. This complements the audience ↔ campaign-type compatibility matrix added to the orchestration rules in v0.10.
🔧 Fixes and internals
- GTM auth goes through the
CredentialsProviderprotocol — hosted/multi-tenant deployments without GTM support fail with a clear capability error instead of falling back to the wrong credentials. - RSA drafts now coerce JSON-string list params for pinned headline/description dicts (closes a gap from #28's original fix).
adloop --versiontold you 0.9.0 since two releases ago —__version__is now derived from installed package metadata and can never drift again.- A static CI guard now scans for stale pre-v0.10 config references, after the pattern bit two merges.
- New dependency:
google-api-python-client(Tag Manager discovery client).
Upgrade
pip install -U adloop # or: uv tool upgrade adloop
adloop update-rules # refresh the orchestration rules (new GTM + demographics sections)OAuth users: re-auth once for the GTM scope (see above). Everyone else: nothing breaking.
☁️ Prefer zero setup? All 61 tools are live on AdLoop Cloud — free during beta, EU-hosted, GDPR-first.