Getting found online

Track your search positions weekly in n8n, free, using Search Console

Search Console shows you a rolling window and no memory. A dated row every week turns that into a history, which is the difference between knowing something worked and believing it did.

Build time
An afternoon
Difficulty
Intermediate
Template
6 nodes

What you need before you start

  • An n8n instance.
  • A verified Search Console property for your site.
  • A Google Cloud project with the Search Console API enabled, and OAuth credentials.
  • A Google Sheet with room to grow, because this one is a log.

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.

Questions about this build

Is Google Search Console data free through the API?

Yes. The Search Analytics API returns the same data the interface shows, at no cost, for any property you have verified. You need a Google Cloud project with the API enabled and OAuth credentials, which is about fifteen minutes of setup and the only genuinely fiddly part of this build.

How far back does Search Console data go?

Sixteen months, on a rolling basis. Month seventeen falls off the back and is gone, which is the whole argument for this workflow: once you are writing a weekly row into your own sheet, your history keeps going after Google's stops.

Why do the numbers not match what I saw yesterday?

Search Console data lags by two to three days and gets revised slightly after it first appears. Always query a window that ends a few days ago rather than yesterday, or your most recent row will be built from incomplete data and every comparison against it will be wrong.

How many rows can I pull at once?

The API returns up to 25,000 rows per request, with startRow for pagination, against a documented export ceiling of 50,000 rows per day per site per search type. A small business site tracking its own queries will not come close, and if you are hitting it you are pulling more detail than you can read.

Should I track positions daily?

No. Positions move on their own from personalisation, location and device, and a daily series is mostly noise with a trend hidden in it. Weekly averages smooth that out and are honest about how quickly anything actually changes.

The next step

Stop losing leads.Let's fix it this week.

Tell us what keeps slipping and we'll scope something around it. You'll be talking to Max, who runs the work, not a sales team. Most clients are live within 48–72 hours of that first conversation.

30-day rolling retainers. No lock-in. Cancel anytime.