import { type FormEvent, useEffect, useRef, useState } from "react"; // Public site key. Cloudflare's always-passing test key is the dev-only // fallback; a prod build without VITE_TURNSTILE_SITE_KEY renders no widget. const TURNSTILE_SITE_KEY = (import.meta.env.VITE_TURNSTILE_SITE_KEY as string | undefined) || (import.meta.env.DEV ? "1x00000000000000000000AA" : ""); type TurnstileApi = { render( container: HTMLElement, options: { sitekey: string; appearance?: string; callback: (token: string) => void; "expired-callback"?: () => void; }, ): string; reset(widgetId?: string): void; }; type BacklinkRow = { domainFrom: string | null; urlFrom: string | null; urlTo: string | null; pageTitle: string | null; anchor: string | null; dofollow: boolean | null; domainRank: number | null; }; type CheckResult = { target: string; summary: { rank: number | null; backlinks: number | null; referringDomains: number | null; brokenBacklinks: number | null; }; topBacklinks: BacklinkRow[]; }; function formatCount(value: number | null): string { return typeof value === "number" ? value.toLocaleString("en-US") : "—"; } /** Small info icon that reveals an explanation on hover or focus. */ function InfoTip({ tip, align = "center", }: { tip: string; align?: "center" | "right"; }) { return ( ); } export function BacklinkCheckerTool() { const [target, setTarget] = useState(""); const [status, setStatus] = useState<"idle" | "loading" | "done" | "error">( "idle", ); const [errorMessage, setErrorMessage] = useState(""); const [result, setResult] = useState(null); const widgetContainerRef = useRef(null); const widgetIdRef = useRef(null); const tokenRef = useRef(""); useEffect(() => { if (!TURNSTILE_SITE_KEY) return; const w = window as unknown as { turnstile?: TurnstileApi; onloadTurnstileCallback?: () => void; }; const renderWidget = () => { if (!w.turnstile || !widgetContainerRef.current) return; if (widgetIdRef.current !== null) return; widgetIdRef.current = w.turnstile.render(widgetContainerRef.current, { sitekey: TURNSTILE_SITE_KEY, // Invisible unless Turnstile decides the visitor needs a challenge. appearance: "interaction-only", callback: (token) => { tokenRef.current = token; }, "expired-callback": () => { tokenRef.current = ""; }, }); }; if (w.turnstile) { renderWidget(); return; } w.onloadTurnstileCallback = renderWidget; if (!document.querySelector("script[data-turnstile]")) { const script = document.createElement("script"); script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback"; script.async = true; script.dataset.turnstile = "true"; document.head.appendChild(script); } }, []); const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setStatus("loading"); setErrorMessage(""); try { const res = await fetch("/api/backlink-check", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ target, turnstileToken: tokenRef.current || undefined, }), }); const data = (await res.json().catch(() => ({}))) as | CheckResult | { error?: string }; if (!res.ok) { throw new Error( (data as { error?: string }).error || "Something went wrong", ); } setResult(data as CheckResult); setStatus("done"); } catch (err) { setStatus("error"); setErrorMessage( err instanceof Error ? err.message : "Something went wrong", ); } finally { // Tokens are single-use; get a fresh one for the next check. tokenRef.current = ""; const w = window as unknown as { turnstile?: TurnstileApi }; if (w.turnstile && widgetIdRef.current !== null) { w.turnstile.reset(widgetIdRef.current); } } }; return (
setTarget(e.target.value)} placeholder="example.com" disabled={status === "loading"} className="h-11 min-w-0 flex-1 rounded-lg border border-[var(--color-border-subtle)] bg-white px-3.5 text-base text-neutral-900 placeholder:text-neutral-500 transition focus:border-neutral-900 focus:outline-none focus:ring-1 focus:ring-neutral-900" />

Free · No signup · Instant results

{status === "error" && (

{errorMessage}

)} {status === "done" && result ? : null}
); } function CheckResults({ result }: { result: CheckResult }) { const { summary, topBacklinks } = result; const total = summary.backlinks; const hasMore = typeof total === "number" && total > topBacklinks.length; const metrics = [ { label: "Domain rank", value: formatCount(summary.rank), tip: "DataForSEO's 0-100 strength score for a domain's link profile. Similar idea to Ahrefs DR or Moz DA, but each tool uses its own index and formula, so numbers differ between tools.", }, { label: "Backlinks", value: formatCount(summary.backlinks), tip: "Total individual links pointing at this domain, counting multiple links from the same website.", }, { label: "Referring domains", value: formatCount(summary.referringDomains), tip: "Unique websites that link to this domain at least once.", }, { label: "Broken backlinks", value: formatCount(summary.brokenBacklinks), tip: "Links pointing at pages on this domain that no longer load, such as deleted pages returning 404.", }, ]; return (

Backlink profile for{" "} {result.target}

{metrics.map((metric, index) => (
1 && "border-t border-[var(--color-border-subtle)]", index > 0 && "md:border-l md:border-t-0", ] .filter(Boolean) .join(" ")} >
{metric.label} 1 ? "right" : "center"} />
{metric.value}
))}
{topBacklinks.length > 0 ? (
{topBacklinks.map((row) => ( ))}
Rank Referring page Anchor and target Type
{formatCount(row.domainRank)}

{row.pageTitle ?? row.domainFrom ?? "—"}

{row.urlFrom ? ( {row.urlFrom} ) : null}

{row.anchor ?? "—"}

{row.urlTo ? (

{row.urlTo}

) : null}
{row.dofollow ? "Follow" : "Nofollow"}
) : (

No live backlinks found for this domain in the index yet.

)}

{hasMore ? ( <> Showing the top {topBacklinks.length} backlinks, one per referring domain, strongest domains first.{" "} {formatCount(total)} total backlinks {" "} are in the index for this domain. ) : ( <> Explore the full picture: referring domains, anchors, new and lost links, and spam signals. )}

); }