adloop 0.13.2__tar.gz → 0.14.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 (59) hide show
  1. adloop-0.13.2/README.md → adloop-0.14.0/PKG-INFO +67 -7
  2. adloop-0.13.2/PKG-INFO → adloop-0.14.0/README.md +39 -32
  3. {adloop-0.13.2 → adloop-0.14.0}/pyproject.toml +4 -2
  4. {adloop-0.13.2 → adloop-0.14.0}/pyproject.toml.orig +6 -3
  5. adloop-0.14.0/src/adloop/ads/conversion_actions.py +558 -0
  6. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/read.py +46 -4
  7. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/write.py +339 -20
  8. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/auth.py +23 -0
  9. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/cli.py +110 -0
  10. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/config.py +59 -12
  11. adloop-0.14.0/src/adloop/reddit/__init__.py +9 -0
  12. adloop-0.14.0/src/adloop/reddit/auth.py +504 -0
  13. adloop-0.14.0/src/adloop/reddit/client.py +270 -0
  14. adloop-0.14.0/src/adloop/reddit/read.py +1344 -0
  15. adloop-0.14.0/src/adloop/reddit/schedule.py +200 -0
  16. adloop-0.14.0/src/adloop/reddit/write.py +1684 -0
  17. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/adloop.md +98 -17
  18. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/safety/preview.py +4 -0
  19. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/server.py +1109 -72
  20. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/__init__.py +0 -0
  21. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/__main__.py +0 -0
  22. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/_mcp_patches.py +0 -0
  23. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/__init__.py +0 -0
  24. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/client.py +0 -0
  25. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/currency.py +0 -0
  26. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/enums.py +0 -0
  27. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/forecast.py +0 -0
  28. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/gaql.py +0 -0
  29. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ads/pmax.py +0 -0
  30. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/crossref.py +0 -0
  31. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/diagnostics.py +0 -0
  32. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ga4/__init__.py +0 -0
  33. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ga4/client.py +0 -0
  34. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ga4/reports.py +0 -0
  35. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ga4/tracking.py +0 -0
  36. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/ga4/write.py +0 -0
  37. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/gsc/__init__.py +0 -0
  38. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/gsc/client.py +0 -0
  39. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/gsc/reports.py +0 -0
  40. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/gtm/__init__.py +0 -0
  41. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/gtm/client.py +0 -0
  42. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/gtm/read.py +0 -0
  43. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/merchant/__init__.py +0 -0
  44. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/merchant/client.py +0 -0
  45. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/merchant/read.py +0 -0
  46. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/pagespeed.py +0 -0
  47. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/__init__.py +0 -0
  48. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/commands/analyze-performance.md +0 -0
  49. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/commands/budget-plan.md +0 -0
  50. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/commands/create-ad.md +0 -0
  51. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/commands/create-campaign.md +0 -0
  52. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/commands/diagnose-tracking.md +0 -0
  53. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules/commands/optimize-campaign.md +0 -0
  54. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/rules_install.py +0 -0
  55. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/runtime.py +0 -0
  56. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/safety/__init__.py +0 -0
  57. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/safety/audit.py +0 -0
  58. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/safety/guards.py +0 -0
  59. {adloop-0.13.2 → adloop-0.14.0}/src/adloop/tracking.py +0 -0
@@ -1,8 +1,37 @@
1
+ Metadata-Version: 2.3
2
+ Name: adloop
3
+ Version: 0.14.0
4
+ Summary: The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.
5
+ Keywords: mcp,google-ads,reddit-ads,google-analytics,ga4,cursor,marketing
6
+ Author: Daniel Klose
7
+ Author-email: Daniel Klose <info@daniel-klose.com>
8
+ License: MIT
9
+ Requires-Dist: fastmcp>=3.0.0
10
+ Requires-Dist: google-ads>=31.1.0
11
+ Requires-Dist: google-analytics-data>=0.20.0
12
+ Requires-Dist: google-analytics-admin>=0.27.0
13
+ Requires-Dist: google-api-python-client>=2.100.0
14
+ Requires-Dist: google-auth-oauthlib>=1.0.0
15
+ Requires-Dist: google-api-python-client>=2.0.0
16
+ Requires-Dist: pyyaml>=6.0
17
+ Requires-Dist: requests>=2.31
18
+ Requires-Dist: pytest>=8.0 ; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
20
+ Requires-Python: >=3.11
21
+ Project-URL: Homepage, https://github.com/kLOsk/adloop
22
+ Project-URL: Repository, https://github.com/kLOsk/adloop
23
+ Project-URL: Issues, https://github.com/kLOsk/adloop/issues
24
+ Project-URL: Changelog, https://github.com/kLOsk/adloop/releases
25
+ Provides-Extra: dev
26
+ Description-Content-Type: text/markdown
27
+
28
+ <!-- mcp-name: com.getadloop/adloop -->
29
+
1
30
  <div align="center">
2
31
 
3
32
  # AdLoop
4
33
 
5
- **The AI command center for Google Ads, GA4, and tracking code.**
34
+ **The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.**
6
35
 
7
36
  [![PyPI](https://img.shields.io/pypi/v/adloop.svg)](https://pypi.org/project/adloop/)
8
37
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
@@ -12,14 +41,14 @@
12
41
  [![GA4 Data API](https://img.shields.io/badge/GA4-Data%20API-E37400.svg?logo=google-analytics&logoColor=white)](https://developers.google.com/analytics/devguides/reporting/data/v1)
13
42
  [![GitHub stars](https://img.shields.io/github/stars/kLOsk/adloop?style=social)](https://github.com/kLOsk/adloop)
14
43
 
15
- An MCP server that gives your AI assistant read + write access to Google Ads and GA4 — with safety guardrails that prevent accidental spend.
44
+ An MCP server that gives your AI assistant read + write access to Google Ads, Reddit Ads and GA4 — with safety guardrails that prevent accidental spend.
16
45
 
17
- **[☁️ Skip the setup — use AdLoop Cloud (free beta)](https://getadloop.com)** &nbsp;·&nbsp; or self-host: `pip install adloop`
46
+ **[☁️ Skip the setup — use AdLoop Cloud (free plan, no card)](https://getadloop.com)** &nbsp;·&nbsp; or self-host: `pip install adloop`
18
47
 
19
48
  </div>
20
49
 
21
50
  > [!TIP]
22
- > **[AdLoop Cloud](https://getadloop.com) is the hosted version of this project — live now, free during beta (limited seats).** Connect Google in two clicks and use the full toolset from claude.ai, ChatGPT, Claude Code, Cursor, or Gemini. No Google Cloud project, no developer token, no OAuth verification wait. EU-hosted, GDPR-first, DPA included.
51
+ > **[AdLoop Cloud](https://getadloop.com) is the hosted version of this project, with a free plan that needs no credit card.** Connect Google in two clicks and use the full toolset from claude.ai, ChatGPT, Claude Code, Cursor, or Gemini. No Google Cloud project, no developer token, no OAuth verification wait. EU-hosted, GDPR-first, DPA included.
23
52
 
24
53
  > 📚 **Documentation: [docs.getadloop.com](https://docs.getadloop.com)** — setup guides per AI client, toolsets, the safety model, and troubleshooting for both editions.
25
54
 
@@ -37,7 +66,7 @@ Both versions run the same tools with the same safety model. The difference is w
37
66
  | **Works with** | claude.ai, ChatGPT, Claude Code, Cursor, Gemini | Claude Code, Cursor, Claude Desktop, any local MCP client |
38
67
  | **Where your data flows** | EU servers (Germany), GDPR-first, DPA included | 100% your machine — nothing leaves it |
39
68
  | **Updates** | Automatic | `pip install -U adloop` |
40
- | **Price** | Free during beta | Free forever (MIT) |
69
+ | **Price** | Free plan, no card; [paid plans](https://getadloop.com/preise) for more accounts and volume | Free forever (MIT) |
41
70
 
42
71
  **Not sure? [Start with Cloud](https://getadloop.com)** — it's the fastest way to see what AdLoop can do, and it's the only way to use AdLoop from claude.ai or ChatGPT. Self-host when you want everything on your own machine or need to modify the code. And if you're here to hack on AdLoop itself: welcome, keep scrolling.
43
72
 
@@ -169,6 +198,27 @@ These tools read the live GTM container and join it with the codebase + GA4 to f
169
198
 
170
199
  > **Setup for GSC tools** — Enable the **Search Console API** in your GCP project. Upgrading OAuth users must re-authorize once for the new scope (delete `~/.adloop/token.json`, run any tool). The killer combo: cross-reference organic queries with `get_keyword_performance` to find paid/organic cannibalization and untapped keyword opportunities.
171
200
 
201
+ ### Reddit Ads Tools
202
+
203
+ A second ad platform, same safety model. Reddit is a separate connection: its own developer app, its own OAuth, no developer token and no approval process. Every tool takes `ad_account_id` (defaults to `reddit.ad_account_id`).
204
+
205
+ | Tool | What It Does |
206
+ |------|-------------|
207
+ | `list_reddit_accounts` | Discover businesses and ad accounts (currency, time zone, approval state) |
208
+ | `list_reddit_funding_instruments` | Billing instruments and posting profiles — prerequisites for creating campaigns and ads |
209
+ | `get_reddit_campaigns` / `get_reddit_ad_groups` / `get_reddit_ads` | Structure with configured vs effective status, budgets, bids, pixel, targeting, weekly schedule, rejection reasons; `include_copy` returns each ad's post (headline, body, destination, media) |
210
+ | `get_reddit_performance` | Spend, clicks, CTR, CPC, conversions, CPA, ROAS per account/campaign/ad group/ad, optional breakdown (date, country, community, keyword, placement, …), compact mode with insights |
211
+ | `run_reddit_report` | Raw reports endpoint for any metric (REACH, video, per-event conversions) |
212
+ | `get_reddit_pixels` | Pixels and when each event last fired — flags ad groups optimizing for events the pixel never sent |
213
+ | `search_reddit_targeting` | Communities, interests, geolocations, languages, keyword suggestions, and Reddit's related-community suggestions (by seed communities or website) |
214
+ | `get_reddit_account_history` | Who changed what and when: field, before/after, member |
215
+ | `estimate_reddit_ad_group` | Audience size, delivery estimate and suggested bid range for a planned ad group (Reddit's counterpart of `estimate_budget`) |
216
+ | `pause_reddit_entity` / `enable_reddit_entity` / `remove_reddit_entity` | Status changes through the preview gate (remove = ARCHIVE, irreversible, double-confirmed) |
217
+ | `update_reddit_campaign` / `update_reddit_ad_group` / `update_reddit_ad` | Budget, bid, run dates, weekly schedule (day names, viewer-local hours), targeting and placements (validated with Reddit at draft time), landing URL and comment changes with old → new previews, budget cap and bid-increase guards |
218
+ | `draft_reddit_campaign` / `draft_reddit_ad_group` / `draft_reddit_ad` | Create campaign → ad group (pixel + targeting required) → post + ad, or promote an existing post with `post_id`. Everything is created **PAUSED**. |
219
+
220
+ > **Setup for Reddit Ads tools** — In Reddit Ads Manager open **Business Manager → Developer Application → Create app** (business admins only; no approval wait). Register the redirect URL exactly as `http://localhost:8765/callback`, then run `adloop init` and complete the Reddit Ads step: it opens Reddit's consent page (scopes `adsread` + `adsedit`, permanent grant), stores the refresh token at `~/.adloop/reddit_token.json`, and lets you pick the default ad account. Reddit rate-limits per user (reporting: 60 requests/min) and requires a descriptive User-Agent, which AdLoop builds from your app id and Reddit username. Reddit has no validate-only mode, so `confirm_and_apply(dry_run=true)` re-reads the target and re-checks the safety caps instead.
221
+
172
222
  ### Planning Tools
173
223
 
174
224
  | Tool | What It Does |
@@ -418,6 +468,10 @@ All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](
418
468
  | `ads` | `developer_token` | — | Your Google Ads API developer token |
419
469
  | `ads` | `customer_id` | — | Default Google Ads customer ID (auto-discovered by `adloop init`) |
420
470
  | `ads` | `login_customer_id` | — | Your MCC account ID |
471
+ | `reddit` | `client_id` / `client_secret` | *(empty)* | Your Reddit developer app (Business Manager → Developer Application) |
472
+ | `reddit` | `ad_account_id` | *(empty)* | Default Reddit ad account for every Reddit tool (picked by `adloop init`) |
473
+ | `reddit` | `username` | *(empty)* | Your Reddit username, used only in the User-Agent Reddit requires |
474
+ | `reddit` | `token_path` | `~/.adloop/reddit_token.json` | Where the Reddit refresh token is stored |
421
475
  | `safety` | `max_daily_budget` | `50.00` | Maximum allowed daily budget per campaign |
422
476
  | `safety` | `require_dry_run` | `true` | Force all writes to dry-run mode |
423
477
  | `safety` | `two_phase_apply` | `false` | Refuse real applies until the plan had a dry-run pass |
@@ -440,6 +494,7 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
440
494
  | `gsc` | Search Console reads |
441
495
  | `web` | PageSpeed / Core Web Vitals |
442
496
  | `merchant` | Merchant Center feed health |
497
+ | `reddit` | Reddit Ads reads, writes, and planning |
443
498
 
444
499
  `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,ga4` drops the session cost to ~13k tokens, and a `ga4`-only client pays ~2k — nearly 90% less. Toolsets are per *client*, not per install: one AdLoop config can serve a trimmed Cursor and a full-catalog Claude Code side by side.
445
500
 
@@ -450,7 +505,7 @@ On [AdLoop Cloud](https://getadloop.com), the same feature is per API key: pick
450
505
  ```
451
506
  src/adloop/
452
507
  ├── __init__.py # Entry point — routes 'adloop init' to wizard, otherwise starts MCP server
453
- ├── server.py # FastMCP server — 67 tool registrations with safety annotations
508
+ ├── server.py # FastMCP server — every tool registration with safety annotations and toolset tags
454
509
  ├── config.py # Config loader (~/.adloop/config.yaml)
455
510
  ├── auth.py # OAuth 2.0 flow (user-supplied credentials, headless fallback) + service accounts; GA4 / Ads / GTM scopes
456
511
  ├── cli.py # Interactive 'adloop init' setup wizard
@@ -470,6 +525,11 @@ src/adloop/
470
525
  ├── gtm/
471
526
  │ ├── client.py # Google Tag Manager API v2 client
472
527
  │ └── read.py # Live container fetching, tag/trigger/variable parsing, workspace diff, version history
528
+ ├── reddit/
529
+ │ ├── auth.py # Reddit OAuth2 (own app, permanent refresh token, loopback flow for adloop init)
530
+ │ ├── client.py # Reddit Ads API v3 REST client — bearer refresh, per-user rate limits, pagination
531
+ │ ├── read.py # Accounts, campaigns, ad groups, ads, performance reports, pixels, targeting lookups
532
+ │ └── write.py # Draft/preflight/apply for status, budget, bid, targeting, and PAUSED creation
473
533
  └── safety/
474
534
  ├── guards.py # Budget caps, bid limits, blocked operations, Broad Match safety
475
535
  ├── preview.py # Change plans and previews
@@ -491,7 +551,7 @@ What's been shipped and what's next:
491
551
  - ~~Claude Code support~~ ✓ — `CLAUDE.md`, `.mcp.json`, `.claude/rules/`, `.claude/commands/`, CLI wizard snippets
492
552
  - **Claude Desktop one-click install** — `adloop install claude-desktop` (and/or a `.dxt` extension bundle) that writes the AdLoop MCP entry into `claude_desktop_config.json` automatically, so Claude Desktop + Cowork users don't have to hand-edit JSON
493
553
  - ~~PyPI package~~ ✓ — `pip install adloop`
494
- - ~~[AdLoop Cloud](https://getadloop.com)~~ ✓ — the hosted version, live in beta: no Google Cloud project, no developer token, connect Google in two clicks (EU-hosted, GDPR-first)
554
+ - ~~[AdLoop Cloud](https://getadloop.com)~~ ✓ — the hosted version: no Google Cloud project, no developer token, connect Google in two clicks (EU-hosted, GDPR-first)
495
555
  - ~~Headless server support~~ ✓ — manual URL copy-paste flow for servers without a browser
496
556
  - ~~Behavioral eval suites~~ ✓ — 28 prompt-and-expectation tests covering read, write, tracking, and planning workflows
497
557
  - ~~Google Tag Manager integration~~ ✓ — read tools for tags, triggers, variables, workspaces, and version history, plus the `audit_event_coverage` three-way join across codebase events, GTM tags, and GA4 actual fires
@@ -1,34 +1,10 @@
1
- Metadata-Version: 2.3
2
- Name: adloop
3
- Version: 0.13.2
4
- Summary: The AI command center for Google Ads, GA4, and tracking code.
5
- Keywords: mcp,google-ads,google-analytics,ga4,cursor,marketing
6
- Author: Daniel Klose
7
- Author-email: Daniel Klose <info@daniel-klose.com>
8
- License: MIT
9
- Requires-Dist: fastmcp>=3.0.0
10
- Requires-Dist: google-ads>=31.1.0
11
- Requires-Dist: google-analytics-data>=0.20.0
12
- Requires-Dist: google-analytics-admin>=0.27.0
13
- Requires-Dist: google-api-python-client>=2.100.0
14
- Requires-Dist: google-auth-oauthlib>=1.0.0
15
- Requires-Dist: google-api-python-client>=2.0.0
16
- Requires-Dist: pyyaml>=6.0
17
- Requires-Dist: pytest>=8.0 ; extra == 'dev'
18
- Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
19
- Requires-Python: >=3.11
20
- Project-URL: Homepage, https://github.com/kLOsk/adloop
21
- Project-URL: Repository, https://github.com/kLOsk/adloop
22
- Project-URL: Issues, https://github.com/kLOsk/adloop/issues
23
- Project-URL: Changelog, https://github.com/kLOsk/adloop/releases
24
- Provides-Extra: dev
25
- Description-Content-Type: text/markdown
1
+ <!-- mcp-name: com.getadloop/adloop -->
26
2
 
27
3
  <div align="center">
28
4
 
29
5
  # AdLoop
30
6
 
31
- **The AI command center for Google Ads, GA4, and tracking code.**
7
+ **The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.**
32
8
 
33
9
  [![PyPI](https://img.shields.io/pypi/v/adloop.svg)](https://pypi.org/project/adloop/)
34
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
@@ -38,14 +14,14 @@ Description-Content-Type: text/markdown
38
14
  [![GA4 Data API](https://img.shields.io/badge/GA4-Data%20API-E37400.svg?logo=google-analytics&logoColor=white)](https://developers.google.com/analytics/devguides/reporting/data/v1)
39
15
  [![GitHub stars](https://img.shields.io/github/stars/kLOsk/adloop?style=social)](https://github.com/kLOsk/adloop)
40
16
 
41
- An MCP server that gives your AI assistant read + write access to Google Ads and GA4 — with safety guardrails that prevent accidental spend.
17
+ An MCP server that gives your AI assistant read + write access to Google Ads, Reddit Ads and GA4 — with safety guardrails that prevent accidental spend.
42
18
 
43
- **[☁️ Skip the setup — use AdLoop Cloud (free beta)](https://getadloop.com)** &nbsp;·&nbsp; or self-host: `pip install adloop`
19
+ **[☁️ Skip the setup — use AdLoop Cloud (free plan, no card)](https://getadloop.com)** &nbsp;·&nbsp; or self-host: `pip install adloop`
44
20
 
45
21
  </div>
46
22
 
47
23
  > [!TIP]
48
- > **[AdLoop Cloud](https://getadloop.com) is the hosted version of this project — live now, free during beta (limited seats).** Connect Google in two clicks and use the full toolset from claude.ai, ChatGPT, Claude Code, Cursor, or Gemini. No Google Cloud project, no developer token, no OAuth verification wait. EU-hosted, GDPR-first, DPA included.
24
+ > **[AdLoop Cloud](https://getadloop.com) is the hosted version of this project, with a free plan that needs no credit card.** Connect Google in two clicks and use the full toolset from claude.ai, ChatGPT, Claude Code, Cursor, or Gemini. No Google Cloud project, no developer token, no OAuth verification wait. EU-hosted, GDPR-first, DPA included.
49
25
 
50
26
  > 📚 **Documentation: [docs.getadloop.com](https://docs.getadloop.com)** — setup guides per AI client, toolsets, the safety model, and troubleshooting for both editions.
51
27
 
@@ -63,7 +39,7 @@ Both versions run the same tools with the same safety model. The difference is w
63
39
  | **Works with** | claude.ai, ChatGPT, Claude Code, Cursor, Gemini | Claude Code, Cursor, Claude Desktop, any local MCP client |
64
40
  | **Where your data flows** | EU servers (Germany), GDPR-first, DPA included | 100% your machine — nothing leaves it |
65
41
  | **Updates** | Automatic | `pip install -U adloop` |
66
- | **Price** | Free during beta | Free forever (MIT) |
42
+ | **Price** | Free plan, no card; [paid plans](https://getadloop.com/preise) for more accounts and volume | Free forever (MIT) |
67
43
 
68
44
  **Not sure? [Start with Cloud](https://getadloop.com)** — it's the fastest way to see what AdLoop can do, and it's the only way to use AdLoop from claude.ai or ChatGPT. Self-host when you want everything on your own machine or need to modify the code. And if you're here to hack on AdLoop itself: welcome, keep scrolling.
69
45
 
@@ -195,6 +171,27 @@ These tools read the live GTM container and join it with the codebase + GA4 to f
195
171
 
196
172
  > **Setup for GSC tools** — Enable the **Search Console API** in your GCP project. Upgrading OAuth users must re-authorize once for the new scope (delete `~/.adloop/token.json`, run any tool). The killer combo: cross-reference organic queries with `get_keyword_performance` to find paid/organic cannibalization and untapped keyword opportunities.
197
173
 
174
+ ### Reddit Ads Tools
175
+
176
+ A second ad platform, same safety model. Reddit is a separate connection: its own developer app, its own OAuth, no developer token and no approval process. Every tool takes `ad_account_id` (defaults to `reddit.ad_account_id`).
177
+
178
+ | Tool | What It Does |
179
+ |------|-------------|
180
+ | `list_reddit_accounts` | Discover businesses and ad accounts (currency, time zone, approval state) |
181
+ | `list_reddit_funding_instruments` | Billing instruments and posting profiles — prerequisites for creating campaigns and ads |
182
+ | `get_reddit_campaigns` / `get_reddit_ad_groups` / `get_reddit_ads` | Structure with configured vs effective status, budgets, bids, pixel, targeting, weekly schedule, rejection reasons; `include_copy` returns each ad's post (headline, body, destination, media) |
183
+ | `get_reddit_performance` | Spend, clicks, CTR, CPC, conversions, CPA, ROAS per account/campaign/ad group/ad, optional breakdown (date, country, community, keyword, placement, …), compact mode with insights |
184
+ | `run_reddit_report` | Raw reports endpoint for any metric (REACH, video, per-event conversions) |
185
+ | `get_reddit_pixels` | Pixels and when each event last fired — flags ad groups optimizing for events the pixel never sent |
186
+ | `search_reddit_targeting` | Communities, interests, geolocations, languages, keyword suggestions, and Reddit's related-community suggestions (by seed communities or website) |
187
+ | `get_reddit_account_history` | Who changed what and when: field, before/after, member |
188
+ | `estimate_reddit_ad_group` | Audience size, delivery estimate and suggested bid range for a planned ad group (Reddit's counterpart of `estimate_budget`) |
189
+ | `pause_reddit_entity` / `enable_reddit_entity` / `remove_reddit_entity` | Status changes through the preview gate (remove = ARCHIVE, irreversible, double-confirmed) |
190
+ | `update_reddit_campaign` / `update_reddit_ad_group` / `update_reddit_ad` | Budget, bid, run dates, weekly schedule (day names, viewer-local hours), targeting and placements (validated with Reddit at draft time), landing URL and comment changes with old → new previews, budget cap and bid-increase guards |
191
+ | `draft_reddit_campaign` / `draft_reddit_ad_group` / `draft_reddit_ad` | Create campaign → ad group (pixel + targeting required) → post + ad, or promote an existing post with `post_id`. Everything is created **PAUSED**. |
192
+
193
+ > **Setup for Reddit Ads tools** — In Reddit Ads Manager open **Business Manager → Developer Application → Create app** (business admins only; no approval wait). Register the redirect URL exactly as `http://localhost:8765/callback`, then run `adloop init` and complete the Reddit Ads step: it opens Reddit's consent page (scopes `adsread` + `adsedit`, permanent grant), stores the refresh token at `~/.adloop/reddit_token.json`, and lets you pick the default ad account. Reddit rate-limits per user (reporting: 60 requests/min) and requires a descriptive User-Agent, which AdLoop builds from your app id and Reddit username. Reddit has no validate-only mode, so `confirm_and_apply(dry_run=true)` re-reads the target and re-checks the safety caps instead.
194
+
198
195
  ### Planning Tools
199
196
 
200
197
  | Tool | What It Does |
@@ -444,6 +441,10 @@ All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](
444
441
  | `ads` | `developer_token` | — | Your Google Ads API developer token |
445
442
  | `ads` | `customer_id` | — | Default Google Ads customer ID (auto-discovered by `adloop init`) |
446
443
  | `ads` | `login_customer_id` | — | Your MCC account ID |
444
+ | `reddit` | `client_id` / `client_secret` | *(empty)* | Your Reddit developer app (Business Manager → Developer Application) |
445
+ | `reddit` | `ad_account_id` | *(empty)* | Default Reddit ad account for every Reddit tool (picked by `adloop init`) |
446
+ | `reddit` | `username` | *(empty)* | Your Reddit username, used only in the User-Agent Reddit requires |
447
+ | `reddit` | `token_path` | `~/.adloop/reddit_token.json` | Where the Reddit refresh token is stored |
447
448
  | `safety` | `max_daily_budget` | `50.00` | Maximum allowed daily budget per campaign |
448
449
  | `safety` | `require_dry_run` | `true` | Force all writes to dry-run mode |
449
450
  | `safety` | `two_phase_apply` | `false` | Refuse real applies until the plan had a dry-run pass |
@@ -466,6 +467,7 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
466
467
  | `gsc` | Search Console reads |
467
468
  | `web` | PageSpeed / Core Web Vitals |
468
469
  | `merchant` | Merchant Center feed health |
470
+ | `reddit` | Reddit Ads reads, writes, and planning |
469
471
 
470
472
  `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,ga4` drops the session cost to ~13k tokens, and a `ga4`-only client pays ~2k — nearly 90% less. Toolsets are per *client*, not per install: one AdLoop config can serve a trimmed Cursor and a full-catalog Claude Code side by side.
471
473
 
@@ -476,7 +478,7 @@ On [AdLoop Cloud](https://getadloop.com), the same feature is per API key: pick
476
478
  ```
477
479
  src/adloop/
478
480
  ├── __init__.py # Entry point — routes 'adloop init' to wizard, otherwise starts MCP server
479
- ├── server.py # FastMCP server — 67 tool registrations with safety annotations
481
+ ├── server.py # FastMCP server — every tool registration with safety annotations and toolset tags
480
482
  ├── config.py # Config loader (~/.adloop/config.yaml)
481
483
  ├── auth.py # OAuth 2.0 flow (user-supplied credentials, headless fallback) + service accounts; GA4 / Ads / GTM scopes
482
484
  ├── cli.py # Interactive 'adloop init' setup wizard
@@ -496,6 +498,11 @@ src/adloop/
496
498
  ├── gtm/
497
499
  │ ├── client.py # Google Tag Manager API v2 client
498
500
  │ └── read.py # Live container fetching, tag/trigger/variable parsing, workspace diff, version history
501
+ ├── reddit/
502
+ │ ├── auth.py # Reddit OAuth2 (own app, permanent refresh token, loopback flow for adloop init)
503
+ │ ├── client.py # Reddit Ads API v3 REST client — bearer refresh, per-user rate limits, pagination
504
+ │ ├── read.py # Accounts, campaigns, ad groups, ads, performance reports, pixels, targeting lookups
505
+ │ └── write.py # Draft/preflight/apply for status, budget, bid, targeting, and PAUSED creation
499
506
  └── safety/
500
507
  ├── guards.py # Budget caps, bid limits, blocked operations, Broad Match safety
501
508
  ├── preview.py # Change plans and previews
@@ -517,7 +524,7 @@ What's been shipped and what's next:
517
524
  - ~~Claude Code support~~ ✓ — `CLAUDE.md`, `.mcp.json`, `.claude/rules/`, `.claude/commands/`, CLI wizard snippets
518
525
  - **Claude Desktop one-click install** — `adloop install claude-desktop` (and/or a `.dxt` extension bundle) that writes the AdLoop MCP entry into `claude_desktop_config.json` automatically, so Claude Desktop + Cowork users don't have to hand-edit JSON
519
526
  - ~~PyPI package~~ ✓ — `pip install adloop`
520
- - ~~[AdLoop Cloud](https://getadloop.com)~~ ✓ — the hosted version, live in beta: no Google Cloud project, no developer token, connect Google in two clicks (EU-hosted, GDPR-first)
527
+ - ~~[AdLoop Cloud](https://getadloop.com)~~ ✓ — the hosted version: no Google Cloud project, no developer token, connect Google in two clicks (EU-hosted, GDPR-first)
521
528
  - ~~Headless server support~~ ✓ — manual URL copy-paste flow for servers without a browser
522
529
  - ~~Behavioral eval suites~~ ✓ — 28 prompt-and-expectation tests covering read, write, tracking, and planning workflows
523
530
  - ~~Google Tag Manager integration~~ ✓ — read tools for tags, triggers, variables, workspaces, and version history, plus the `audit_event_coverage` three-way join across codebase events, GTM tags, and GA4 actual fires
@@ -1,12 +1,13 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.13.2"
4
- description = "The AI command center for Google Ads, GA4, and tracking code."
3
+ version = "0.14.0"
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"
7
7
  keywords = [
8
8
  "mcp",
9
9
  "google-ads",
10
+ "reddit-ads",
10
11
  "google-analytics",
11
12
  "ga4",
12
13
  "cursor",
@@ -21,6 +22,7 @@ dependencies = [
21
22
  "google-auth-oauthlib>=1.0.0",
22
23
  "google-api-python-client>=2.0.0",
23
24
  "pyyaml>=6.0",
25
+ "requests>=2.31",
24
26
  ]
25
27
 
26
28
  [[project.authors]]
@@ -1,14 +1,14 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.13.2"
4
- description = "The AI command center for Google Ads, GA4, and tracking code."
3
+ version = "0.14.0"
4
+ description = "The AI command center for Google Ads, Reddit Ads, GA4, and tracking code."
5
5
  readme = "README.md"
6
6
  authors = [
7
7
  { name = "Daniel Klose", email = "info@daniel-klose.com" }
8
8
  ]
9
9
  requires-python = ">=3.11"
10
10
  license = { text = "MIT" }
11
- keywords = ["mcp", "google-ads", "google-analytics", "ga4", "cursor", "marketing"]
11
+ keywords = ["mcp", "google-ads", "reddit-ads", "google-analytics", "ga4", "cursor", "marketing"]
12
12
  dependencies = [
13
13
  "fastmcp>=3.0.0",
14
14
  "google-ads>=31.1.0",
@@ -18,6 +18,9 @@ dependencies = [
18
18
  "google-auth-oauthlib>=1.0.0",
19
19
  "google-api-python-client>=2.0.0",
20
20
  "pyyaml>=6.0",
21
+ # Reddit Ads has no SDK; the REST client (adloop.reddit.client) and the
22
+ # PageSpeed helper call requests directly.
23
+ "requests>=2.31",
21
24
  ]
22
25
 
23
26
  [project.urls]