Setup Guide

Build Your Own Ads Reporting Dashboards

A step-by-step walkthrough for recreating two things: a live account health dashboard and a weekly written performance report for a Google Ads account — built entirely by describing what you want, in plain English, to Claude Code. No coding experience required.

Who this is for: anyone managing Google Ads accounts who wants automated reporting, even if you've never opened a terminal, used VS Code, or talked to Claude before. Budget roughly an hour of hands-on setup, plus however long Google takes to approve your API access (often same-day, sometimes a day or two).
Before you start

What you need

Five things, all free or already something you likely have:

  • A Claude account with Claude Code access — a Claude Pro, Max, Team, or Enterprise plan, or API access via the Anthropic Console.Check at claude.ai — Claude Code is the version that can read/write files and run commands on your computer, not the regular chat.
  • A computer you can install software on — Mac or Windows both work. This guide's terminal commands lean Mac/VS Code-flavored; Claude Code will adapt them for Windows if that's what you're on — just tell it your OS.
  • Admin access to a Google Ads Manager (MCC) account — the account that has your client accounts linked underneath it.If you only manage a single account with no MCC, that's fine too — the API access steps are the same.
  • A free Cloudflare account — only needed if you want a shareable web link. Sign up at dash.cloudflare.com. Skip this if you're happy just opening the report as a local file on your own computer.
  • Patience for one slow step — Google's "Basic" developer token access requires a short review.Apply for it as your very first action so it's approved by the time you need it.
Phase 0

Install the tools

Four installs, about fifteen minutes total.

1
VS Code — download and install from code.visualstudio.com, then open it. This is the editor Claude Code runs inside of.
2
Claude Code — inside VS Code, open the Extensions panel (the icon that looks like four squares in the left sidebar) and search for "Claude Code." Install it, then sign in with your Claude account when prompted. This gives you a Claude chat panel that can read and edit files and run terminal commands right inside your project.
3
Python 3 — download from python.org if you're on Windows. On a Mac, open the Terminal app and run python3 --version — if nothing prints, run xcode-select --install and follow the prompts, which installs Python along with it.
4
Node.js — download the "LTS" version from nodejs.org and install it. You won't touch this directly, but it's needed later if you want to publish the dashboard as a shareable website.
Phase 0, continued

Get Google Ads API access

This is the fiddliest part, and it's a one-time setup. You're collecting five pieces of information.

1
Developer token. In the Google Ads UI, switch to your Manager (MCC) account, then go to the wrench icon (Tools & Settings) → Setup → API Center. Apply for a developer token. You'll get "Test account" access instantly — apply for Basic access right away too, since that's what lets you pull real client data, and it goes through a short Google review.
2
OAuth Client ID + Secret. Go to console.cloud.google.com and create a new project (top left dropdown → New Project). Once inside it, go to "APIs & Services" → "Enabled APIs" and enable the Google Ads API. Then go to "Credentials" → "Create Credentials" → "OAuth client ID" → Application type: Desktop app. Save the Client ID and Client Secret it gives you.
3
Refresh token. This is the one manual step worth asking Claude Code for help with directly, since it involves a one-time browser sign-in flow. Once you're inside your project (next section), use this prompt:
Paste into Claude Code
I need to generate a Google Ads API refresh token. I have a Client ID and Client Secret from Google Cloud Console. Can you write and run a small Python script using the google-auth-oauthlib library that opens my browser, has me sign in and approve access with scope https://www.googleapis.com/auth/adwords, and prints out the refresh token?
4
Your Manager account's Customer ID. Log into your MCC in the Google Ads UI — it's the 10-digit number shown top-right, formatted like 123-456-7890.
By the end of this phase you should have
Developer token
a long string from API Center
Client ID
ends in .apps.googleusercontent.com
Client secret
from the same OAuth credential
Refresh token
starts with 1//
Manager customer ID
10 digits, no dashes when you use it
Phase 0, last step

Set up your project folder

1
Create a new, empty folder somewhere on your computer — e.g. Ads Dashboards.
2
In VS Code: File → Open Folder… and select it. This becomes your project root.
3
Create a new file named exactly .env in that folder, and fill it in with the five values you collected above:
KeyExample
GOOGLE_ADS_DEVELOPER_TOKENAbCdEfGh12345...
GOOGLE_ADS_CLIENT_ID123-abc.apps.googleusercontent.com
GOOGLE_ADS_CLIENT_SECRETGOCSPX-...
GOOGLE_ADS_REFRESH_TOKEN1//0g...
GOOGLE_ADS_LOGIN_CUSTOMER_ID1234567890
Keep this private This file grants full access to every Google Ads account under your MCC. Never share it, paste it into a chat, or commit it to a public code repository. If you ever use git, add a .gitignore file containing just .env on its own line.

Everything from here on is a conversation. Open the Claude Code panel in VS Code, and work through these prompts roughly in order — copy one in, let Claude do the work, look at the result, then move to the next. Claude will often ask you clarifying questions first; just answer honestly about your own setup. Nothing below is a rigid script — feel free to phrase things your own way.

Phase 1

Confirm access

Get a working connection before building anything on top of it.

Paste into Claude Code
I have Google Ads API credentials in a .env file in this project (developer token, client id, client secret, refresh token, and login customer id for my manager account). Using the "google-ads" and "python-dotenv" Python libraries, write a script that connects and lists every client account under my manager account, so I can confirm access is working. Then run it.

If it works, you'll see a list of account names and ID numbers print out. If it fails, Claude will usually be able to tell you exactly which credential is wrong — most often it's the Basic access approval still pending, or a typo in the .env file.

Phase 2

Build the audit script

This is the core data-pulling script everything else builds on.

Paste into Claude Code
Now build a script that pulls a 30-day performance snapshot for one client account: campaign list with status, budget, spend, clicks, conversions, search impression share, top search terms with real spend but zero conversions, ad strength distribution, active conversion actions, and shared negative keyword lists. I only want campaigns named starting with "YOUR-PREFIX" included in every number — everything else should be excluded entirely, not just hidden.

Replace YOUR-PREFIX with whatever naming convention your campaigns actually follow — e.g. your agency's initials, or leave this rule out entirely if you don't need it.

Phase 3

Turn it into a website

Paste into Claude Code
I want to see this as a website instead of raw data. Build a single self-contained HTML dashboard: summary stats at the top, a bar chart of accounts by spend, and a searchable, sortable table where each account expands to show its campaigns, wasted search terms, and any account hygiene issues.

Claude will generate an HTML file you can open directly in your browser by double-clicking it — no server needed yet.

Phase 4

Run it across every account

Paste into Claude Code
Can you run this across every client account under my manager account instead of just one, and combine the results into a single report?
Heads up With more than a handful of accounts, this can take several minutes — each account is a separate set of API calls. Claude will typically run it in the background and let you know when it's done.
Phase 5

Apply your business rules

Refine what counts as "real" data for your reporting.

Paste into Claude Code
A few rules to apply everywhere: (1) leave out any account you don't actually have API access to, (2) leave out any campaign not named with our "YOUR-PREFIX" convention, (3) leave out any campaign that's paused with zero spend, clicks, impressions, and conversions in the last 30 days. Apply all three to every number in the report, not just what's displayed.
Phase 6

KPI health colors

The most useful single feature: an at-a-glance red / yellow / green per account.

Paste into Claude Code
For each of our services we have a target cost-per-conversion: Service A $65, Service B $45, Service C $25 (replace with your real services and targets). Detect which service a campaign or ad group belongs to from its name. Mark each account green if every campaign is hitting its target, yellow if some are and some aren't, red if none are or it looks like a billing/serving problem. Let me hover over the color to see exactly why it was scored that way.

Expect some back-and-forth tuning this one — the first version is rarely exactly right. It's normal (and encouraged) to look at the result and say things like "this account should really be green, why isn't it?" — Claude can walk through the exact math with you and adjust the rule.

Phase 7

Style it

Paste into Claude Code
I'd like the design to be light with pastel colors, and forced to always render in light mode regardless of the viewer's system theme — some of the current text is hard to read.

Say exactly what's bothering you — "the yellow looks brown," "I can't read this text," "make the font bigger" — plain feedback like this works better than trying to specify hex codes yourself.

Phase 8

Schedule it automatically

Paste into Claude Code
I want this to run automatically every Monday at 8am, my local timezone. This is a Mac / Windows — what's the best way to schedule it without needing a separate cloud service?

On a Mac, Claude will typically set up a LaunchAgent; on Windows, Task Scheduler. Either way, your computer needs to be on and awake at that time for it to run — it won't retroactively catch up if your laptop was asleep. See Troubleshooting below for a permissions issue that's very likely to come up here.

Phase 9

Host it online & share a link

Paste into Claude Code
I want to send this dashboard to other people as a link instead of a file. What are my options, including whether it can be access-controlled rather than fully public?

Claude will lay out the trade-off directly: a fully public link (simplest, but genuinely public forever to anyone who gets it) versus an access-controlled one (adds a login wall so only specific emails can view it, more setup). Decide based on how sensitive the data is, then follow up:

Paste into Claude Code
Let's go with [the option you picked]. I have a free Cloudflare account already — the login is your-email@example.com.

Claude will use Cloudflare's wrangler command-line tool, which opens a browser tab for you to approve the connection to your Cloudflare account once.

Phase 10

The weekly narrative report

A second, plain-English companion to the dashboard.

Paste into Claude Code
On top of the dashboard, I also want a written weekly report per account, broken down by service: a GOOD / BAD / PLANS paragraph comparing this week against last week and against the last 30 days, plus a portfolio summary of top performers, accounts needing attention, and the biggest week-over-week movers. Generate this every time the dashboard regenerates.
Phase 11 — optional

Extra signals worth asking for

Smaller, standalone additions — ask for any that are useful to you, in any order.

Paste into Claude Code
Also flag keywords (not just search terms) that spent money but got zero conversions in the last 30 days.
Paste into Claude Code
Flag any change made to an account by someone other than me in the last 30 days — I'm your-email@example.com. Show me who, what changed, and when, on hover.
Paste into Claude Code
Pull audience segment performance (in-market, affinity, remarketing lists) for accounts where that data exists, even though most of ours are Search-only campaigns.
Worth knowing upfront If you ask for Auction Insights data (competitor overlap, outranking share), the honest answer is that Google Ads has no API access to it at all — it only exists in the Ads UI. That's not a limitation Claude introduced; it's a genuine, permanent gap in Google's own API.

When something breaks

Troubleshooting

Four issues that came up building this the first time — all fixable, none of them your fault.

"Operation not permitted" when the scheduled job runs macOS blocks background scripts from touching files in Documents/Desktop/Downloads unless you explicitly grant access. Fix: System Settings → Privacy & Security → Full Disk Access → add the exact program running your script (e.g. Python) and turn it on. Adding bash here won't work — it's a protected system file macOS silently ignores.
Scheduled job runs fine, but publishing the site silently fails Background jobs run with a stripped-down system PATH that often can't find Node or other tools. Tell Claude the publish step is failing under the schedule but works when you run it manually — it can hardcode the full path in the script.
"This site can't be reached" right after publishing Usually just DNS catching up — wait a couple of minutes and reload, or try your phone's cellular data to confirm it's live elsewhere. If it persists, your Mac's DNS cache may be stale; switching your network's DNS to 1.1.1.1 or 8.8.8.8 usually clears it.
Auction Insights data isn't available, no matter how you ask Confirmed by testing directly against Google's API — there is no resource for it. UI-only, always.
Last step

Making it yours

Before you call it done, make sure these reflect your agency, not a template:

  • Campaign naming convention — whatever prefix or pattern you used in Phase 2/5.
  • Target CPA per service — your real numbers from Phase 6, not placeholders.
  • Account owner email — used in Phase 11's "changes not made by you" check.
  • Schedule day, time, and timezone — from Phase 8.
  • Sharing model — public link, access-controlled, or manual snapshot — from Phase 9.

None of this has to be perfect on the first pass. The whole point of building it this way is that "this looks wrong, can you fix it" is a completely normal, expected part of the process — every phase above was refined at least once in exactly that way.