Rank Tracking Snapshot Comparator avatar

Rank Tracking Snapshot Comparator

Pricing

from $11.50 / 1,000 rank snapshot compareds

Go to Apify Store
Rank Tracking Snapshot Comparator

Rank Tracking Snapshot Comparator

Compare two or more SERP snapshots and report position changes, URL swaps, domain movements, feature gains/losses, and query-level volatility

Pricing

from $11.50 / 1,000 rank snapshot compareds

Rating

0.0

(0)

Developer

junipr

junipr

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

21 days ago

Last modified

Share

Compare an earlier and later set of query-ranked URLs. The actor detects position movement, entrants, exits, URL swaps, and result-feature changes while preserving the source evidence behind every comparison.

What you get

Each dataset row represents one query-domain pair and includes:

  • baseline and current positions;
  • signed positionDelta, where a positive number is an improvement;
  • current or most recent URL;
  • URL-change detection for the same query and domain;
  • feature gained and feature lost flags;
  • a bounded volatility score;
  • movement type such as entered, exited, url_swap, improved, major_improvement, declined, major_decline, feature_change, or unchanged;
  • source URL, evidence, issue code, scan time, and recommendation.

Owned domains are recognized in recommendations so an analyst can distinguish movements that directly affect controlled properties. With reports enabled, the actor writes Markdown, CSV, issue JSON, evidence JSON, run metadata, and a digest artifact to key-value storage.

Required evidence

Supply both baselineSerpResults and currentSerpResults. Each array may contain individual records or snapshot objects with a query and nested results. Every usable record needs:

  • query;
  • positive numeric position or rank;
  • public url or resultUrl;
  • optional domain, resultType, and sourceUrl.

Invalid, missing, zero, or negative positions are ignored. If either side has no accepted records, the actor returns a diagnostic row rather than inferring movement.

Comparison controls:

  • ownedDomains: domains highlighted as controlled properties.
  • compareFeatures: compare organic versus explicitly typed result features.
  • rankDepth: boundary used to score entrances and exits.
  • movementThresholds.minor and .major: configure movement labels.
  • maxQueries: cap distinct queries.
  • maxSnapshots: cap snapshot containers read from each side.
  • maxResultsPerQuery: cap result records accepted for each query and side.
  • maxComparisons: cap emitted query-domain rows.
  • maxChargeUsd: stop before a paid event would exceed the ceiling.

Example input

{
"baselineSerpResults": [
{
"query": "seo tools",
"sourceUrl": "https://example.com/serp/seo-tools/previous",
"results": [
{ "position": 5, "url": "https://junipr.io/seo", "resultType": "organic" },
{ "position": 2, "url": "https://competitor.example/old-page", "resultType": "organic" }
]
}
],
"currentSerpResults": [
{
"query": "seo tools",
"sourceUrl": "https://example.com/serp/seo-tools/current",
"results": [
{ "position": 2, "url": "https://junipr.io/seo", "resultType": "organic" },
{ "position": 2, "url": "https://competitor.example/new-page", "resultType": "organic" },
{ "position": 4, "url": "https://new.example/list", "resultType": "featured_snippet" }
]
}
],
"ownedDomains": ["junipr.io"],
"compareFeatures": true,
"rankDepth": 10,
"movementThresholds": { "minor": 2, "major": 5 },
"maxQueries": 10,
"maxSnapshots": 20,
"maxResultsPerQuery": 20,
"maxComparisons": 100,
"includeReport": true,
"maxChargeUsd": 35
}

Example output

{
"recordType": "rank_tracking_snapshot_comparator",
"recordName": "seo tools | junipr.io",
"issueCode": "rank_tracking_snapshot_comparator_rank_change",
"severity": "medium",
"query": "seo tools",
"domain": "junipr.io",
"url": "https://junipr.io/seo",
"baselinePosition": 5,
"currentPosition": 2,
"positionDelta": 3,
"urlChanged": false,
"featureGained": false,
"featureLost": false,
"volatilityScore": 30,
"movementType": "improved",
"sourceUrl": "https://example.com/serp/seo-tools/current",
"scannedAt": "2026-07-10T12:00:00.000Z"
}

Comparison semantics

Records are grouped by query and normalized domain. When multiple URLs from a domain appear for the same query, the best position on each side is compared. A different best URL becomes url_swap. A domain seen only in the current evidence becomes entered; one seen only in the baseline becomes exited. The configured rank depth supplies the comparison boundary for those one-sided records.

Feature comparison uses resultType. Organic-to-feature changes set featureGained; feature-to-organic changes set featureLost. Disable compareFeatures when capture providers do not use compatible result-type labels.

The volatility score is a deterministic aid, not a prediction. It combines absolute position movement with bounded additions for URL and feature changes.

Pay-per-event pricing

Platform usage pass-through is off, and charges occur before related output.

EventPrice
actor-start$0.0350
rank-snapshot-compared$0.0115
url-position-record-checked$0.0115
rank-change-detected$0.0225
digest-generated$0.0900
executive-report-generated$0.1800

The default maximum charge is $35. Set maxChargeUsd to zero to prevent paid processing and output.

Practical uses

  • compare weekly or monthly rank exports from the same provider;
  • detect URL swaps after migrations or internal-link changes;
  • identify newly visible and disappearing competitor domains;
  • track result-feature ownership separately from numeric rank;
  • produce a capped movement digest for SEO reporting.

Limits

Use consistent query, locale, device, provider, and collection depth on both sides. The actor compares supplied observations and does not fetch historical rankings or reconstruct missing records. Query-domain grouping intentionally reports the best observed URL for each side.