adloop 0.19.6__tar.gz → 0.21.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.
Files changed (67) hide show
  1. {adloop-0.19.6 → adloop-0.21.0}/PKG-INFO +23 -2
  2. {adloop-0.19.6 → adloop-0.21.0}/README.md +21 -1
  3. {adloop-0.19.6 → adloop-0.21.0}/pyproject.toml +2 -1
  4. {adloop-0.19.6 → adloop-0.21.0}/pyproject.toml.orig +2 -1
  5. adloop-0.21.0/src/adloop/ads/conversion_actions.py +2508 -0
  6. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/validate_only.py +35 -2
  7. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/write.py +247 -24
  8. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/auth.py +54 -6
  9. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/config.py +21 -0
  10. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/gtm/client.py +16 -0
  11. adloop-0.21.0/src/adloop/gtm/entities.py +22 -0
  12. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/gtm/read.py +6 -2
  13. adloop-0.21.0/src/adloop/gtm/write.py +986 -0
  14. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/adloop.md +18 -0
  15. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/safety/preview.py +80 -0
  16. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/server.py +1738 -497
  17. adloop-0.19.6/src/adloop/ads/conversion_actions.py +0 -559
  18. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/__init__.py +0 -0
  19. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/__main__.py +0 -0
  20. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/_mcp_patches.py +0 -0
  21. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/__init__.py +0 -0
  22. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/ai_max.py +0 -0
  23. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/brands.py +0 -0
  24. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/client.py +0 -0
  25. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/currency.py +0 -0
  26. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/custom_conversion_goals.py +0 -0
  27. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/enums.py +0 -0
  28. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/forecast.py +0 -0
  29. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/gaql.py +0 -0
  30. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/image_fetch.py +0 -0
  31. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/pmax.py +0 -0
  32. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ads/read.py +0 -0
  33. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/cli.py +0 -0
  34. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/crossref.py +0 -0
  35. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/diagnostics.py +0 -0
  36. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ga4/__init__.py +0 -0
  37. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ga4/client.py +0 -0
  38. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ga4/reports.py +0 -0
  39. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ga4/tracking.py +0 -0
  40. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/ga4/write.py +0 -0
  41. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/gsc/__init__.py +0 -0
  42. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/gsc/client.py +0 -0
  43. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/gsc/reports.py +0 -0
  44. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/gtm/__init__.py +0 -0
  45. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/merchant/__init__.py +0 -0
  46. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/merchant/client.py +0 -0
  47. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/merchant/read.py +0 -0
  48. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/pagespeed.py +0 -0
  49. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/reddit/__init__.py +0 -0
  50. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/reddit/auth.py +0 -0
  51. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/reddit/client.py +0 -0
  52. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/reddit/read.py +0 -0
  53. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/reddit/schedule.py +0 -0
  54. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/reddit/write.py +0 -0
  55. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/__init__.py +0 -0
  56. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/commands/analyze-performance.md +0 -0
  57. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/commands/budget-plan.md +0 -0
  58. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/commands/create-ad.md +0 -0
  59. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/commands/create-campaign.md +0 -0
  60. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/commands/diagnose-tracking.md +0 -0
  61. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules/commands/optimize-campaign.md +0 -0
  62. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/rules_install.py +0 -0
  63. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/runtime.py +0 -0
  64. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/safety/__init__.py +0 -0
  65. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/safety/audit.py +0 -0
  66. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/safety/guards.py +0 -0
  67. {adloop-0.19.6 → adloop-0.21.0}/src/adloop/tracking.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: adloop
3
- Version: 0.19.6
3
+ Version: 0.21.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
@@ -13,6 +13,7 @@ Requires-Dist: google-analytics-admin>=0.27.0
13
13
  Requires-Dist: google-api-python-client>=2.100.0
14
14
  Requires-Dist: google-auth-oauthlib>=1.0.0
15
15
  Requires-Dist: google-api-python-client>=2.0.0
16
+ Requires-Dist: phonenumbers>=8.13
16
17
  Requires-Dist: pyyaml>=6.0
17
18
  Requires-Dist: requests>=2.31
18
19
  Requires-Dist: pytest>=8.0 ; extra == 'dev'
@@ -187,6 +188,26 @@ These tools read the live GTM container and join it with the codebase + GA4 to f
187
188
  | `list_gtm_versions` | Publish history with version IDs and entity counts. Use to correlate a metric drop with a recent publish. |
188
189
  | `get_gtm_version` | Full metadata + tag/trigger names for a single historical container version |
189
190
 
191
+ #### GTM write tools (opt-in)
192
+
193
+ Off by default. Set `gtm.write_enabled: true` in `~/.adloop/config.yaml` and restart; the next call asks you to re-consent with the Tag Manager edit + publish scopes, which are never part of the default grant. Everything follows the usual draft → preview → `confirm_and_apply` flow, and tag/trigger edits only touch a workspace until you publish it.
194
+
195
+ | Tool | What It Does |
196
+ |------|-------------|
197
+ | `draft_gtm_tag` | Create a tag, or update one by `tag_id`. Updates are a read-modify-write: `parameters` merge by key and every field you don't pass (priority, consent settings, firing options, schedule, folder, …) is preserved. Tag types are canonical GTM template IDs (`googtag`, `gaawe`, `awct`, `sp`, `gclidw`, …) or `cvt_<id>` gallery templates. |
198
+ | `draft_gtm_trigger` | Create a trigger, or update one by `trigger_id` (type is immutable). `custom_event_name` wires a `customEvent` trigger to a dataLayer event. |
199
+ | `draft_delete_gtm_entity` | Delete a workspace tag or trigger. Triggers still referenced by a tag are refused up front, with the tags listed. |
200
+ | `draft_publish_gtm_workspace` | Publish a workspace live. The preview lists every pending change, including edits other people made in the GTM UI. |
201
+
202
+ Safety gates specific to GTM:
203
+ - **Custom HTML** runs arbitrary JavaScript on your site, so creating or editing an `html` tag — or publishing a workspace that adds or changes one — is refused unless `gtm.allow_custom_html: true` is also set. Pausing or deleting one is always allowed.
204
+ - **No stale writes.** Updates and deletes pin the entity's fingerprint from the preview, and publish pins the workspace's pending changes; if someone edits the container in between, apply refuses and you re-draft.
205
+ - Publishing stops on merge conflicts or GTM compiler errors. The dry run runs a Tag Manager **quick preview** first (Tag Manager has no validate-only mode), so compiler errors surface before a version is even created. That preview is a POST and stores a preview version in the container — nothing is published and no live tag changes; the rest of the dry run only reads.
206
+ - The publish result names the version it replaced (`previous_live_version_id`), so rolling back is one step: publish that version again in the GTM UI. If the version was created but publishing it failed, the error carries both the created version id and the still-live one.
207
+ - Per-operation names for `safety.blocked_operations`: `gtm_create_tag`, `gtm_update_tag`, `gtm_delete_tag`, `gtm_create_trigger`, `gtm_update_trigger`, `gtm_delete_trigger`, `gtm_publish_workspace`.
208
+
209
+ The Google account also needs **Edit** permission on the container (and **Publish** to publish) under Admin → User Management.
210
+
190
211
  > **Setup for GTM tools** — Enable the **Tag Manager API v2** in your GCP project, then add your AdLoop credentials' email (the OAuth user, or the service account email if using a service account) as a **Read** user on the GTM container under Admin → User Management. Service accounts pick up access on the next call. **OAuth users upgrading from an earlier AdLoop version must re-authorize once**: the GTM scope is new, so delete `~/.adloop/token.json` and run any tool to re-consent — until then GTM tools return a permissions error.
191
212
 
192
213
  ### Search Console Tools
@@ -515,7 +536,7 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
515
536
  | `ads` | Google Ads reads, writes, and planning (Keyword Planner) |
516
537
  | `ga4` | Google Analytics reports, realtime, key events |
517
538
  | `tracking` | Cross-channel attribution + tracking code generation |
518
- | `gtm` | Google Tag Manager audits and reads |
539
+ | `gtm` | Google Tag Manager audits, reads, and opt-in writes |
519
540
  | `gsc` | Search Console reads |
520
541
  | `web` | PageSpeed / Core Web Vitals |
521
542
  | `merchant` | Merchant Center feed health |
@@ -160,6 +160,26 @@ These tools read the live GTM container and join it with the codebase + GA4 to f
160
160
  | `list_gtm_versions` | Publish history with version IDs and entity counts. Use to correlate a metric drop with a recent publish. |
161
161
  | `get_gtm_version` | Full metadata + tag/trigger names for a single historical container version |
162
162
 
163
+ #### GTM write tools (opt-in)
164
+
165
+ Off by default. Set `gtm.write_enabled: true` in `~/.adloop/config.yaml` and restart; the next call asks you to re-consent with the Tag Manager edit + publish scopes, which are never part of the default grant. Everything follows the usual draft → preview → `confirm_and_apply` flow, and tag/trigger edits only touch a workspace until you publish it.
166
+
167
+ | Tool | What It Does |
168
+ |------|-------------|
169
+ | `draft_gtm_tag` | Create a tag, or update one by `tag_id`. Updates are a read-modify-write: `parameters` merge by key and every field you don't pass (priority, consent settings, firing options, schedule, folder, …) is preserved. Tag types are canonical GTM template IDs (`googtag`, `gaawe`, `awct`, `sp`, `gclidw`, …) or `cvt_<id>` gallery templates. |
170
+ | `draft_gtm_trigger` | Create a trigger, or update one by `trigger_id` (type is immutable). `custom_event_name` wires a `customEvent` trigger to a dataLayer event. |
171
+ | `draft_delete_gtm_entity` | Delete a workspace tag or trigger. Triggers still referenced by a tag are refused up front, with the tags listed. |
172
+ | `draft_publish_gtm_workspace` | Publish a workspace live. The preview lists every pending change, including edits other people made in the GTM UI. |
173
+
174
+ Safety gates specific to GTM:
175
+ - **Custom HTML** runs arbitrary JavaScript on your site, so creating or editing an `html` tag — or publishing a workspace that adds or changes one — is refused unless `gtm.allow_custom_html: true` is also set. Pausing or deleting one is always allowed.
176
+ - **No stale writes.** Updates and deletes pin the entity's fingerprint from the preview, and publish pins the workspace's pending changes; if someone edits the container in between, apply refuses and you re-draft.
177
+ - Publishing stops on merge conflicts or GTM compiler errors. The dry run runs a Tag Manager **quick preview** first (Tag Manager has no validate-only mode), so compiler errors surface before a version is even created. That preview is a POST and stores a preview version in the container — nothing is published and no live tag changes; the rest of the dry run only reads.
178
+ - The publish result names the version it replaced (`previous_live_version_id`), so rolling back is one step: publish that version again in the GTM UI. If the version was created but publishing it failed, the error carries both the created version id and the still-live one.
179
+ - Per-operation names for `safety.blocked_operations`: `gtm_create_tag`, `gtm_update_tag`, `gtm_delete_tag`, `gtm_create_trigger`, `gtm_update_trigger`, `gtm_delete_trigger`, `gtm_publish_workspace`.
180
+
181
+ The Google account also needs **Edit** permission on the container (and **Publish** to publish) under Admin → User Management.
182
+
163
183
  > **Setup for GTM tools** — Enable the **Tag Manager API v2** in your GCP project, then add your AdLoop credentials' email (the OAuth user, or the service account email if using a service account) as a **Read** user on the GTM container under Admin → User Management. Service accounts pick up access on the next call. **OAuth users upgrading from an earlier AdLoop version must re-authorize once**: the GTM scope is new, so delete `~/.adloop/token.json` and run any tool to re-consent — until then GTM tools return a permissions error.
164
184
 
165
185
  ### Search Console Tools
@@ -488,7 +508,7 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
488
508
  | `ads` | Google Ads reads, writes, and planning (Keyword Planner) |
489
509
  | `ga4` | Google Analytics reports, realtime, key events |
490
510
  | `tracking` | Cross-channel attribution + tracking code generation |
491
- | `gtm` | Google Tag Manager audits and reads |
511
+ | `gtm` | Google Tag Manager audits, reads, and opt-in writes |
492
512
  | `gsc` | Search Console reads |
493
513
  | `web` | PageSpeed / Core Web Vitals |
494
514
  | `merchant` | Merchant Center feed health |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.19.6"
3
+ version = "0.21.0"
4
4
  description = "The AI command center for Google Ads, Reddit Ads, GA4, and tracking code."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -21,6 +21,7 @@ dependencies = [
21
21
  "google-api-python-client>=2.100.0",
22
22
  "google-auth-oauthlib>=1.0.0",
23
23
  "google-api-python-client>=2.0.0",
24
+ "phonenumbers>=8.13",
24
25
  "pyyaml>=6.0",
25
26
  "requests>=2.31",
26
27
  ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.19.6"
3
+ version = "0.21.0"
4
4
  description = "The AI command center for Google Ads, Reddit Ads, GA4, and tracking code."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -17,6 +17,7 @@ dependencies = [
17
17
  "google-api-python-client>=2.100.0",
18
18
  "google-auth-oauthlib>=1.0.0",
19
19
  "google-api-python-client>=2.0.0",
20
+ "phonenumbers>=8.13",
20
21
  "pyyaml>=6.0",
21
22
  # Reddit Ads has no SDK; the REST client (adloop.reddit.client) and the
22
23
  # PageSpeed helper call requests directly.