SERP overlay / implementation handoff
Download handoff

SERP overlay implementation handoff

Compare the designs, then use the design specifications and technical fixes below to implement the changes.

Legacy version

3.13.5
Apple
https://www.apple.com › iphone
3.iPhone – Apple

Explore the iPhone lineup. Compare models, discover their features, and find the right iPhone for you.

Original styling; result number outside the bar.

Final Design

Implementation target
Apple
https://www.apple.com › iphone
iPhone – Apple

Explore the iPhone lineup. Compare models, discover their features, and find the right iPhone for you.

#3

Implementation target.

Current version

Package 4.1.2
Apple
https://www.apple.com › iphone
iPhone – Apple

Explore the iPhone lineup. Compare models, discover their features, and find the right iPhone for you.

Current styling reference.

SERP implementation

Current → Final Design

Light-mode presentation changes only; preserve existing data, settings, loading/error behavior, metric and utility links, and tracking.

AreaCurrent · 4.1.2Final Design · specification
Typography13px controls; 14px position.12px Inter (Arial / sans-serif fallback) throughout. Labels 400; values and #3 600. Control line height 20px; #3 22px. Tabular, lining numerals.
StripPadding 2px 7px; square corners; margins 4px 0 6px.Width 100%; padding 4px 7px; radius 3px; no outer margin, border or shadow. #3 stays outside the wrapping flow, with a 7px gap.
Control spacing8px padding; 6px internal gap.Padding 1px 0; internal gap 4px; radius 3px; min-height 24px. Metric text baseline-aligned; icons vertically centered.
WrappingControls wrap independently.Flow gap 0px vertically / 9px horizontally. Keep PIN, whois and source together with 10px gaps. Labels and values do not wrap internally. Height follows content: 32px for one row, 56px for two; more rows allowed.
Labels and orderShort labels without colons.Keep order: #3 → Rank: → Traffic: → Costs: → L: → LD: → LRD: → PIN: → whois → source. PIN remains non-clickable.
IconsExisting Semrush, Pinterest and utility icons.Six Semrush icons plus Pinterest: 16 × 16px. Utility icons: 12 × 12px. Keep icon identities; no extra standalone logo.
ColorsExisting gray strip and controls.Strip #F0F1F2; values #181E15; labels and Semrush/Pinterest icons #60636B; utilities #5C6269; #3 #696D76; interactive green #11AA88.
Hover and focusMetric icon and label highlight.Linked metric: highlight only the value; label and provider icon stay gray. Value focus outline: 2px green, 2px offset, 1px radius. Whois/Source: highlight icon and label; focus outline 2px #7137AD, 2px offset. No filled hover background.
TransitionsExisting control transitions.Color / background-color: 120ms; disable for reduced motion. No entry animation or moving metrics.
New behaviorNo Analyze link; definitions hidden in the SERP specimen.Add Analyze and definitions as specified below.

Known issue: approved interaction colors have unresolved contrast concerns; this is not an accessibility sign-off.

Analyze CTA

Show = one row AND (flow width − used item widths − gaps ≥ CTA width + 16px)
  • Fit: measure rendered widths after fonts load; recheck on resize, item-size and content changes, including selected parameters. Use the 9px flow gaps; the utility group counts as one item. No fixed viewport breakpoint.
  • Position: absolute, 7px from the right edge, vertically centered. Never reserve space or push metrics onto another row.
  • Appearance: text and external-link icon #C190FF; 12px Inter / 20px line height / weight 600; padding 2px 4px; minimum height 24px; 6px gap to a 12px icon. Underline on hover, no filled button. Focus outline: 2px #7137AD with 2px offset.
  • Keyboard: hidden means visibility:hidden, no pointer events, aria-hidden="true" and tabindex="-1"; restore interaction when shown. If it disappears while focused, move focus to a nearby visible control (production safeguard; not implemented in the prototype).
  • Destination: Domain Overview for the analyzed domain, using the existing URL helper. Open in a new tab with noopener noreferrer.

Definitions and tooltips

Reuse the existing Quick View / full-report copy verbatim:

LabelTitleDefinition
Rank:Semrush RankA Semrush visibility ranking for the analyzed domain.
Traffic:SE TrafficEstimated US organic traffic for this domain from Semrush data.
Costs:Traffic CostEstimated paid-search equivalent value of this domain's organic traffic.
L:URL BacklinksLinks from other websites pointing to this URL.
LD:Subdomain BacklinksTotal backlinks pointing to tracked subdomains for the analyzed domain.
LRD:Root Domain BacklinksTotal backlinks pointing to the root domain.
PIN:Pinterest Pin CountEstimated Pinterest pin count for the linked URL.
whoisWhoisOwnership lookup helper for the linked domain.
sourcePage SourceView the page source for the linked URL.
  • Show one tooltip at a time on hover or keyboard focus. PIN retains its hover definition without becoming a link or tab stop.
  • Keep open while the trigger or tooltip is hovered, or the trigger is focused; allow 150ms before dismissal after leaving. Escape dismisses immediately.
  • Use role="tooltip" and a unique aria-describedby; remove native titles. Position outside the strip’s flow so tooltips do not affect wrapping or Analyze visibility.

Tooltip positioning and visual specs

Actual-size reference · Traffic tooltip shown
Traffic:1.62B
SE TrafficEstimated US organic traffic for this domain from Semrush data.

Fixed position, 6px below the trigger or above if needed; clamp to an 8px viewport inset. Max-width 280px, capped at viewport width minus 16px. Padding 10px 12px; radius 6px; white background; 1px #DADDDE border; #181E15 text; 12px / 18px Inter. Title weight 600 with 3px bottom gap. Shadow: 0 3px 12px #0002.

SEObar implementation

Highlight the value

  • On hover and keyboard focus, highlight only the linked metric’s value with its existing theme-specific interaction color; keep the label and provider icon gray. Preserve the visible focus indicator.
  • Whois / Source still highlight their icon and label together. Non-link counts and loading states keep their existing behavior.
  • Scope shared-component changes to SEObar; leave SERP, Quick View and Full Report unaffected.

Everything else stays unchanged: layout, typography, spacing, hit areas, icons, tooltips, settings, destinations and seobar_* tracking. No Analyze CTA or dark-mode redesign for SEObar.

Engineering handoff

Technical fixes

Two correctness fixes, separate from the design changes above. Causes verified against the supplied 4.1.2 package and the freshly fetched SERP branch on 11 September 2026 (51b50b5). Recommendations below are implementation guidance, not an implemented or release-tested patch.

1. Destination URL

Required outcome: identify each result by its actual destination, never by an address reconstructed from Google’s displayed breadcrumb.

Confirmed problem: resolveResultUrl() prefers extractCiteUrl() over the title link. Tests with the supplied code collapse distinct /a and /b pages into one domain, or invent /Products/Widget instead of the real /products/detail?id=42 destination.

Implementation guidance

  1. Use the title anchor already selected by findHeadingLink(). Parse its non-empty href against the document base URL. Remove breadcrumb reconstruction from URL identity; do not fall back to it when a link is missing or invalid.
  2. Unwrap only recognized Google-hosted redirects. For supported /url links, extract a valid q or url destination and validate it again. Do not unwrap a third-party site merely because its path is /url. Keep existing ad and result-eligibility exclusions.
  3. Accept only a resolved, eligible HTTP(S) destination. If a redirect form cannot be resolved safely, skip that URL-dependent overlay/export row; do not send Google’s redirect URL to the metric service. Add a captured fixture before supporting another redirect form such as /goto.
  4. Use the resolved URL consistently for result identity, CSV URLs and inputs to page-level metrics/report links. Keep domain-level metrics domain-scoped. Preserve the destination’s path and query; do not merge different pages by domain or displayed breadcrumb.

Follow the URL through the shared helpers. normalizeSemrushTarget() currently calls normalizeUrl(), which removes every query parameter. A resolver-only fix therefore does not preserve ?id=42 versus ?id=43 in page-level requests and report targets. Preserve query identity in the page-target path and test its callers, caches and generated requests. Do not globally change the shared normalizer without regression checks. This is an existing shared dependency, not established as a new SERP regression.

QA checklist

Run after implementation. These are checks to cover, not necessarily separate automated tests.

TestRequired result
Different pages, same domainLinks to /a and /b remain distinct even when their displayed breadcrumbs show only the domain.
Misleading or absent breadcrumbThe real /products/detail?id=42 link wins over “Products › Widget”. For an otherwise eligible result, an absent cite does not prevent resolving its valid title-link destination.
Google redirect and ordinary /url pageSupported Google /url?q=… and /url?url=… links resolve correctly. An external site’s /url?q=… address remains that site’s URL.
Invalid or unresolved destinationMissing href, non-HTTP(S), excluded ads and unresolved Google redirects produce no guessed URL or metric request.
Meaningful query parameters?id=42 and ?id=43 remain distinct in results and CSV, and in page-level request/cache/report targets; domain metrics retain their existing scope.

Source: URL resolution · detection and deduplication · metric target normalization · shared URL normalizer. Legacy 3.13.5 read the selected result link’s href directly; it did not reconstruct the breadcrumb.

2. Result numbering & exports

Required outcome: overlay positions and CSV rows must come from the same current, page-ordered list of eligible results.

Confirmed problem: added subtrees are scanned and numbered independently, then merged. In the supplied-code test, a fourth result becomes another #1; a whole-page scan gives #4. Removing an overlay’s metric snapshot does not remove its separate export row.

Implementation guidance

  1. After each relevant debounced mutation batch, run one complete detection pass for the current page and use the replacement path: replaceSerpExportRows() plus syncSerpOverlays(). Do not merge independently numbered partial scans.
  2. Number accepted, connected results in DOM order using the existing pagination offset. Preserve the current policy of one result per exact resolved URL, keeping its first accepted occurrence; this change does not introduce a new duplicate-card policy.
  3. Reconcile export membership, mounted overlays and metric snapshots together. Remove departed results and update retained positions. Preserve unchanged result state; do not clear/reload all metrics on every mutation. When a URL’s container or insertion anchor changes, reposition its existing host/root when possible. If remounting is necessary, retain or reuse loaded metric state for the unchanged URL; a connected host alone does not prove correct placement.
  4. Keep debouncing and the existing generation guards. Cover additions, removals, DOM moves and result-link href changes; the current observer watches child-list changes only. Filter SEOquake’s own DOM updates to avoid feedback loops. Invalidate obsolete async work on URL/lifecycle resets so old work cannot overwrite the current page.
  5. Before Export reads the store, flush or run the current reconciliation and wait for it to finish. Capture rows, metric snapshots and search-query filename from the same current-page generation. Do not wait for every metric to load: retain existing n/a versus zero behavior.
QA checklist

Run after implementation. These are checks to cover, not necessarily separate automated tests.

TestRequired result
Append, insert, remove or reorderStart with three results; append a fourth → #1–#4. Insert above or move/remove a result → positions and CSV follow the new DOM order, with no departed rows.
Container replacement or changed hrefA retained URL’s overlay follows its current container/anchor. Changing a card’s URL removes the old identity and does not reuse the wrong page’s metrics.
Export immediately after a changeClick within the observer’s 400ms debounce window: exported URLs, positions and filename reflect the reconciled current page.
Pagination and exact duplicatesstart=10 begins at #11. An exact duplicate resolved URL retains the first accepted occurrence; distinct same-domain paths remain separate.
Navigation, disable and delayed responsesOld settings/metric responses cannot restore departed results after navigation or teardown. Removing all results empties the list and CSV membership.
Stable results and repeated mutationsPosition-only changes do not reset loaded metrics or trigger unnecessary refetches. SEOquake’s own updates cause no observer loop or duplicate overlay.

Source: mutation orchestration · observer · result stores · overlay reconciliation · export action · CSV assembly. File links use the inspected revision; the async, placement and export-timing items are implementation safeguards, not additional reproduced live failures.

Verification boundary: isolated original-code tests reproduce the two causes. The acceptance cases above still require the implemented extension, including mixed Google results and coexistence with other extensions. This handoff is not release approval.