SERP tracking API that tells your code the moment the results page moves.
A SERP tracking API watches a search results page on a schedule and reports what changed on it. Verid points a monitor at the search URL you build, renders it in real Chrome, cuts the page into the fields you named with XPath, CSS, regex or an LLM prompt, compares them against the previous check, and fires an HMAC signed webhook when your rule is met. Down to five minutes per query, on up to 1,500 queries.
It is a rank tracking API for teams that need to react today, not a report to read on Monday. Position is one field on the monitor. So is the AI Overview that pushed you down the page without touching your position at all.
- 5 monitors free, no card
- 5 min fastest check
- 9 alert predicates
- 6 extraction methods
- my_rank
- 3→3
- unchanged
- blocks_above
- 2→5
- +3
- ai_overview
- absent→present
- changed
Straight answers
SERP tracking API at a glance
Twelve answers with no adjectives in them. Every number is read from the shipping product rather than from a sales sheet, and the ones that differ by plan say which plan. If you are comparing this against a rank tracker or a SERP API, the first two rows are the ones that decide it, and the comparison table takes it row by row.
- What it is
- change detection
- Scheduled change detection pointed at search result pages, with the diff and the alert as the product.
- What it is not
- not a scraper
- Not a SERP scraping API. No endpoint takes a bare keyword and hands back a fully parsed results page, which is the difference between scraping and change detection.
- Input
- url + selectors
- A search URL you construct, plus one selector for each element you want to follow over time.
- Output
- diff webhook
- A JSON webhook holding the previous SERP object, the current one, and the list of field names that moved. Full shape in the REST API reference.
- Extraction methods
- 6 methods
- XPath, CSS, regex, JSONPath, whole page text, or an LLM prompt with an optional response schema.
- Alert rules
- 9 predicates
- Any field, one field, four numeric threshold rules, exact value, regex, and a composite of any of those. All nine are documented under predicates.
- Rendering
- browser mode
- Real Chrome with a stealth browser profile, chosen per monitor. Required for Google and Bing results, and the same engine behind screenshots.
- Fastest check
- 5 min on Scale
- Set per monitor in seconds and floored by your plan: daily on Free, hourly on Starter, 15 minutes on Pro. Every floor is on the pricing page.
- Scale unit
- 1,500 queries
- One monitor per query per market. 5 on the permanent Free plan, 250 on Pro, 1,500 on Scale, and the arithmetic for a keyword list is yours to do up front.
- Location control
- query string
- Through the URL itself, using gl, hl, uule and cr. There is no per-monitor exit country to pick, which the location section sets out in full.
- Where alerts land
- 4 channels
- Signed webhook, Slack, Discord or email, up to 25 endpoints on one monitor. See notifications.
- Delivery guarantee
- 6 attempts
- Six attempts spread across two hours, then the dead letter queue, where a delivery can be replayed by hand.
The loop
How SERP monitoring runs on one query, from URL to webhook
Five things happen on every check, in this order, whether the monitor runs once a day or every five minutes. Four of them you configure once and never think about again. The fifth is the only one you ever hear about. Each read below names what it is handed and what it hands on, so the chain is visible rather than implied. It is the same loop behind change detection, competitor monitoring and visual monitoring, pointed at a search result.
Pin the query into a URL
One monitor watches one query, and the query is the URL. Write the parameters you want held constant into it, hl for language, gl for country, pws=0 to strip personalisation, so every check reads the same search from the same angle. A monitor with a moving URL has no baseline worth comparing.
takesa keyword and a market
urlgivesone stable search URL
Render it in real Chrome
Search results are assembled in JavaScript, so fetch_mode is set to browser and the page loads in a real Chrome with a stealth profile rather than an HTTP client. That is not an optimisation here, it is the difference between a full results page and an empty shell.
takesone stable search URL
fetch_mode: browsergivesthe rendered results page
Cut it into named fields
Point a selector at each part you track and it becomes a key in a flat JSON object: your own listing, the first organic result, the AI Overview container, the snippet, the People Also Ask block. XPath and CSS cover structure, regex pulls a number out of a string, and a prompt asks a model for the shape you describe.
takesthe rendered results page
extract_configgivesa SERP object with your field names
Compare it with the last one
The new object is compared key by key against the object stored for the previous run of this monitor. The result is a list of the field names that changed plus the before and after value of each, which is a far smaller thing than two web pages and the reason the alert is readable.
takesa SERP object with your field names
fields_changedgivesthe field level diff
Decide whether it is worth waking anyone
One predicate decides. Any tracked field moving, one named field only, a rank number worsening by three or more, a field going empty, a regex hit, or a composite of those joined with AND or OR. A run that fails the predicate is still recorded, it just does not deliver.
takesthe field level diff
diff_predicategivesa signed webhook, or a quiet run
Two details in read four are worth knowing before you trust an alert. The comparison is against the previous run of the same monitor and nothing else, so a monitor created this morning has no opinion about last week. And a field whose selector stops matching extracts an empty string rather than an error, which is a change like any other: useful when your listing genuinely left the page, and worth checking in the run history when it was the markup that moved instead. To try a selector before it ever reaches a monitor, the playground runs one against a live URL with no account.
see alsothe diff engineREST API referencethe worked SERP examplewhy the loop is the product
Extraction
The results page, cut into fields you named
A monitor does not store a screenshot of a search result and it does not store a rank. It stores a flat JSON object whose keys are the names you chose, and the diff you get is a list of those key names. Six zones and six fields below, with the method that reaches each one. Nothing here is a fixed feature list, which is the reason a block Google ships next year is a new key rather than a support ticket. The engine underneath is documented in extractors, with a guide for every method.
- "ai_overview":"Invoicing software helps small..."xpath
//div[contains(@aria-label,"AI Overview")] - "featured_snippet":"A good invoicing tool should..."xpath
//div[@data-attrid="wa:/description"] - "top_result_url":"https://competitor.com/invoicing"xpath
(//div[@id="search"]//a[h3])[1]/@href - "my_rank":"3"regex
position:\s*(\d+) - "blocks_above":"ads, ai_overview, video_carousel, paa"prompt
List the blocks above the result for our domain, in order - "paa":"Is invoicing software worth it?"css
div[jsname] div[role="heading"]
Values are illustrative of one run. The keys are yours, and the diff names them.
What each field is actually good for
ai_overviewAI OverviewPresence is the signal. An empty string one run and a paragraph the next is the block arriving.
xpath guidefeatured_snippetFeatured snippetWinning or losing the snippet moves clicks harder than the position underneath it ever does.
xpath guidetop_result_urlFirst organic resultA new value here means the page changed hands, whichever direction your own number went.
xpath guidemy_rankYour own listingExtracted as a number so a threshold predicate can fire on it. Higher is worse, so watch increases.
regex guideblocks_aboveEverything above youThe honest answer to how far down the page you landed. A model reads the layout and names the order.
prompt guidepaaPeople Also AskThe questions Google thinks belong to your query, which is a content brief that updates itself.
css guideFive of the six use a selector. The sixth, blocks_above, uses the prompt method: you describe the shape you want and a model reads the rendered page and returns it. That is the method to reach for when the thing you want is a judgement about the layout rather than a node in it, or when the markup keeps breaking your selectors. The LLM call budget on your plan is what bounds it, from 50 calls a month on Free to 25,000 on Scale.
see alsoXPath tutorialXPath vs CSSregex extractionJSONPath on an APItest a selector live
SERP feature tracking
Position three is not a place on the page
A rank number tells you how many organic results are above you. It says nothing about the sponsored block, the AI Overview, the video carousel or the People Also Ask stack that are also above you, and those are what decide whether anybody sees your listing at all. Position can hold at three for a year while the page you are third on quietly grows two screens taller. It is also why rankings appear to drop without warning. SERP feature tracking is how you notice, and here it is the same mechanism as everything else: one field per block, one predicate per question.
The measurement is the set, not a number of pixels
Verid does not measure how far down the page your listing sits, and any tool that hands you a pixel figure is quoting one rendering at one viewport width. What you can hold honestly is the set of blocks above your listing: which ones are present on this check, which were present on the last one, and what entered or left between them. That set is extractable, reproducible, and the same on every run, which a pixel number is not.
Two ways to build it. Extract each block as its own field and let any of them changing fire the alert, which costs you one selector per block and no LLM calls. Or use theprompt method once and ask a model to return the blocks above your result in order, which costs one LLM call per check and survives a markup change that would break a selector.
{ "type": "composite", "operator": "OR", "conditions": [ ... field_changes ... ] }Every block that can sit above you, and how to watch it
| Block | What it does to the page | How you watch it | Field |
|---|---|---|---|
| Sponsored results | Pushes every organic listing down before the page has said anything organic at all. | Count the ad slots as one field and alert when the count changes. | ad_slots |
| AI Overview | The single largest displacement on the page, and it can appear on a query that never had one. | Extract the container. Empty to non empty is the block arriving. | ai_overview |
| Featured snippet | Answers the query above the results, so the click it takes is a click nobody below it gets. | Extract the snippet block on its own field, separate from position. | featured_snippet |
| People Also Ask | Expands as visitors open it, absorbing attention in the middle of the result list. | Extract the first question. New questions mean the intent Google reads has shifted. | paa |
| Video carousel | A horizontal band that costs a full result slot of vertical room wherever it lands. | Extract the carousel container and treat presence as the signal. | video_carousel |
| Local pack | Three map results plus a map, which on a local query is most of the first screen. | Extract the pack, and the three business names if you compete with them. | local_pack |
| Shopping and product grids | Commercial queries hand the top of the page to a product grid without warning. | Extract the grid container. Its arrival usually explains a click through rate drop. | shopping_grid |
| Anything Google ships next | The list above was shorter two years ago and will be longer next year. | A selector is not a fixed feature list, so a new block is a new field, not a product roadmap. | your_field_name |
Field names in the last column are suggestions. A field is whatever you call it, and the diff reports the names you chose, which is why an alert can read like your own vocabulary rather than like a vendor schema.
see alsotitle and meta driftnew URLs in a sitemapSEO monitoring end to endSERP analysis tools compared
AI Overview tracking
AI Overview tracking, down to the sources it cites
An AI Overview is the largest single change that can happen to a query, and it is invisible to every tool that only records a position. It has no rank, so there is no number to move. Here it is a field: extract the container and you know when it arrives and when it goes, extract the citation chips inside it and you know which domains Google is currently willing to quote on your query, including whether yours is still one of them. Both are ordinary extractions gated by an ordinary predicate.
The citation set is the ranking inside the overview
There is no position one inside an AI Overview. What there is instead is a set of cited sources, and being in it or out of it is the closest equivalent to ranking that the block has. Extract the chips into one field and a field_changes predicate reports every time the set moves. Point a field_matches_regex predicate at your own domain in the same field and the alert fires on the specific event you care about, which is the run where you stop matching.
Because it is an ordinary field, it composes with the rest of the monitor. One monitor can hold your position, the first organic result, the snippet and the citation set, and a composite predicate can say: wake me if my rank worsens by three or more, or if I leave the citations, whichever happens first. Pair it with the competitor monitoring API and the landing page rewrite behind a citation change arrives in the same channel.
previous check
- yoursite.com
- wikipedia.org
- reddit.com
this check
- competitor.io
- wikipedia.org
- g2.com
- reddit.com
yoursite.com left the citation set. Two domains entered it. No organic position on the page changed.
Four states worth an alert, and the rule for each
It appears on a query that never had one
The field goes from an empty string to a paragraph of text. Every organic listing on the page just moved down, and no position number changed to tell you.
- field
- ai_overview
- rule
- field_changes
It disappears again
The same predicate, the other direction. Overviews are withdrawn from queries as readily as they are added, and the recovery in click through rate is worth knowing about on the day it happens.
- field
- ai_overview
- rule
- field_changes
The sources it cites change
Extract the citation chips as their own field and you are watching who Google is willing to quote on your query. A domain entering that list is a competitor gaining ground in a place a rank report cannot see.
- field
- ai_overview_cites
- rule
- field_changes
You are dropped from the citations
Match your own domain in the citation field with a regex predicate. The alert fires the moment the pattern stops matching, which is the closest thing to a rank drop that exists inside an AI Overview.
- field
- ai_overview_cites
- rule
- field_matches_regex
Why a selector, and not an AI Overview endpoint
An endpoint would be a promise about a block Google is still redesigning in public. A selector is a promise about nothing, which is why it kept working when overviews arrived and will keep working when the next block does. The cost of that is honest: you own the selector, and when the container markup changes you update it. The run history shows you the run it stopped matching on.
What this does not tell you
It does not tell you why the overview changed, does not estimate the traffic it took, and does not track your presence in ChatGPT, Perplexity or Google AI Mode. It tells you that the block on this URL is different from the last time it was read, and which part of it. Everything after that is your analysis, on your data, in your warehouse.
see alsowriting the selectorregex on a citation listAI extraction when selectors breakwhy rankings drop silently
Location control
Local SERP tracking and multi location rank checks
You change the location a results page is measured from by changing the search URL, not by changing where the request comes from. Because the URL is the input to a monitor, local SERP tracking is one monitor per market with the country, the language and the location written into the query string, the approach set out in the location tracking guide. Three cities on one keyword is three monitors, each holding its own baseline and firing its own webhook.
The Phoenix monitor differs by the uule value alone. That is what makes a per market series reproducible months later.
The market lives in the URL, so it lives in your version control too
A vendor setting that says “Austin” is a value in someone else’s database. A query string is a string you can print, diff, commit and reproduce two years later. When a per market series looks wrong, the input is right there in monitor.url in every payload it ever sent, which is a materially different debugging position to be in.
It also means the same technique works on surfaces that are not Google. Any results page that encodes its filters in the URL, a marketplace category, a job board region, a store locator, can be tracked per market with exactly this pattern.
The URL parameters that set the location
| Parameter | What it controls | Example | What to watch for |
|---|---|---|---|
| gl | The country the results are served for | gl=us, gl=de | The main country lever. Set it on every SERP monitor you create. |
| hl | Interface and result language | hl=en, hl=es | Also changes the wording inside SERP features, which changes the selectors that match them. |
| uule | The city or region the results are measured from | uule=w+CAIQICI... | Undocumented and encoded. Google can ignore it, so check it against the location line printed under the results. |
| cr | Restricts the result set to one country | cr=countryUS | A filter on the results, not a viewpoint. Use it with gl, not instead of it. |
| lr | Restricts the result set to one language | lr=lang_en | Same shape as cr. Useful in bilingual markets where hl alone leaves the mix noisy. |
| pws | Personalisation of the results | pws=0 | Keeps two runs of one monitor comparable. Without it a diff can fire on state you never controlled. |
| num | How many results the page returns | num=20 | Google no longer reliably honours large values, so treat page one as the surface you track. |
| Domain | Which Google property you query | google.co.uk | Country domains resolve to the same results service now. gl moves the country, not the ccTLD. |
One monitor per market, one baseline per market
Name the monitor after the market
The payload carries monitor.name and monitor.url, so a Slack linecan read “SERP / emergency plumber / Austin TX” with nobody opening a dashboard. Keep the keyword and the market in the name and your routing rules stay a single string match.
Every market keeps its own baseline
A monitor stores the previous extraction for its own URL and nothing else. Position four in Austin and position nine in Phoenix never contaminate each other, and the before and after values in a diff always belong to the same city.
Budget the markets before the keywords
Markets multiply monitors: 20 keywords across 5 cities is 100 monitors, which is Pro at 250 rather than Starter at 50. Check the plan counts first. Most teams run head terms in every market and the long tail in one.
Where URL level location control stops
There is no exit country to pick
Checks run from Verid infrastructure. The residential proxy path on Starter and above exists to recover a blocked fetch, not to place you in a country, so location has to come from the query string. For Google that is enough, because Google reads the parameters.
uule is a convention, not a contract
It is encoded, undocumented and can stop working without an announcement, which is true of every tool offering city level tracking. Rank tracking and location monitoring are not the same measurement, so verify a new city string against the location Google prints on the page before you start a series you plan to trust.
Not every search surface reads the URL
Marketplace and site search pages usually geolocate from the IP address or an account setting rather than a parameter. Where the URL carries no location, this approach carries none either. The same selector work still applies to those pages, it just cannot be split per market: see competitor price tracking.
see alsoautomating location checksrank tracking vs location monitoringcreating monitors in bulkmonitors per plan
Real time
The movement a daily rank report averages away
A rank tracker crawls once a day and stores a number. Real time SERP tracking watches the page and pushes an event the moment a tracked element changes, which is the only way to see movement that starts and finishes inside the same twenty four hours. Six signals that reach you here as a webhook and reach a daily report as nothing at all, and the reason a drop can look like it came out of nowhere.
Rank movement inside a single day
A query that sits at four all week can spend three hours at eleven during an update and recover before the nightly crawl runs. Extract your position as a number and the dip arrives as an event with a timestamp instead of never having happened.
- field
- my_rank
- rule
- field_increases_by_absolute, threshold 3
A competitor rewrites the title above you
Both positions can be identical either side of the change while the click share moves, because the snippet winning the click is different. The title of the listing above yours is a field like any other.
- field
- top_result_title
- rule
- field_changes
An AI Overview lands on the query
The block that pushes every organic listing below the fold is not a position, so a position only report has no way to report it. Extract the container and you learn when it arrives, when it goes, and when the sites it cites change.
- field
- ai_overview
- rule
- field_changes
A featured snippet changes hands
Winning or losing the snippet moves clicks further than the position underneath it moves. Watch the snippet on its own field so the alert is about the snippet rather than about the page rearranging.
- field
- featured_snippet
- rule
- field_changes
A new domain enters the top three
Extract the first three result URLs as three separate fields. Any of them changing means the competitive shape of the page moved, whichever direction your own number went that day.
- field
- result_1_url, result_2_url, result_3_url
- rule
- any_field_changes
Your listing leaves page one
When the selector for your own listing matches nothing it extracts an empty string, and an empty string is a value you can match exactly. This is the alert most teams want first and the one a weekly report delivers last.
- field
- my_result_url
- rule
- field_equals, value ""
How real time each plan actually is
Detection lag is your check interval plus the time it takes to render the results page. The interval is set per monitor in seconds and floored by your plan, so the fastest a query can be caught is the floor on its row. Endpoints is how many places one monitor can deliver to at once, which is what decides whether an alert can hit your service and the SEO channel in the same run.
| Plan | Per month | Fastest check | Monitors | Endpoints | Run history |
|---|---|---|---|---|---|
| Free | $0 | Once a day | 5 | 1 | 14 days |
| Lite | $9 | Every 2 hours | 25 | 2 | 90 days |
| Starter | $19 | Every hour | 50 | 3 | 180 days |
| Pro | $49 | Every 15 minutes | 250 | 10 | 1 year |
| Scale | $149 | Every 5 minutes | 1,500 | 25 | 2 years |
Free SERP change monitoring, honestly scoped
The Free plan is permanent, needs no card, and gives you five monitors checking once a day with fourteen days of run history and one delivery endpoint each. That is a real answer for five queries you care about and a poor one for a keyword list, which is the trade every free tier in this category makes. Paid plans move the floor, not the feature set: the predicates, the extraction methods and the payload are identical on every plan. Compare the floors.
White label SERP tracking for agencies
There is no Verid dashboard to rebrand. What an agency gets instead is a payload carrying monitor.name, monitor.url and the before and after value of every named field, with no branding in it to strip, so client facing reporting renders from your own front end against your own storage. Create the monitors per client through theREST API and the account structure stays yours.
see alsowebhook, Slack, Discord, emailcutting alert noisemonitoring at scaleintervals by plan
The contract
One request in, one signed diff out
A SERP monitor is an ordinary monitor with a search URL on it, so the same POST that creates anything else creates this. The request on the left checks a Google results page every thirty minutes in a real browser, tracks five fields including the AI Overview, and delivers to both your service and Slack. The payload on the right is what your endpoint receives on the run where two of those five fields moved.
curl -X POST https://api.verid.dev/v1/monitors \
-H "Authorization: Bearer vrd_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "SERP / best invoicing software / US",
"url": "https://www.google.com/search?q=best+invoicing+software&hl=en&gl=us&pws=0",
"fetch_mode": "browser",
"schedule_interval_seconds": 1800,
"extract_config": {
"method": "xpath",
"fields": {
"top_result_title": "(//div[@id=\"search\"]//h3)[1]",
"top_result_url": "(//div[@id=\"search\"]//a[h3])[1]/@href",
"my_result_url": "//div[@id=\"search\"]//a[contains(@href,\"yoursite.com\")]/@href",
"ai_overview": "//div[contains(@aria-label,\"AI Overview\")]",
"featured_snippet": "//div[@data-attrid=\"wa:/description\"]"
}
},
"diff_predicate": { "type": "any_field_changes" },
"deliveries": [
{ "type": "webhook", "url": "https://api.yourapp.com/hooks/serp" },
{ "type": "slack", "webhookUrl": "https://hooks.slack.com/services/..." }
]
}'{
"id": "d_2h8Kq...",
"version": "2026-05-01",
"monitor_id": "9f3c...",
"run_id": "r_71ba...",
"fired_at": "2026-08-11T09:14:02.418Z",
"diff": {
"fields_changed": ["ai_overview", "top_result_url"],
"before": {
"top_result_title": "Best Invoicing Software (2026)",
"top_result_url": "https://oldwinner.com/invoicing",
"my_result_url": "https://yoursite.com/invoicing",
"ai_overview": "",
"featured_snippet": "A good invoicing tool should..."
},
"after": {
"top_result_title": "Best Invoicing Software (2026)",
"top_result_url": "https://competitor.io/invoicing",
"my_result_url": "https://yoursite.com/invoicing",
"ai_overview": "Invoicing software helps small...",
"featured_snippet": "A good invoicing tool should..."
}
},
"monitor": {
"name": "SERP / best invoicing software / US",
"url": "https://www.google.com/search?q=best+invoicing+software..."
}
}Read the diff, not the object. fields_changed is the list of keys that moved, so a handler is a switch on strings rather than a comparison of two payloads. Here it is ai_overview and top_result_url, and my rank field is absent from that list, which is precisely the case a position only report cannot describe.
Verify before you trust it. The signature is an HMAC-SHA256 over the timestamp and the raw request body, so a replayed or edited payload fails verification. Fetch the plaintext secret once from GET /v1/monitors/{id}/signing-secret and keep it out of your logs.
Failures are not dropped. A delivery is retried six times across roughly two hours, then parked in the dead letter queue for a manual replay. Field reference and the verification snippets are in the SERP monitoring recipe.
see alsoREST API referencedelivery and retrieswebhook best practicesn8n, Zapier and Makealerts into Slack
Honest comparison
SERP tracking API compared to rank trackers, SERP APIs and Search Console
Four things that all claim to tell you where you rank and answer different questions underneath. Read down the row that matters to you rather than across the column with the most ticks, because on three of these rows something else is the better answer and you should know that before you wire anything in. If you are weighing building it yourself, the build versus buy arithmetic is a fifth column.
| Criterion | Verid | Rank trackers | SERP scraping APIs | Search Console |
|---|---|---|---|---|
| What you receive | A webhook when your tracked SERP fields change | A dashboard and a position history | A parsed results page per API call | Aggregated clicks, impressions and average position |
| Freshness | Down to 5 minutes per query | Usually daily | On demand, whenever you call | Roughly two days behind |
| Alerting | Predicate gated push, inside your check interval | Threshold email on a daily cycle | None, you build it | None for ranking movement |
| SERP features and layout | Anything you can select, including AI Overviews | Feature flags on higher tiers | Structured, but you diff it yourself | No layout data at all |
| Position accuracy | The literal position on the page you asked for | The position their crawler saw that day | The position in the response you paid for | An average across users, devices and days |
| Keyword research data | No, bring your keyword list | Yes, volume and difficulty included | Some, through separate endpoints | Only queries you already rank for |
| Cost model | Monitors on a flat plan, from $0 | Per tracked keyword per month | Per request or per credit | Free |
| Where history lives | Your warehouse, plus Verid run history | The vendor dashboard | Your storage, once you write it | 16 months, then it is gone |
If you are already running one of these
You already pay for a rank tracker
Keep it. It answers what your visibility looked like last quarter, and it owns the volume and difficulty data you plan with. Add monitors on the twenty queries where a same day reaction is worth something, and let the tracker keep reporting on the rest. That split is what SEO monitoring alongside an existing stack looks like in practice.
You already call a SERP API
You are paying per request for full results pages and then writing the scheduler, the storage, the comparison and the alerting yourself. That loop is the part this replaces. If you also need arbitrary keyword lookups on demand, keep the SERP API for those calls.
You are watching Search Console
Search Console tells you what already happened to clicks, two days late and averaged. It cannot tell you that an AI Overview landed on your best query this morning. If email alerts are what you are replacing, the Google Alerts comparison covers that ground. The two are complements, and neither replaces the other.
Where it stops
What this SERP tracking API does not do
Six places where this is the wrong tool, is weaker than the copy above would like, or stops on purpose. Two of them are behaviours you would otherwise discover on day three, which is the only reason to put a section like this on a page trying to sell you something.
It is not a SERP scraping API
You do not send a keyword and receive a fully parsed results page. You send a URL and the selectors for the parts you care about. If you need complete structured SERPs for thousands of ad hoc queries, use a dedicated SERP API. This is the monitoring and alerting layer, and scraping and change detection answer different questions.
No keyword research metrics and no history to backfill
There is no search volume, no keyword difficulty, and no historic rank database. Your first check is your baseline, which means a monitor created today can tell you nothing about last month. Teams keep their research tool and use this for movement between crawls, which is the arrangement the comparison table assumes.
Search markup shifts, so selectors need maintenance
Google changes its DOM without notice, which is true of every tool in this space including the ones that hide it from you. Prefer stable anchors and structural XPath over generated class names, or move the field to prompt extraction, which does not depend on markup at all. Expect to revisit a selector when a field starts returning empty.
No pixel measurement, and no visibility score
The stack section above is about the order of the blocks on the page, not about pixels. Verid does not measure how many pixels down your listing sits, does not compute a share of voice number, and does not roll your queries up into an index. What it gives you is the raw before and after, on the field names you chose.
One query per monitor, and the arithmetic is on you
Tracking 200 keywords means 200 monitors, and 200 keywords across three markets means 600. Read the plan monitor counts before you commit a keyword list, because the count is what decides your plan, not the check volume.
You are responsible for the terms of the page you point at
A monitor will fetch whatever URL you give it on the schedule you set. Whether that is compatible with the terms of service of the search engine or site in question is your call to make, and the check interval floor on your plan is not a legal opinion. The legal ground is worth reading first.
SERP tracking API questions
The sixteen things SEO and growth engineers ask before the first monitor, answered with the numbers the product enforces.
What is a SERP tracking API?
A SERP tracking API programmatically watches a search engine results page and reports when it changes. Verid does this by monitoring the search URL you supply: it renders the page in real Chrome on a schedule, extracts the rank positions and SERP features you selected, compares them against the previous check, and posts a signed webhook when your rule is met.
Is this a rank tracking API or a SERP scraping API?
It behaves as a rank tracking API in that you get position data over time through an API. It is not a SERP scraping API: no endpoint takes a keyword and returns a full parsed results page. You point a monitor at a search URL and name the elements to track, which is also why the same product tracks site search, marketplace and app store result pages.
How is this different from a normal rank tracker?
A rank tracker crawls on a daily cycle and stores a number for a report. This watches the page and pushes an event within your check interval, down to five minutes, carrying the before and after value of every field you named. It has no keyword volume data and no historic rank database, so it is an alerting layer rather than a replacement for your reporting tool.
How do I track rankings for a specific country or city?
Set the locale in the URL itself: hl for language, gl for country, uule for a city or region, and pws=0 to reduce personalisation. Because the URL is the input to a monitor, local SERP tracking is one monitor per market, explicit and reproducible months later rather than hidden behind a vendor setting.
Can I choose which country the check is made from?
Not as an exit IP. Checks run from Verid infrastructure, and the residential proxy path on Starter and above exists to recover a blocked fetch rather than to place you in a country. Location comes from the search URL instead, through gl, hl and uule, which is what Google reads anyway.
How often can it check a SERP?
The interval is set per monitor in seconds and floored by your plan: once a day on Free, every two hours on Lite, hourly on Starter, every fifteen minutes on Pro and every five minutes on Scale. High value commercial queries usually run at the floor while the long tail runs daily, which keeps both the monitor count and the check volume sensible.
Can it alert me when an AI Overview appears?
Yes. Extract the AI Overview container as its own field and use a field_changes predicate pointed at that field. The webhook fires when it appears, when it disappears, and when its text changes, which is the earliest signal available that the top of the page rearranged itself.
Can I track which sources an AI Overview cites?
Yes, by extracting the citation chips as a separate field. A field_changes predicate on that field tells you whenever the cited set moves, and a field_matches_regex predicate on your own domain tells you the moment you stop being one of the sources. Both are ordinary predicates on an ordinary field, not a special AI feature.
Can it track SERP features other than position?
Yes, and that is usually the point. Featured snippets, People Also Ask, video carousels, local packs, shopping grids and ad slots are all just containers you can select. Because a selector is not a fixed feature list, a block Google ships next year becomes a new field on your monitor rather than a request to a vendor roadmap.
Does it measure how far down the page my listing is?
Not in pixels. Verid extracts the fields you name, so the honest measure of displacement is the set of blocks above your listing: which of them are present, and how that set changes. With the prompt extraction method you can ask a model to return that list in order. There is no pixel depth number and no visibility score.
Can I track competitor rankings too?
Yes. Extract the first few organic titles and URLs as separate fields on the same monitor and you learn both your own position and who moved above you. Many teams pair this with the competitor monitoring API so a ranking gain and the landing page rewrite behind it arrive in the same channel.
Do I still need a rank tracker?
If you need search volume, keyword difficulty, share of voice reporting or years of historic rank data, keep it. This answers a different question: tell my code, right now, that this specific search result changed, so an automation can respond to it.
Is there a free way to monitor SERP changes?
Yes, within limits. The permanent Free plan gives you five monitors on a once a day check with fourteen days of run history and no card required, which covers a handful of queries properly rather than a whole keyword list. Faster intervals and higher monitor counts start at $9 a month on Lite.
Can I white-label SERP tracking for clients?
There is no rebrandable Verid dashboard, but the delivery payload carries only your monitor name, your URL and the before and after values of your named fields, so there is no branding in it to strip. Agencies create monitors per client through the REST API and render client facing reports from their own front end against their own storage.
What does it cost to track SERPs this way?
Pricing is per monitor on a flat monthly plan rather than per tracked keyword: 5 monitors on the permanent Free plan, 25 on Lite at $9, 50 on Starter at $19, 250 on Pro at $49 and 1,500 on Scale at $149. One monitor equals one query in one market, so the cost of a keyword list is arithmetic you can do before you sign up.
What happens if my endpoint is down when a SERP moves?
The delivery is retried six times over roughly two hours, immediately and then after 5, 15 and 30 minutes, 1 hour and 2 hours. If every attempt fails it lands in the dead letter queue, where it can be replayed by hand once your endpoint is back. Every payload is signed with HMAC-SHA256 in a Verid-Signature header so a replay cannot be forged.