Most SEO workflows are surprisingly disconnected from development.
A typical day looks something like this:
- Write code in your IDE
- Open Google Analytics in a browser
- Open Search Console in another tab
- Open Google Ads Keyword Planner somewhere else
- Try to correlate everything manually
I got tired of switching between dashboards and wondering whether a code change I deployed last week had actually improved anything.
So I decided to bring the data directly into my development workspace.
The goal was simple:
- Run Search Console queries locally
- Pull Google Analytics metrics into reports
- Generate keyword ideas without opening Google Ads
- Keep everything inside the same workspace where I write code
It sounded straightforward.
It wasn't.
Within a few hours I ran into:
- Random
RemoteDisconnectederrors - OAuth refresh tokens expiring
- Google Ads API returning mysterious 404s
- Different Google APIs behaving completely differently despite coming from the same company
Here's what I learned.
Why I Wanted This Setup
I manage websites where search traffic matters.
The problem wasn't accessing the data.
The problem was context switching.
If I wanted to investigate a traffic drop, the workflow looked like this:
- Open Search Console
- Check impressions
- Open Analytics
- Compare engagement metrics
- Open Ads
- Research keywords
- Return to the codebase
I wanted all of that available from scripts running directly inside my workspace.
Instead of:
Browser → Dashboard → Browser → Dashboard
I wanted:
IDE → Data
The Architecture
The final setup ended up looking like this:
Google Analytics 4
│
▼
Google APIs
│
▼
OAuth Authentication
│
▼
Local Python Scripts
│
▼
Markdown Reports
│
▼
IDE Workspace
The idea is simple.
A few Python scripts handle authentication and data collection.
Instead of viewing reports in a browser, the scripts generate Markdown and JSON files directly inside the project.
That means I can inspect performance data without leaving the editor.
Problem #1: Random Connection Failures
The first issue appeared when pulling larger datasets.
Everything worked perfectly.
Until it didn't.
Occasionally Google's servers would simply terminate the connection:
requests.exceptions.ConnectionError:
('Connection aborted.',
RemoteDisconnected('Remote end closed connection without response'))
No useful explanation.
No retry.
Just failure.
At first I assumed I had made a mistake in my implementation.
After more testing, it became obvious that the safest solution was simply to expect failures and retry automatically.
I wrapped requests inside a retry helper with exponential backoff.
def robust_post(url, json=None, retries=5):
for i in range(retries):
try:
return requests.post(url, json=json)
except Exception:
time.sleep(2 ** i)
Nothing revolutionary.
But it dramatically improved reliability.
Lesson learned:
Treat API failures as normal operating conditions rather than exceptional events.
Problem #2: OAuth Tokens Expiring After 7 Days
This one confused me for longer than I'd like to admit.
Everything worked perfectly for about a week.
Then suddenly:
invalid_grant:
Token has been expired or revoked
I regenerated credentials.
Same issue.
Eventually I discovered the cause.
My Google Cloud application was still running in Testing mode.
When an OAuth application remains unpublished, refresh tokens automatically expire after a short period.
The fix wasn't code.
The fix was configuration.
Publishing the OAuth application prevented refresh tokens from being discarded.
Lesson learned:
Before debugging authentication code, verify the OAuth application configuration itself.
Problem #3: Google Ads API 404 Errors
This was the most frustrating bug.
I had valid credentials.
The customer ID was correct.
The endpoint looked correct.
Yet every request returned:
404 Not Found
After far too much debugging, I noticed something subtle.
Google Ads uses endpoint patterns that differ from many other Google APIs.
This works:
customers/{customerId}:searchStream
This doesn't:
customers/{customerId}/searchStream
That tiny colon matters.
Once corrected, everything immediately started working.
Lesson learned:
Never assume consistency across Google's APIs. Verify endpoint syntax against current documentation.
What Ended Up Being Most Useful
I originally built this to view traffic metrics.
The biggest benefit turned out to be something else.
I can now generate reports directly inside the project repository.
Examples:
Search Visibility Reports
Top Queries
Top Pages
Click Trends
Indexing Issues
Analytics Reports
Sessions
Traffic Sources
Engagement Metrics
Keyword Research
Keyword Ideas
Search Volume
Location-Based Suggestions
Because the reports live beside the code, it's much easier to correlate changes and outcomes.
Would I Build It Again?
Yes.
But only because I spend a lot of time working inside development environments.
If you're primarily a marketer, browser dashboards remain easier.
Google's dashboards are polished and require almost no maintenance.
For developers, however, there is something satisfying about treating SEO and analytics as data sources rather than web applications.
Once the authentication headaches were solved, having everything available locally became surprisingly useful.
Final Thoughts
The most interesting part of this project wasn't Google Analytics, Search Console, or Google Ads themselves.
It was realizing how much friction comes from constantly moving between tools.
Developers spend enormous effort reducing friction in software.
Yet many of us still manage performance data by manually clicking through dashboards.
Bringing the data into the workspace didn't magically improve rankings.
But it did make analysis faster, experimentation easier, and reporting significantly less annoying.
If you've built similar local analytics pipelines, I'd be interested to hear what approach you took and what problems you ran into.
Naveen Gaur is a WordPress Performance Specialist & Full-Stack Consultant specializing in speed optimization, Core Web Vitals, and technical audits for high-performance websites.
Top comments (0)