adloop 0.27.2__tar.gz → 0.29.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {adloop-0.27.2 → adloop-0.29.0}/PKG-INFO +15 -3
- {adloop-0.27.2 → adloop-0.29.0}/README.md +14 -2
- {adloop-0.27.2 → adloop-0.29.0}/pyproject.toml +1 -1
- {adloop-0.27.2 → adloop-0.29.0}/pyproject.toml.orig +1 -1
- adloop-0.29.0/src/adloop/ads/audiences.py +547 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/write.py +2 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/cli.py +6 -3
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/adloop.md +18 -2
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/server.py +159 -8
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/__main__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/_mcp_patches.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/ai_max.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/brands.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/client.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/conversion_actions.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/currency.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/custom_conversion_goals.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/enums.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/forecast.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/gaql.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/image_fetch.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/pmax.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/read.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/shopping.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ads/validate_only.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/auth.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/config.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/crossref.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/diagnostics.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ga4/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ga4/client.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ga4/reports.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ga4/tracking.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/ga4/write.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gsc/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gsc/client.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gsc/reports.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gtm/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gtm/client.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gtm/entities.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gtm/read.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/gtm/write.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/merchant/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/merchant/client.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/merchant/read.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/pagespeed.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/reddit/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/reddit/auth.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/reddit/client.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/reddit/read.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/reddit/schedule.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/reddit/write.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/commands/analyze-performance.md +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/commands/budget-plan.md +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/commands/create-ad.md +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/commands/create-campaign.md +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/commands/diagnose-tracking.md +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules/commands/optimize-campaign.md +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/rules_install.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/runtime.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/safety/__init__.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/safety/approval.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/safety/approval_card.html +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/safety/audit.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/safety/guards.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/safety/preview.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/tracking.py +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/upload_card.html +0 -0
- {adloop-0.27.2 → adloop-0.29.0}/src/adloop/uploads.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: adloop
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.29.0
|
|
4
4
|
Summary: The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.
|
|
5
5
|
Keywords: mcp,google-ads,reddit-ads,google-analytics,ga4,cursor,marketing
|
|
6
6
|
Author: Daniel Klose
|
|
@@ -138,6 +138,9 @@ The best features come from real workflows. If you're using AdLoop and find your
|
|
|
138
138
|
| `get_audience_performance` | Audience segment performance — remarketing, in-market, affinity, demographics |
|
|
139
139
|
| `get_change_history` | What changed before the drop: who changed what and when, through which client (UI, API, scripts, auto-applied recommendations), last 30 days |
|
|
140
140
|
| `get_demographic_targeting` | List demographic criteria (age/gender/parental status/income) on an ad group or campaign |
|
|
141
|
+
| `get_audience_lists` | The account's remarketing and customer lists (size, eligibility, open/closed), custom and combined segments |
|
|
142
|
+
| `search_audience_segments` | Find Google's in-market and affinity segments by name |
|
|
143
|
+
| `get_audience_targeting` | Audiences and audience exclusions on a campaign or ad group, plus the audience mode (observation or targeting) |
|
|
141
144
|
| `suggest_brands` | Resolve a brand name to the brands Google recognizes — brand ID, name, state, URLs |
|
|
142
145
|
| `check_brand_names` | Check a shortlist of brand names against Google's brand knowledge graph (max 25 per call) |
|
|
143
146
|
| `get_brand_lists` | List brand lists (SharedSets of type BRANDS) — ID, name, status, member count |
|
|
@@ -308,6 +311,7 @@ All write operations follow a **draft → preview → confirm** workflow. Nothin
|
|
|
308
311
|
| `draft_key_event` | Mark a GA4 event as a key event (conversion) — the fix for "fires but isn't tracked as a conversion" |
|
|
309
312
|
| `draft_delete_key_event` | Remove a GA4 key event. The event keeps firing but no longer counts as a conversion, for future data only |
|
|
310
313
|
| `draft_demographic_targeting` | Propose demographic criteria (age, gender, parental status, income) — exclusions by default |
|
|
314
|
+
| `draft_audience_attachment` | Attach audiences as observation (default), targeting (double confirmation) or exclusion; refuses pairings Google doesn't allow and Search lists too small to target |
|
|
311
315
|
| `propose_negative_keyword_list` | Draft a shared negative keyword list (SharedSet) and attach it to a campaign — reusable across multiple campaigns |
|
|
312
316
|
| `propose_brand_list` | Draft a brand list (SharedSet of type BRANDS) from Commercial KG MIDs and optionally attach it to campaigns — `negative=true` (default) excludes the brands, `false` restricts targeting to them |
|
|
313
317
|
| `add_to_brand_list` | Draft adding brands to an existing brand list |
|
|
@@ -557,7 +561,7 @@ All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](
|
|
|
557
561
|
|
|
558
562
|
### Toolsets — trim the context footprint
|
|
559
563
|
|
|
560
|
-
Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into the model's context at the start of every conversation**. AdLoop's full catalog
|
|
564
|
+
Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into the model's context at the start of every conversation**. With AdLoop's full catalog that's a noticeable share of the context window, paid before you type a word. If you only use part of AdLoop, expose a subset with the `ADLOOP_TOOLSETS` environment variable in your MCP client's `env` block (the `adloop init` wizard offers this and writes it into the snippets for you):
|
|
561
565
|
|
|
562
566
|
```json
|
|
563
567
|
"env": { "ADLOOP_TOOLSETS": "ads,ga4" }
|
|
@@ -574,7 +578,15 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
|
|
|
574
578
|
| `merchant` | Merchant Center feed health |
|
|
575
579
|
| `reddit` | Reddit Ads reads, writes, and planning |
|
|
576
580
|
|
|
577
|
-
|
|
581
|
+
Google Ads can be narrowed further. Use one of these instead of `ads`:
|
|
582
|
+
|
|
583
|
+
| Subset | Covers |
|
|
584
|
+
|---|---|
|
|
585
|
+
| `ads:read` | Ads reports, GAQL, and the Ads/Analytics cross-checks (`attribution_check`, `analyze_campaign_conversions`, `landing_page_analysis`) |
|
|
586
|
+
| `ads:write` | Ads drafts and changes; turns on `ads:read` too, because a draft needs the reads first (IDs, bidding strategy) |
|
|
587
|
+
| `ads:plan` | Keyword ideas and budget forecasts (`discover_keywords`, `estimate_budget`) |
|
|
588
|
+
|
|
589
|
+
`health_check` and `confirm_and_apply` are always included, whatever you select. Unset = the full catalog; unknown names fail at startup with the valid list. The effect is real: `ads:read,ga4` costs about 40% of `ads,ga4` for audits and diagnosis, and an `ads:plan`-only client for keyword research pays about 5% of the full catalog. Toolsets are per *client*, not per install: one AdLoop config can serve a trimmed Cursor and a full-catalog Claude Code side by side.
|
|
578
590
|
|
|
579
591
|
On [AdLoop Cloud](https://getadloop.com), the same feature is per API key: pick toolsets when creating a key in the dashboard, and that key's tools/list is trimmed server-side for whichever AI client uses it.
|
|
580
592
|
|
|
@@ -110,6 +110,9 @@ The best features come from real workflows. If you're using AdLoop and find your
|
|
|
110
110
|
| `get_audience_performance` | Audience segment performance — remarketing, in-market, affinity, demographics |
|
|
111
111
|
| `get_change_history` | What changed before the drop: who changed what and when, through which client (UI, API, scripts, auto-applied recommendations), last 30 days |
|
|
112
112
|
| `get_demographic_targeting` | List demographic criteria (age/gender/parental status/income) on an ad group or campaign |
|
|
113
|
+
| `get_audience_lists` | The account's remarketing and customer lists (size, eligibility, open/closed), custom and combined segments |
|
|
114
|
+
| `search_audience_segments` | Find Google's in-market and affinity segments by name |
|
|
115
|
+
| `get_audience_targeting` | Audiences and audience exclusions on a campaign or ad group, plus the audience mode (observation or targeting) |
|
|
113
116
|
| `suggest_brands` | Resolve a brand name to the brands Google recognizes — brand ID, name, state, URLs |
|
|
114
117
|
| `check_brand_names` | Check a shortlist of brand names against Google's brand knowledge graph (max 25 per call) |
|
|
115
118
|
| `get_brand_lists` | List brand lists (SharedSets of type BRANDS) — ID, name, status, member count |
|
|
@@ -280,6 +283,7 @@ All write operations follow a **draft → preview → confirm** workflow. Nothin
|
|
|
280
283
|
| `draft_key_event` | Mark a GA4 event as a key event (conversion) — the fix for "fires but isn't tracked as a conversion" |
|
|
281
284
|
| `draft_delete_key_event` | Remove a GA4 key event. The event keeps firing but no longer counts as a conversion, for future data only |
|
|
282
285
|
| `draft_demographic_targeting` | Propose demographic criteria (age, gender, parental status, income) — exclusions by default |
|
|
286
|
+
| `draft_audience_attachment` | Attach audiences as observation (default), targeting (double confirmation) or exclusion; refuses pairings Google doesn't allow and Search lists too small to target |
|
|
283
287
|
| `propose_negative_keyword_list` | Draft a shared negative keyword list (SharedSet) and attach it to a campaign — reusable across multiple campaigns |
|
|
284
288
|
| `propose_brand_list` | Draft a brand list (SharedSet of type BRANDS) from Commercial KG MIDs and optionally attach it to campaigns — `negative=true` (default) excludes the brands, `false` restricts targeting to them |
|
|
285
289
|
| `add_to_brand_list` | Draft adding brands to an existing brand list |
|
|
@@ -529,7 +533,7 @@ All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](
|
|
|
529
533
|
|
|
530
534
|
### Toolsets — trim the context footprint
|
|
531
535
|
|
|
532
|
-
Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into the model's context at the start of every conversation**. AdLoop's full catalog
|
|
536
|
+
Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into the model's context at the start of every conversation**. With AdLoop's full catalog that's a noticeable share of the context window, paid before you type a word. If you only use part of AdLoop, expose a subset with the `ADLOOP_TOOLSETS` environment variable in your MCP client's `env` block (the `adloop init` wizard offers this and writes it into the snippets for you):
|
|
533
537
|
|
|
534
538
|
```json
|
|
535
539
|
"env": { "ADLOOP_TOOLSETS": "ads,ga4" }
|
|
@@ -546,7 +550,15 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
|
|
|
546
550
|
| `merchant` | Merchant Center feed health |
|
|
547
551
|
| `reddit` | Reddit Ads reads, writes, and planning |
|
|
548
552
|
|
|
549
|
-
|
|
553
|
+
Google Ads can be narrowed further. Use one of these instead of `ads`:
|
|
554
|
+
|
|
555
|
+
| Subset | Covers |
|
|
556
|
+
|---|---|
|
|
557
|
+
| `ads:read` | Ads reports, GAQL, and the Ads/Analytics cross-checks (`attribution_check`, `analyze_campaign_conversions`, `landing_page_analysis`) |
|
|
558
|
+
| `ads:write` | Ads drafts and changes; turns on `ads:read` too, because a draft needs the reads first (IDs, bidding strategy) |
|
|
559
|
+
| `ads:plan` | Keyword ideas and budget forecasts (`discover_keywords`, `estimate_budget`) |
|
|
560
|
+
|
|
561
|
+
`health_check` and `confirm_and_apply` are always included, whatever you select. Unset = the full catalog; unknown names fail at startup with the valid list. The effect is real: `ads:read,ga4` costs about 40% of `ads,ga4` for audits and diagnosis, and an `ads:plan`-only client for keyword research pays about 5% of the full catalog. Toolsets are per *client*, not per install: one AdLoop config can serve a trimmed Cursor and a full-catalog Claude Code side by side.
|
|
550
562
|
|
|
551
563
|
On [AdLoop Cloud](https://getadloop.com), the same feature is per API key: pick toolsets when creating a key in the dashboard, and that key's tools/list is trimmed server-side for whichever AI client uses it.
|
|
552
564
|
|