• script

Rank tracker jumped? Repeat-check script with a 40% ceiling

Python script, stdlib only: flags keywords whose top 10 flipped, remeasures only those, keeps the second result only if it is closer to the last check.

  • v1.0
  • updated 12 November 2026
  • MIT
  • Vladislav Krivorutško

A position jump in a rank tracker is often not a jump of your page. The same query, asked twice, returns a different top 10 now and then. In the author's data from 2026-11-12, two runs of one tool shared on average 7.6 of 10 domains, and for 7% of the pairs only 4 or fewer. This script takes your last trusted check and the new one, finds the keywords whose top 10 flipped, and applies one rule: measure again, and keep the second measurement only if it is closer to the last check.

It is one Python file with no packages and no network access. Give it three CSV files (keyword, position, domain), get a table and two CSV files. The data behind the thresholds is a separate resource: SERP repeatability dataset.

Files, grouped by job

5 files · or all in one zip

Read me

1 file
  • README.md

    3-step run, rules and thresholds, decision table, gotchas

    12 KB

Run it

1 file
  • serp_repeat_check.py

    The checker: Python 3.8+, standard library only, with an offline self-test of 22 checks

    17 KB

Try it first

3 files
  • sample-prior.csv

    Synthetic last check: 9 keywords, example-*.com domains

    5.3 KB
  • sample-first.csv

    Synthetic new check: 10 keywords, five of them flipped

    6.1 KB
  • sample-remeasure.csv

    Synthetic second measurement for the keywords to repeat

    3.1 KB

Quick start

  1. Unzip the download and check Python: python3 --version (3.8 or newer).

  2. Run the offline self-test, then the sample:

    bash
    python3 serp_repeat_check.py --selftest
    python3 serp_repeat_check.py --prior sample-prior.csv --first sample-first.csv
    

    The table shows which keywords flipped and which of them to measure again.

  3. Measure those keywords in your tracker, save the top 10 in the same CSV format, and run again:

    bash
    python3 serp_repeat_check.py --prior sample-prior.csv --first sample-first.csv --remeasure sample-remeasure.csv --out result.csv --out-final final.csv
    

    result.csv has the decision per keyword; final.csv has the measurement that stands.

The rules

StepRule
OverlapThe domains that the last check and the new check share in their top 10
FlippedFewer than half in common: under 5 of 10. Exactly 5 is not flipped
CeilingAt most 40% of the keywords of a check are remeasured, rounded down; the lowest overlap goes first, the rest are not_remeasured and stay flagged
DecisionThe second measurement replaces the first only if it shares more top-10 domains with the last check than with the first measurement. A tie keeps the first
No priorA keyword without a last check is not remeasured

The thresholds are from the author's measurements in 2026-11 on a few dozen keywords. They are a starting point: --threshold, --max-share and --top change them, and the right values depend on your tool and market.

Example output

The sample is synthetic: 10 neutral keywords and example-*.com domains. The second run, with the remeasure file:

text
keyword                          common prior/first  flipped  decision        remeasure vs prior/first  final
-------------------------------  ------------------  -------  --------------  ------------------------  ---------
how to tie a tie                 5/10                no       stable          -                         first
python list comprehension        4/10                yes      not_remeasured  -                         first
how to renew a passport          2/10                yes      kept_first      2 / 9                     first
what is inflation                3/10                yes      kept_first      3 / 3                     first
how to start a vegetable garden  1/10                yes      switched        8 / 1                     remeasure
quick pasta recipes              0/10                yes      switched        8 / 0                     remeasure
how to change a flat tire        -                   -        no_prior        -                         first

keywords 10; flipped 5; remeasure ceiling 4 (a share of the keywords, rounded down); selected 4; not remeasured (over the ceiling) 1
remeasure: switched to the second measurement 2, kept the first 2, missing from the remeasure file 0

Seven of the ten rows; the README shows all of them. Read the remeasure vs prior/first column as "domains shared with the last check / with the first measurement". Two of the four remeasured keywords switched because the second measurement looked like the last check; one kept the first because the second looked like it (9 against 2); one kept the first on a tie (3 against 3).

Rather have this done for you?

Send the site address and what you want to know. We run the audit and send the report.

Send a request

Who it is not for

  • Anyone who needs to know which measurement is true. The rule picks the one that is consistent with the last check. That is not the same thing.
  • Checks that mix tools, countries or devices. A different setup makes every keyword look flipped: in the author's data, two tools shared 3.7 of 10 domains on average.
  • Very small checks. With 2 keywords the ceiling is 0.

Gotchas

  • The last check must come from the same setup, and ideally it has itself passed this rule. Otherwise the rule copies old noise forward.
  • A real change also flips. A new competitor in the top 5 flips the keyword too. When the second measurement agrees with the first, the first stands, which is the right outcome. When it agrees with neither, nothing here says which is right.
  • Domains, not pages. A site that swaps its ranking page does not flip here.
  • Positions are not smoothed. The script chooses between two measurements; it does not average or repair positions.
  • Ceiling order is a choice. Lowest overlap first, because the keyword that lost most of its page is the least trustworthy one.

Tested on

2026-11-12: Windows 11, Python 3.13.14. From a clean folder holding only the files of this download: the self-test passed 22 of 22 checks, and the two runs on the sample printed the output shown above. The decisions were compared with an independent inline version of the same rule on four real runs of one tool (the data of the dataset resource): 630 combinations, 44 flipped, 21 switched, no difference. Not run on Python 3.8 to 3.12, nor on Linux or macOS, and not on a live tracker export.

Files are provided as is: run them on your own data and check the result.

Want an audit like this on your site?

If you would rather have it done for you, send a request and describe the site.

Send a request
Download serp_repeat_check.py