adloop 0.1.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.1.0/PKG-INFO +382 -0
- adloop-0.1.0/README.md +362 -0
- adloop-0.1.0/pyproject.toml +29 -0
- adloop-0.1.0/src/adloop/__init__.py +21 -0
- adloop-0.1.0/src/adloop/__main__.py +5 -0
- adloop-0.1.0/src/adloop/ads/__init__.py +0 -0
- adloop-0.1.0/src/adloop/ads/client.py +41 -0
- adloop-0.1.0/src/adloop/ads/forecast.py +156 -0
- adloop-0.1.0/src/adloop/ads/gaql.py +178 -0
- adloop-0.1.0/src/adloop/ads/read.py +238 -0
- adloop-0.1.0/src/adloop/ads/write.py +950 -0
- adloop-0.1.0/src/adloop/auth.py +132 -0
- adloop-0.1.0/src/adloop/cli.py +375 -0
- adloop-0.1.0/src/adloop/config.py +102 -0
- adloop-0.1.0/src/adloop/crossref.py +509 -0
- adloop-0.1.0/src/adloop/ga4/__init__.py +0 -0
- adloop-0.1.0/src/adloop/ga4/client.py +31 -0
- adloop-0.1.0/src/adloop/ga4/reports.py +141 -0
- adloop-0.1.0/src/adloop/ga4/tracking.py +36 -0
- adloop-0.1.0/src/adloop/safety/__init__.py +0 -0
- adloop-0.1.0/src/adloop/safety/audit.py +40 -0
- adloop-0.1.0/src/adloop/safety/guards.py +56 -0
- adloop-0.1.0/src/adloop/safety/preview.py +58 -0
- adloop-0.1.0/src/adloop/server.py +778 -0
- adloop-0.1.0/src/adloop/tracking.py +244 -0
adloop-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: adloop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server connecting Google Ads + GA4 + codebase into one AI-driven feedback loop
|
|
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>=29.0.0
|
|
11
|
+
Requires-Dist: google-analytics-data>=0.20.0
|
|
12
|
+
Requires-Dist: google-analytics-admin>=0.27.0
|
|
13
|
+
Requires-Dist: google-auth-oauthlib>=1.0.0
|
|
14
|
+
Requires-Dist: pyyaml>=6.0
|
|
15
|
+
Requires-Dist: pytest>=8.0 ; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
<div align="center">
|
|
22
|
+
|
|
23
|
+
# AdLoop
|
|
24
|
+
|
|
25
|
+
**MCP server that connects Google Ads + Google Analytics (GA4) into one AI-driven feedback loop inside your IDE.**
|
|
26
|
+
|
|
27
|
+
[](LICENSE)
|
|
28
|
+
[](https://www.python.org/downloads/)
|
|
29
|
+
[](https://modelcontextprotocol.io)
|
|
30
|
+
[](https://developers.google.com/google-ads/api/docs/start)
|
|
31
|
+
[](https://developers.google.com/analytics/devguides/reporting/data/v1)
|
|
32
|
+
[](https://github.com/kLOsk/adloop)
|
|
33
|
+
|
|
34
|
+
*26 tools · Read + Write · Safety-first · GDPR-aware*
|
|
35
|
+
|
|
36
|
+
> "You built your product with AI. Now manage your ads the same way."
|
|
37
|
+
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Why
|
|
43
|
+
|
|
44
|
+
Solo founders and small teams ship products fast with AI-assisted coding — but managing Google Ads still means switching between the Ads UI, GA4 dashboards, and your code editor. Whether you're running a SaaS, an e-commerce store, a local service, or anything else you drive traffic to with Google Ads — the workflow is the same fragmented mess.
|
|
45
|
+
|
|
46
|
+
AdLoop brings the entire **build → ship → market → measure → iterate** cycle into your IDE.
|
|
47
|
+
|
|
48
|
+
One MCP server gives your AI assistant access to both Google Analytics and Google Ads (read + write), with a safety layer that prevents accidental spend. Combined with your codebase context, it can do things no dashboard can — like diagnosing why conversions dropped by cross-referencing ad traffic, analytics events, and your actual frontend code.
|
|
49
|
+
|
|
50
|
+
## What's Included — 26 Tools
|
|
51
|
+
|
|
52
|
+
> **Quick start:** `git clone https://github.com/kLOsk/adloop.git && cd adloop && uv sync && uv run adloop init`
|
|
53
|
+
|
|
54
|
+
### Diagnostics
|
|
55
|
+
|
|
56
|
+
| Tool | What It Does |
|
|
57
|
+
|------|-------------|
|
|
58
|
+
| `health_check` | Test OAuth, GA4, and Ads connectivity in one call — actionable error messages if anything is broken. Also reports the pinned Google Ads API version and warns if a newer version is available. |
|
|
59
|
+
|
|
60
|
+
### GA4 Read Tools
|
|
61
|
+
|
|
62
|
+
| Tool | What It Does |
|
|
63
|
+
|------|-------------|
|
|
64
|
+
| `get_account_summaries` | List GA4 accounts and properties |
|
|
65
|
+
| `run_ga4_report` | Custom reports — sessions, users, conversions, page performance |
|
|
66
|
+
| `run_realtime_report` | Live data — verify tracking fires after deploys |
|
|
67
|
+
| `get_tracking_events` | All configured events and their volume |
|
|
68
|
+
|
|
69
|
+
### Google Ads Read Tools
|
|
70
|
+
|
|
71
|
+
| Tool | What It Does |
|
|
72
|
+
|------|-------------|
|
|
73
|
+
| `list_accounts` | Discover accessible Ads accounts |
|
|
74
|
+
| `get_campaign_performance` | Campaign metrics — impressions, clicks, cost, conversions, CPA |
|
|
75
|
+
| `get_ad_performance` | Ad copy analysis — headlines, descriptions, CTR |
|
|
76
|
+
| `get_keyword_performance` | Keywords — quality scores, competitive metrics |
|
|
77
|
+
| `get_search_terms` | What users actually searched before clicking |
|
|
78
|
+
| `get_negative_keywords` | List existing negative keywords for a campaign or all campaigns |
|
|
79
|
+
| `run_gaql` | Arbitrary GAQL queries for anything else |
|
|
80
|
+
|
|
81
|
+
### Cross-Reference Tools (GA4 + Ads Combined)
|
|
82
|
+
|
|
83
|
+
These tools call both APIs internally and return unified results with auto-generated insights. They're the core of what makes AdLoop different from having separate GA4 and Ads tools.
|
|
84
|
+
|
|
85
|
+
| Tool | What It Does |
|
|
86
|
+
|------|-------------|
|
|
87
|
+
| `analyze_campaign_conversions` | Maps Ads clicks → GA4 sessions → conversions per campaign. Detects GDPR consent gaps, computes real CPA, compares paid vs organic channels. |
|
|
88
|
+
| `landing_page_analysis` | Joins ad final URLs with GA4 page data. Shows conversion rate, bounce rate, and engagement per landing page. Flags pages with paid traffic but zero conversions. |
|
|
89
|
+
| `attribution_check` | Compares Ads-reported conversions vs GA4 events. Diagnoses whether discrepancies are from GDPR consent, attribution windows, or broken tracking. |
|
|
90
|
+
|
|
91
|
+
### Tracking Tools
|
|
92
|
+
|
|
93
|
+
| Tool | What It Does |
|
|
94
|
+
|------|-------------|
|
|
95
|
+
| `validate_tracking` | Compare event names found in your codebase against what GA4 actually records. Returns matched, missing, and unexpected events with diagnostics. |
|
|
96
|
+
| `generate_tracking_code` | Generate ready-to-paste GA4 gtag JavaScript for any event, with recommended parameters for well-known events (sign_up, purchase, etc.) and optional trigger wrappers. |
|
|
97
|
+
|
|
98
|
+
### Planning Tools
|
|
99
|
+
|
|
100
|
+
| Tool | What It Does |
|
|
101
|
+
|------|-------------|
|
|
102
|
+
| `estimate_budget` | Forecast clicks, impressions, and cost for a set of keywords using Google Ads Keyword Planner. Supports geo/language targeting. Essential for budget planning before launching campaigns. |
|
|
103
|
+
|
|
104
|
+
### Google Ads Write Tools
|
|
105
|
+
|
|
106
|
+
All write operations follow a **draft → preview → confirm** workflow. Nothing executes without explicit approval.
|
|
107
|
+
|
|
108
|
+
| Tool | What It Does |
|
|
109
|
+
|------|-------------|
|
|
110
|
+
| `draft_campaign` | Create a full campaign structure — budget + campaign (PAUSED) + ad group + optional keywords. Validates bidding strategy, enforces budget caps, rejects unsafe BROAD match + Manual CPC combinations. |
|
|
111
|
+
| `draft_responsive_search_ad` | Create RSA preview (3-15 headlines ≤30 chars, 2-4 descriptions ≤90 chars). Warns if headline/description count is below best practice. |
|
|
112
|
+
| `draft_keywords` | Propose keyword additions with match types. Proactively checks bidding strategy — blocks BROAD match on Manual CPC campaigns. |
|
|
113
|
+
| `add_negative_keywords` | Propose negative keywords to reduce wasted spend |
|
|
114
|
+
| `pause_entity` | Pause a campaign, ad group, ad, or keyword |
|
|
115
|
+
| `enable_entity` | Re-enable a paused entity |
|
|
116
|
+
| `remove_entity` | Permanently remove an entity (irreversible — prefers pause). Supports keywords, negative keywords, ads, ad groups, campaigns. |
|
|
117
|
+
| `confirm_and_apply` | Execute a previously previewed change |
|
|
118
|
+
|
|
119
|
+
### Orchestration Rules
|
|
120
|
+
|
|
121
|
+
AdLoop ships with orchestration rules that teach the AI *how* to combine these tools — marketing workflows, GAQL syntax, safety protocols, GDPR awareness, and best practices. Without rules, the AI has tools but doesn't know the playbook.
|
|
122
|
+
|
|
123
|
+
- **Cursor**: `.cursor/rules/adloop.mdc` (canonical source)
|
|
124
|
+
- **Claude Code**: `.claude/rules/adloop.md` (synced from Cursor rules via `scripts/sync-rules.py`)
|
|
125
|
+
|
|
126
|
+
The rules include:
|
|
127
|
+
- **Orchestration patterns** for common workflows (performance review, conversion diagnosis, campaign creation, negative keyword hygiene, tracking validation, budget planning, landing page analysis)
|
|
128
|
+
- **GAQL quick reference** with syntax, common queries, and gotchas
|
|
129
|
+
- **Safety rules** including Broad Match + Manual CPC prevention and pre-write validation
|
|
130
|
+
- **Ad copy character limit guidance** (30-char headlines are shorter than you think)
|
|
131
|
+
- **GDPR consent awareness** to prevent false tracking diagnoses in EU markets
|
|
132
|
+
|
|
133
|
+
### Slash Commands (Claude Code)
|
|
134
|
+
|
|
135
|
+
AdLoop includes pre-built slash commands in `.claude/commands/` for common workflows:
|
|
136
|
+
|
|
137
|
+
| Command | What It Does |
|
|
138
|
+
|---------|-------------|
|
|
139
|
+
| `/analyze-performance` | Full performance review across Google Ads + GA4 |
|
|
140
|
+
| `/create-ad` | Create a responsive search ad with safety checks |
|
|
141
|
+
| `/diagnose-tracking` | Diagnose tracking and conversion issues |
|
|
142
|
+
| `/optimize-campaign` | Full optimization checklist for a campaign |
|
|
143
|
+
| `/create-campaign` | Create a new search campaign with budget estimation |
|
|
144
|
+
| `/budget-plan` | Estimate budget for keywords via Keyword Planner |
|
|
145
|
+
|
|
146
|
+
## Safety Model
|
|
147
|
+
|
|
148
|
+
AdLoop manages real ad spend, so safety is not optional.
|
|
149
|
+
|
|
150
|
+
- **Two-step writes.** Every mutation returns a preview first. A separate `confirm_and_apply` call is required to execute.
|
|
151
|
+
- **Dry-run by default.** Even `confirm_and_apply` defaults to `dry_run=true`. Real changes require explicit `dry_run=false`.
|
|
152
|
+
- **Budget caps.** Configurable maximum daily budget — the server rejects anything above the cap.
|
|
153
|
+
- **Audit log.** Every operation (including dry runs) is logged to `~/.adloop/audit.log`.
|
|
154
|
+
- **New campaigns and ads are PAUSED.** Nothing goes live without manual enablement.
|
|
155
|
+
- **Destructive ops require double confirmation.** Removing entities or large budget increases trigger extra warnings.
|
|
156
|
+
- **Broad Match + Manual CPC blocked.** The #1 cause of wasted ad spend is automatically prevented — `draft_keywords` refuses to add BROAD match keywords to campaigns without Smart Bidding.
|
|
157
|
+
- **Pre-write validation.** Before any write, the AI checks bidding strategy, conversion tracking status, and quality scores. If the campaign is fundamentally broken, AdLoop warns you instead of making things worse.
|
|
158
|
+
- **Structured error handling.** All tools return actionable error messages with hints instead of raw exceptions. Auth errors include specific re-authorization steps.
|
|
159
|
+
- **API version pinning.** The Google Ads API version is pinned to prevent silent breaking changes from library updates. `health_check` warns when a newer version is available.
|
|
160
|
+
- **Ask mode compatibility.** Read tools declare `readOnlyHint` so they work in Cursor's Ask mode without switching to Agent mode.
|
|
161
|
+
|
|
162
|
+
## Setup
|
|
163
|
+
|
|
164
|
+
### Quick Start (Recommended)
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
git clone https://github.com/kLOsk/adloop.git
|
|
168
|
+
cd adloop
|
|
169
|
+
uv sync
|
|
170
|
+
uv run adloop init
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The `adloop init` wizard walks you through everything:
|
|
174
|
+
|
|
175
|
+
1. **Google Cloud checklist** with clickable links to each setup page
|
|
176
|
+
2. **Credentials** — prompts for your OAuth JSON path, validates the file exists
|
|
177
|
+
3. **GA4 Property ID** — validates numeric format
|
|
178
|
+
4. **Developer Token** — from your Google Ads MCC API Center
|
|
179
|
+
5. **Customer IDs** — auto-formats `1234567890` → `123-456-7890`
|
|
180
|
+
6. **Safety defaults** — budget cap and dry-run preference
|
|
181
|
+
7. **OAuth authorization** — optionally opens your browser to complete auth immediately
|
|
182
|
+
8. **Editor config snippets** — prints MCP configuration for both Cursor and Claude Code
|
|
183
|
+
|
|
184
|
+
### Requirements
|
|
185
|
+
|
|
186
|
+
- Python 3.11+
|
|
187
|
+
- [uv](https://docs.astral.sh/uv/) for package management
|
|
188
|
+
- A Google Cloud project (free tier works)
|
|
189
|
+
- A Google Ads account with an MCC (Manager Account)
|
|
190
|
+
|
|
191
|
+
### Manual Setup (If Not Using the Wizard)
|
|
192
|
+
|
|
193
|
+
<details>
|
|
194
|
+
<summary>Click to expand manual setup steps</summary>
|
|
195
|
+
|
|
196
|
+
#### Step 1 — Google Cloud Project
|
|
197
|
+
|
|
198
|
+
1. Go to [console.cloud.google.com](https://console.cloud.google.com/) and create a new project
|
|
199
|
+
2. Enable these three APIs (search for each in the API Library):
|
|
200
|
+
- **Google Analytics Data API** — for GA4 reports and events
|
|
201
|
+
- **Google Analytics Admin API** — for listing GA4 properties
|
|
202
|
+
- **Google Ads API** — for all ads operations
|
|
203
|
+
|
|
204
|
+
#### Step 2 — OAuth Credentials
|
|
205
|
+
|
|
206
|
+
1. In your Google Cloud project, go to **APIs & Services → Credentials**
|
|
207
|
+
2. Click **Create Credentials → OAuth client ID**
|
|
208
|
+
3. Select **Desktop app** as the application type, give it any name
|
|
209
|
+
4. Download the JSON file and save it as `~/.adloop/credentials.json`
|
|
210
|
+
|
|
211
|
+
On first run, AdLoop opens a browser window where you sign in with your Google account and grant access. The resulting token is saved to `~/.adloop/token.json` and refreshed automatically.
|
|
212
|
+
|
|
213
|
+
> Service accounts are also supported — just place the service account key JSON at the same `credentials_path`. AdLoop detects the file type automatically.
|
|
214
|
+
|
|
215
|
+
#### Step 3 — Google Ads Developer Token
|
|
216
|
+
|
|
217
|
+
1. **Create an MCC** (free) at [ads.google.com/home/tools/manager-accounts](https://ads.google.com/home/tools/manager-accounts/) if you don't have one. Link your regular Google Ads account to it.
|
|
218
|
+
2. In the MCC, go to **Tools & Settings → API Center**
|
|
219
|
+
3. Your **developer token** is shown there. Copy it.
|
|
220
|
+
|
|
221
|
+
Access levels:
|
|
222
|
+
- **Explorer** (automatic) — 2,880 operations/day on production accounts. Enough to get started.
|
|
223
|
+
- **Basic** (requires application) — 15,000 operations/day. Apply through the same API Center page if you need more.
|
|
224
|
+
|
|
225
|
+
#### Step 4 — Find Your IDs
|
|
226
|
+
|
|
227
|
+
| ID | Where to Find It |
|
|
228
|
+
|----|-------------------|
|
|
229
|
+
| **GA4 Property ID** | GA4 → Admin → Property Settings (numeric, e.g. `123456789`) |
|
|
230
|
+
| **Google Ads Customer ID** | Google Ads UI → top bar (e.g. `123-456-7890`) |
|
|
231
|
+
| **MCC Account ID** | MCC UI → top bar (e.g. `123-456-7890`) |
|
|
232
|
+
|
|
233
|
+
#### Step 5 — Install and Configure
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
git clone https://github.com/kLOsk/adloop.git
|
|
237
|
+
cd adloop
|
|
238
|
+
uv sync
|
|
239
|
+
|
|
240
|
+
mkdir -p ~/.adloop
|
|
241
|
+
cp config.yaml.example ~/.adloop/config.yaml
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Edit `~/.adloop/config.yaml` and fill in the values from the previous steps. See [`config.yaml.example`](config.yaml.example) for a fully documented template.
|
|
245
|
+
|
|
246
|
+
#### Step 6 — Connect to Your Editor
|
|
247
|
+
|
|
248
|
+
**Cursor** — Add to your project's `.cursor/mcp.json`:
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"mcpServers": {
|
|
253
|
+
"adloop": {
|
|
254
|
+
"command": "/absolute/path/to/adloop/.venv/bin/python",
|
|
255
|
+
"args": ["-m", "adloop"]
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Then copy `.cursor/rules/adloop.mdc` from this repo into your project's `.cursor/rules/` directory.
|
|
262
|
+
|
|
263
|
+
**Claude Code** — Run:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
claude mcp add --transport stdio adloop -- /absolute/path/to/adloop/.venv/bin/python -m adloop
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Or add to your project's `.mcp.json`:
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"mcpServers": {
|
|
274
|
+
"adloop": {
|
|
275
|
+
"command": "/absolute/path/to/adloop/.venv/bin/python",
|
|
276
|
+
"args": ["-m", "adloop"]
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Then copy `.claude/rules/adloop.md` and `.claude/commands/` from this repo into your project for orchestration rules and slash commands.
|
|
283
|
+
|
|
284
|
+
</details>
|
|
285
|
+
|
|
286
|
+
### Use It
|
|
287
|
+
|
|
288
|
+
Ask your AI assistant things like:
|
|
289
|
+
|
|
290
|
+
- *"How are my Google Ads campaigns performing this month?"*
|
|
291
|
+
- *"Which search terms are wasting budget? Add them as negative keywords."*
|
|
292
|
+
- *"My sign-up conversions dropped — check GA4 and Ads to find out why."*
|
|
293
|
+
- *"Draft a new responsive search ad for my main campaign."*
|
|
294
|
+
- *"Which landing pages get paid traffic but don't convert?"*
|
|
295
|
+
- *"Is my tracking set up correctly? Compare my codebase events against GA4."*
|
|
296
|
+
- *"How much budget would I need for these keywords in Germany?"*
|
|
297
|
+
- *"Create a new search campaign for [product feature] with a €20/day budget."*
|
|
298
|
+
|
|
299
|
+
## Configuration Reference
|
|
300
|
+
|
|
301
|
+
All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](config.yaml.example) for a documented template.
|
|
302
|
+
|
|
303
|
+
| Section | Key | Default | Description |
|
|
304
|
+
|---------|-----|---------|-------------|
|
|
305
|
+
| `google` | `project_id` | — | Your Google Cloud project ID |
|
|
306
|
+
| `google` | `credentials_path` | `~/.adloop/credentials.json` | Path to OAuth client JSON or service account key |
|
|
307
|
+
| `google` | `token_path` | `~/.adloop/token.json` | Where to store the OAuth token (auto-created) |
|
|
308
|
+
| `ga4` | `property_id` | — | Your GA4 property ID (found in GA4 Admin → Property Settings) |
|
|
309
|
+
| `ads` | `developer_token` | — | Your Google Ads API developer token |
|
|
310
|
+
| `ads` | `customer_id` | — | Default Google Ads customer ID |
|
|
311
|
+
| `ads` | `login_customer_id` | — | Your MCC account ID |
|
|
312
|
+
| `safety` | `max_daily_budget` | `50.00` | Maximum allowed daily budget per campaign |
|
|
313
|
+
| `safety` | `require_dry_run` | `true` | Force all writes to dry-run mode |
|
|
314
|
+
| `safety` | `blocked_operations` | `[]` | Operations to block entirely |
|
|
315
|
+
|
|
316
|
+
## Project Structure
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
src/adloop/
|
|
320
|
+
├── __init__.py # Entry point — routes 'adloop init' to wizard, otherwise starts MCP server
|
|
321
|
+
├── server.py # FastMCP server — 26 tool registrations with safety annotations
|
|
322
|
+
├── config.py # Config loader (~/.adloop/config.yaml)
|
|
323
|
+
├── auth.py # OAuth 2.0 Desktop flow + service account support + token refresh handling
|
|
324
|
+
├── cli.py # Interactive 'adloop init' setup wizard
|
|
325
|
+
├── crossref.py # Cross-reference tools (GA4 + Ads combined analysis)
|
|
326
|
+
├── tracking.py # Tracking validation + code generation tools
|
|
327
|
+
├── ga4/
|
|
328
|
+
│ ├── client.py # GA4 Data + Admin API clients
|
|
329
|
+
│ ├── reports.py # Account summaries, reports, realtime
|
|
330
|
+
│ └── tracking.py # Event discovery
|
|
331
|
+
├── ads/
|
|
332
|
+
│ ├── client.py # Google Ads API client (version-pinned)
|
|
333
|
+
│ ├── gaql.py # GAQL query execution with human-readable error parsing
|
|
334
|
+
│ ├── read.py # Campaign, ad, keyword, search term, negative keyword reads
|
|
335
|
+
│ ├── write.py # Draft campaign, RSA, keywords; pause, enable, remove, confirm
|
|
336
|
+
│ └── forecast.py # Budget estimation via Keyword Planner API
|
|
337
|
+
└── safety/
|
|
338
|
+
├── guards.py # Budget caps, bid limits, blocked operations, Broad Match safety
|
|
339
|
+
├── preview.py # Change plans and previews
|
|
340
|
+
└── audit.py # Mutation audit logging
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Built From Real Usage
|
|
344
|
+
|
|
345
|
+
AdLoop isn't a theoretical tool — it's built from running real Google Ads campaigns and hitting real problems. Every tool exists because of an actual situation: needing to diagnose a conversion drop without leaving the IDE, wanting to bulk-add negative keywords after seeing wasted spend in the search terms report, drafting ad variants that match a landing page the AI just helped rewrite.
|
|
346
|
+
|
|
347
|
+
The cross-reference tools exist because we kept manually asking the AI to "get Ads data, then get GA4 data, then compare them" — so we automated the join. The Broad Match + Manual CPC safety rule exists because the AI once created that exact combination and wasted budget. The GDPR consent awareness exists because the AI kept diagnosing normal EU cookie rejection as broken tracking.
|
|
348
|
+
|
|
349
|
+
The best features come from real workflows. If you're using AdLoop and find yourself wishing it could do something it can't, **that's exactly the kind of feedback that shapes what gets built next.** Open an issue describing your situation — not just "add feature X" but "I was trying to do Y and couldn't because Z." The context matters more than the request.
|
|
350
|
+
|
|
351
|
+
## Roadmap
|
|
352
|
+
|
|
353
|
+
What's been shipped and what's next:
|
|
354
|
+
|
|
355
|
+
- ~~GA4 read tools~~ ✓
|
|
356
|
+
- ~~Google Ads read + write tools with safety layer~~ ✓
|
|
357
|
+
- ~~Cross-reference intelligence (campaign→conversion mapping, landing page analysis, attribution comparison)~~ ✓
|
|
358
|
+
- ~~Tracking utilities (validate events against GA4, generate gtag code)~~ ✓
|
|
359
|
+
- ~~Budget estimation via Keyword Planner~~ ✓
|
|
360
|
+
- ~~Setup wizard (`adloop init`)~~ ✓
|
|
361
|
+
- ~~Claude Code support~~ ✓ — `CLAUDE.md`, `.mcp.json`, `.claude/rules/`, `.claude/commands/`, CLI wizard snippets
|
|
362
|
+
- **PyPI package** — `pip install adloop`
|
|
363
|
+
- **Community launch** — HN, Indie Hackers, r/cursor, Twitter
|
|
364
|
+
- **Video walkthrough**
|
|
365
|
+
|
|
366
|
+
## Contributing
|
|
367
|
+
|
|
368
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. The short version: open an issue describing your situation first, then submit a PR if you want to build it.
|
|
369
|
+
|
|
370
|
+
## License
|
|
371
|
+
|
|
372
|
+
MIT — see [LICENSE](LICENSE).
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
<div align="center">
|
|
377
|
+
|
|
378
|
+
**If AdLoop saves you from switching between Google Ads, GA4, and your code editor — [give it a star](https://github.com/kLOsk/adloop).**
|
|
379
|
+
|
|
380
|
+
Made by [@kLOsk](https://github.com/kLOsk)
|
|
381
|
+
|
|
382
|
+
</div>
|