documentation
blockrate docs
A 1.6 KB client library that measures per-provider block rate. Drop it in, point it at blockrate.app or your own server, see exactly how much each third-party tool is being blocked.
Quick start
| 1 | bun add blockrate |
The library runs in the browser, checks each provider, and calls your reporter with the results. There are two ways to collect data:
Option A: Hosted dashboard (blockrate.app)
Sign up, get an API key from /app/keys, and use serverReporter. No server code needed — blockrate.app stores and visualizes the data.
| 1 | import { BlockRate, serverReporter } from "blockrate"; |
| 2 | |
| 3 | new BlockRate({ |
| 4 | providers: ["optimizely", "posthog", "ga4"], |
| 5 | service: "my-app", |
| 6 | reporter: serverReporter({ |
| 7 | endpoint: "https://blockrate.app/api", |
| 8 | apiKey: "br_your_key_here", |
| 9 | }), |
| 10 | sampleRate: 0.1, // check 10% of sessions |
| 11 | }).check(); |
Option B: Self-hosted (blockrate-server)
Run blockrate-server on your own infrastructure. Same library, different endpoint.
| 1 | import { BlockRate, serverReporter } from "blockrate"; |
| 2 | |
| 3 | new BlockRate({ |
| 4 | providers: ["optimizely", "posthog", "ga4"], |
| 5 | reporter: serverReporter({ |
| 6 | endpoint: "https://br.your-domain.com", |
| 7 | apiKey: "br_your_self_hosted_key", |
| 8 | }), |
| 9 | }).check(); |
Option C: Custom pipeline
Write your own reporter to forward results anywhere — BigQuery, Datadog, a webhook, your own API. The reporter receives a BlockRateResult object.
| 1 | import { BlockRate } from "blockrate"; |
| 2 | |
| 3 | new BlockRate({ |
| 4 | providers: ["optimizely", "posthog", "ga4"], |
| 5 | reporter: (result) => { |
| 6 | // result.providers = [{ name, status, latency }, ...] |
| 7 | fetch("/your-api/analytics", { |
| 8 | method: "POST", |
| 9 | body: JSON.stringify(result), |
| 10 | headers: { "Content-Type": "application/json" }, |
| 11 | keepalive: true, |
| 12 | }); |
| 13 | }, |
| 14 | }).check(); |
Built-in providers
Each provider is checked first via a window global (fast — the script already loaded), then via a fetch HEAD probe to its CDN with mode: "cors". If the ad blocker redirects to a local response (which lacks CORS headers), the fetch throws — correctly detected as blocked.
| Name | Detection |
|---|---|
| optimizely | window.optimizely + cdn.optimizely.com probe |
| posthog | window.posthog + us.i.posthog.com / eu.i.posthog.com probe |
| ga4 | window.gtag / dataLayer + google-analytics.com probe |
| gtm | window.google_tag_manager + googletagmanager.com probe |
| segment | window.analytics + cdn.segment.com probe |
| hotjar | window.hj + static.hotjar.com probe |
| amplitude | window.amplitude + cdn.amplitude.com probe |
| mixpanel | window.mixpanel + cdn.mxpnl.com probe |
| meta-pixel | window.fbq + connect.facebook.net probe |
| intercom | window.Intercom + widget.intercom.io probe |
Need a provider we don't ship? Add your own:
| 1 | import { BlockRate, createProvider, serverReporter } from "blockrate"; |
| 2 | |
| 3 | const myProvider = createProvider({ |
| 4 | name: "my-analytics", |
| 5 | detect: async () => (window.myAnalytics ? "loaded" : "blocked"), |
| 6 | }); |
| 7 | |
| 8 | new BlockRate({ |
| 9 | providers: ["posthog", myProvider], // mix built-in + custom |
| 10 | reporter: serverReporter({ endpoint: "https://blockrate.app/api", apiKey: "..." }), |
| 11 | }).check(); |
Framework guides
The library is framework-agnostic — it's just a class that calls .check(). These guides show the idiomatic way to wire it into each framework so it runs once per session, handles SSR safely, and doesn't block rendering.
React
The useBlockRate hook runs once on mount, skips on the server, and handles cleanup.
| 1 | import { useBlockRate } from "blockrate/react"; |
| 2 | import { serverReporter } from "blockrate"; |
| 3 | |
| 4 | function App() { |
| 5 | useBlockRate({ |
| 6 | providers: ["optimizely", "posthog", "ga4"], |
| 7 | reporter: serverReporter({ |
| 8 | endpoint: "https://blockrate.app/api", |
| 9 | apiKey: process.env.NEXT_PUBLIC_BR_KEY!, |
| 10 | }), |
| 11 | sampleRate: 0.1, |
| 12 | }); |
| 13 | |
| 14 | return <div>...</div>; |
| 15 | } |
Next.js (App Router)
Add a client component that calls useBlockRate and drop it in your root layout. The "use client" directive is required because the library uses browser APIs.
| 1 | "use client"; |
| 2 | |
| 3 | import { useBlockRate } from "blockrate/react"; |
| 4 | import { serverReporter } from "blockrate"; |
| 5 | |
| 6 | export function BlockRate() { |
| 7 | useBlockRate({ |
| 8 | providers: ["optimizely", "posthog", "ga4"], |
| 9 | reporter: serverReporter({ |
| 10 | endpoint: "https://blockrate.app/api", |
| 11 | apiKey: process.env.NEXT_PUBLIC_BR_KEY!, |
| 12 | }), |
| 13 | sampleRate: 0.1, |
| 14 | }); |
| 15 | return null; |
| 16 | } |
| 1 | import { BlockRate } from "@/components/blockrate"; |
| 2 | |
| 3 | export default function RootLayout({ children }) { |
| 4 | return ( |
| 5 | <html> |
| 6 | <body> |
| 7 | {children} |
| 8 | <BlockRate /> |
| 9 | </body> |
| 10 | </html> |
| 11 | ); |
| 12 | } |
SvelteKit
Call BlockRate in onMount in your root layout.
| 1 | <script lang="ts"> |
| 2 | import { onMount } from "svelte"; |
| 3 | import { BlockRate, serverReporter } from "blockrate"; |
| 4 | |
| 5 | onMount(() => { |
| 6 | new BlockRate({ |
| 7 | providers: ["optimizely", "posthog", "ga4"], |
| 8 | reporter: serverReporter({ |
| 9 | endpoint: "https://blockrate.app/api", |
| 10 | apiKey: import.meta.env.VITE_BR_KEY, |
| 11 | }), |
| 12 | sampleRate: 0.1, |
| 13 | }).check(); |
| 14 | }); |
| 15 | </script> |
| 16 | |
| 17 | <slot /> |
TanStack Start
Same useBlockRate hook as React, dropped into the root layout component.
| 1 | import { useBlockRate } from "blockrate/react"; |
| 2 | import { serverReporter } from "blockrate"; |
| 3 | |
| 4 | function RootLayout() { |
| 5 | useBlockRate({ |
| 6 | providers: ["optimizely", "posthog", "ga4"], |
| 7 | reporter: serverReporter({ |
| 8 | endpoint: "https://blockrate.app/api", |
| 9 | apiKey: import.meta.env.VITE_BR_KEY, |
| 10 | }), |
| 11 | sampleRate: 0.1, |
| 12 | }); |
| 13 | |
| 14 | return <Outlet />; |
| 15 | } |
Vanilla JS / script tag
Import the library directly in a script tag. Works in any site.
| 1 | <script type="module"> |
| 2 | import { BlockRate, serverReporter } from "https://esm.sh/blockrate"; |
| 3 | |
| 4 | new BlockRate({ |
| 5 | providers: ["optimizely", "posthog", "ga4"], |
| 6 | reporter: serverReporter({ |
| 7 | endpoint: "https://blockrate.app/api", |
| 8 | apiKey: "br_your_key_here", |
| 9 | }), |
| 10 | sampleRate: 0.1, |
| 11 | }).check(); |
| 12 | </script> |
Need the hosted API reference? See /docs/api · Self-hosting? See packages/server