SearchOps + n8n
Own your data: a warehouse of every client's profile results, Map Pack history and AI visibility, plus a weekly brief per account written for your team.
n8n is for agencies that want full control. Self-host it for free, pull SearchOps data into your own Postgres or BigQuery, and give each account manager a short weekly brief per client, written by the AI model you choose from numbers SearchOps supplies. One run counts as one execution however many steps it has, so heavy workflows stay cheap.
Your own local SEO warehouse
Profile performance, Map Pack history and AI visibility for every location, in tables you own and can join to sales data.
A brief per client, every Monday
An AI node turns each client's numbers into a short internal note: what moved, what we did, what to do next.
Verified events only
A Code node checks every webhook signature before anything runs.
Cheap at scale
Self-hosted n8n is free; n8n Cloud counts one execution per run, not per step.
Recipes
What agencies build with n8n
Weekly warehouse load
GET /profile/performance, /grid-history, /ai-visibilityAgencies with their own BI or a data person
- 1Schedule Trigger, weekly.
- 2HTTP Request to /api/v1/locations with Bearer Auth, paginating with limit and offset.
- 3Per location: /profile/performance?months=1, /keywords/{keywordId}/grid-history and /ai-visibility?engine=chatgpt.
- 4Insert into Postgres or BigQuery, keyed on location and week, then chart it in your BI tool.
Monday account brief, written per client
GET /week, /geo-grid/insightsAccount managers with ten or more clients
- 1Schedule Trigger on Monday morning, then loop over each client's locations.
- 2HTTP: /locations/{id}/week (results and tasks done) and /locations/{id}/geo-grid/insights (why rivals win).
- 3AI node with your own model: write five lines (what moved, what we did, what to do next), from the numbers only.
- 4Create a Notion page or Slack message for the account manager. Internal only: a person decides what reaches the client.
Verified event router
all eventsTeams that want signatures checked before acting
- 1Webhook node, POST, Respond Immediately, Raw Body on.
- 2Code node with the verification snippet below.
- 3Switch on type: geo_grid.moved to the account channel, profile.changed to #ops, task.completed to the client's work log.
Setup
Connect n8n, step by step
- 1
Add a Webhook node or a Schedule Trigger
For events, add a Webhook node: POST, Respond Immediately, Raw Body on if you'll verify signatures, and copy the Production URL (the Test URL only works while listening). For reports, start with a Schedule Trigger.
- 2
Add the webhook in SearchOps
In SearchOps, open Developers, then Webhooks, and choose Add webhook. Paste the URL from the n8n Webhook node (the Production URL), tick the events you want and, for a client-specific workflow, pick that client's locations. Save, and copy the signing secret somewhere safe: it is shown once.
- 3
Publish the workflow
The Production URL only receives events once the workflow is published (active). Publish it, then send the test.
- 4
Send a test event
Back in SearchOps, press Send test on the endpoint. The test event has the same envelope as real events but a short sample body. To map review or scan fields, wait for a real event of that type or replay one from Deliveries, then use that as your sample.
- 5
Verify the signature
Add a Code node set to Run Once for Each Item with the snippet below. n8n's built-in Crypto node can't decode the whsec_ secret, so use code. On self-hosted n8n, allow the crypto module with NODE_FUNCTION_ALLOW_BUILTIN=crypto.
Code node// Code node, "Run Once for Each Item", after a Webhook node with Raw Body on. const crypto = require('crypto'); const secret = 'whsec_...'; // from SearchOps, ideally from a credential or variable const h = $json.headers; const id = h['webhook-id'], ts = h['webhook-timestamp'], sigs = h['webhook-signature'] || ''; const bin = $input.item.binary && $input.item.binary.data; const raw = bin ? Buffer.from(bin.data, 'base64').toString('utf8') : JSON.stringify($json.body); if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) throw new Error('stale webhook'); const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64'); const expected = crypto.createHmac('sha256', key).update(`${id}.${ts}.${raw}`).digest(); const ok = sigs.split(' ').some((entry) => { const [version, sig] = entry.split(','); if (version !== 'v1' || !sig) return false; const given = Buffer.from(sig, 'base64'); return given.length === expected.length && crypto.timingSafeEqual(given, expected); }); if (!ok) throw new Error('bad signature'); return { json: JSON.parse(raw) }; - 6
Call the API
HTTP Request node with the Bearer Auth credential and your SearchOps API key. Base URL https://searchops.co/api/v1; 120 requests a minute per key, so add a short Wait in big loops.
Field reference
The fields you'll map most
From the SearchOps webhook payload. Every event also carries type, id, created_at and the location's id and business name.
| Field | Use it for |
|---|---|
| type | Route by event: geo_grid.moved, scan.completed, profile.changed, task.created, task.planned, task.completed, review.created |
| location.business_name | Which client or branch it is about |
| data.direction | up or down: a grid move beyond normal re-run swing (geo_grid.moved) |
| data.points_gained / data.points_lost | How many grid points entered or left the top 3 (geo_grid.moved) |
| data.keyword / data.engine_label | The keyword and engine: Google Maps, Google Search or AI Mode |
| data.share / data.share_low / data.share_high | Share of answered grid points in the top 3 (or named, for AI Mode), with its likely range |
| data.keyword_url / data.scan_url | Open the keyword's grid history or the scan in SearchOps |
| data.field_label / data.before / data.after | What changed on the Business Profile (profile.changed) |
| data.changed_by | google or someone_else: who changed the profile |
| data.kind / data.severity | verification or duplicate, and how serious the change is |
| data.title / data.completed_at / data.task_url | A task and when it was done: your proof of work (task.created, task.planned, task.completed) |
What you need
- SearchOps Pro, Agency or Enterprise. Webhooks and the API are included; an owner or admin sets them up.
- n8n: self-hosted Community Edition is free. On n8n Cloud, Starter includes 2,500 executions a month; one execution is one run, whatever its length.
- The AI brief uses your own model key in n8n; SearchOps supplies the numbers.
Steps checked against the vendor's own documentation on 12 October 2026. Tools change their menus often; if a step no longer matches, the help article has the latest.
Works well alongside
FAQ
SearchOps and n8n
What can I put in a warehouse?
Anything the 29 read-only endpoints return: Business Profile performance by day, week or month for up to 18 months, search terms, Map Pack grid history per keyword, AI Mode and AI Overview answers, ChatGPT and Gemini visibility, competitors, Search Console and Google Analytics.
Test URL or Production URL?
Paste the Production URL into SearchOps and publish the workflow. The Test URL only works while the editor is listening for a test event.
Why not the Crypto node for signatures?
Our secret is base64 after the whsec_ prefix, and the Crypto node takes the secret as plain text, so its HMAC won't match. The Code node snippet decodes it correctly.