serp-ctr 0.1.0

Search-console arithmetic: click-through rate, impression-weighted average position, and click projection against a caller-supplied CTR-by-position curve.
Documentation
  • Coverage
  • 100%
    33 out of 33 items documented5 out of 21 items with examples
  • Size
  • Source code size: 34.23 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 476.26 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 2s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • theluckystrike/serp-ctr-rs
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • theluckystrike

serp-ctr

Search-console arithmetic in safe, dependency-free Rust: click-through rate, impression-weighted average position, SERP page bucketing, pooled totals, and click projection against a CTR-by-position curve.

Why there is no built-in CTR table

Published "average CTR by position" tables are third-party estimates that disagree with each other and vary by query intent and SERP layout. Baking one in would turn somebody else's sample into this crate's constant. CtrCurve is therefore built from your observations, and it returns an error for a position it has never seen rather than interpolating one.

use serp_ctr::{ctr_percent, CtrCurve, PositionRow, weighted_average_position};

// 7 clicks on 1,000 impressions
assert_eq!(ctr_percent(7, 1_000, 2).unwrap(), 0.7);

// Impression-weighted, not a mean of the position column
let rows = [
    PositionRow { position: 2.0, impressions: 9_000 },
    PositionRow { position: 90.0, impressions: 1_000 },
];
assert!((weighted_average_position(&rows).unwrap() - 10.8).abs() < 1e-9);

// Curve built from measured rows, then used to restate them at a new volume
let curve = CtrCurve::from_observations([(3.0, 60, 1_000), (9.0, 10, 1_000)]).unwrap();
assert_eq!(curve.project_clicks(3, 5_000).unwrap(), 300);
assert!(curve.ctr_at(5).is_err()); // never observed, so never guessed

Install

[dependencies]
serp-ctr = "0.1"

#![forbid(unsafe_code)], no dependencies, MSRV 1.63.

Licence

MIT OR Apache-2.0.

Written for the SEO pipeline at https://toolsthatrank.com/.