Open Search Console and you get the last sixteen months. Come back in a year and the first four of those have gone.
That is not a criticism of the tool, it is how it works. But it does mean that if you want to know whether something you did in March 2025 made a difference, and it is now late 2026, the data to answer that no longer exists.
Writing a row into a sheet every week fixes it permanently, and takes an afternoon.
Why not just use the interface
Three reasons, and none of them is that the interface is bad.
It forgets. Sixteen months rolling. Your own sheet does not.
It shows you a period, not a series. You can compare two date ranges, which answers “is this better than last month” and not “what has this done all year”.
You cannot annotate it. In your own sheet you add a column saying what you changed that week. Six months later, that column is the most valuable thing in the file, because it is the only place the cause and the effect sit next to each other.
Getting the credentials
This is the fiddly part and it is worth being told plainly rather than discovering it.
Create a Google Cloud project. Enable the Google Search Console API on it. Create an OAuth 2.0 Client ID of type Web application, and add n8n’s OAuth redirect URL, which n8n shows you when you create the credential. Then connect it in n8n and authorise with the Google account that has access to the Search Console property.
The two things that catch people: it has to be the account with property access, not just any Google account, and the API has to be enabled on the project or you get a permission error that reads as though your credentials are wrong when they are fine.
Budget fifteen minutes. Nothing after this is difficult.
The build, six nodes
1. Schedule Trigger. Weekly, Monday morning.
2. Code node, called Window. Work out the dates. Do not query up to yesterday:
const end = new Date();
end.setDate(end.getDate() - 3);
const start = new Date(end);
start.setDate(start.getDate() - 6);
const iso = (d) => d.toISOString().slice(0, 10);
return [{ json: { startDate: iso(start), endDate: iso(end) } }];Three days back is the point of this node. Search Console data lags two to three days and is revised after it lands. Query up to yesterday and your newest row is built from partial data, sits lower than it should, and every comparison you make against it afterwards is wrong.
3. HTTP Request, called Query. Against the Search Analytics endpoint, authenticated with the OAuth credential:
POST https://www.googleapis.com/webmasters/v3/sites/
{{ encodeURIComponent('https://yoursite.co.uk/') }}/searchAnalytics/query
{
"startDate": "{{ $json.startDate }}",
"endDate": "{{ $json.endDate }}",
"dimensions": ["query", "page"],
"rowLimit": 1000
}The site URL has to be encoded, including the trailing slash, and it has to match how the property is registered. A domain property looks like sc-domain:yoursite.co.uk instead, which is a different string entirely and the most common reason a first attempt returns a 403.
Two dimensions rather than one is deliberate. Query alone tells you a term moved. Query and page together tells you which page moved, and when two of your pages are competing for the same term, that pair is the only thing that shows it.
4. Split Out. Field rows.
5. Code node, called Shape. Flatten, and stamp the week:
return $input.all().map((i) => ({ json: {
week: $('Window').first().json.endDate,
query: i.json.keys[0],
page: i.json.keys[1],
clicks: i.json.clicks,
impressions: i.json.impressions,
ctr: (i.json.ctr * 100).toFixed(2),
position: i.json.position.toFixed(2),
}}));6. Google Sheets, Append. Append, never clear. This is a log, and the whole value is in the rows you already have.
Add the column the API cannot give you
One more column, filled in by hand: note.
Every time you change something, write a line. “Rewrote the pricing page.” “Added FAQs to three service pages.” “Fixed the internal links after the rename.”
Six months later that column is what turns a spreadsheet of numbers into an answer. Without it you have a record that something moved and no idea why, and you will invent a reason, and the reason will be wrong.
Reading it without fooling yourself
Positions are noisy. They vary by device, by location, by who is searching, and a term can move two places in a week for no reason at all.
Three habits keep you honest.
Look at four weeks, not one. A single week’s movement is almost never real.
Watch impressions alongside position. A term rising from 40 to 25 with no change in impressions has not started earning anything yet. Position 25 is still nobody clicking, and the change only starts to matter under about 10.
Expect the average to drop when things go well. As a page starts appearing for more long-tail terms, its average position gets worse while its traffic gets better, because the new terms it appears for start at the bottom. Average position falling is often the shape of progress, which is the single most misread number in this whole file.
What it does not do
It tracks where you are, not why. It has no competitor data, no search volume figures, and no view of anything outside your own property. Those come from paid tools, and they are worth buying at the point where you have run out of obvious things to fix on your own site rather than before it.
For most small businesses the useful sequence is: this workflow, then the on-page audit, then a look at what competitors cover that you do not. Paid tools after that, if at all.
Published 28 August 2026. Written by the people who run this sort of thing for clients, on n8n, including our own lead pipeline.
Next in getting found online: The competitor content gap check. Or go back to all 4 in this category.