shadimage
atroui
blockanalytics-providersource: ok · hit

Analytics Provider

Plausible / GA loader with trackEvent helpers.

npx shadcn add "https://www.atroui.com/r/analytics-provider.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · medium
frameworknext

Registry dependencies

@atroui/analytics

Files1 · source cached 10/8/2026, 7:40:48 PM

registry/default/blocks/analytics-provider.tsx
"use client";

import { useEffect } from "react";
import Script from "next/script";

import { getExperimentVariant, trackEvent } from "@/lib/analytics";

export { trackEvent, getExperimentVariant };

type AnalyticsProviderProps = {
  children?: React.ReactNode;
};

/**
 * Loads optional Plausible/GA scripts and exposes experiment tracking.
 * Set NEXT_PUBLIC_PLAUSIBLE_DOMAIN or NEXT_PUBLIC_GA_ID in env.
 */
export function AnalyticsProvider({ children }: AnalyticsProviderProps) {
  const plausibleDomain = process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN;
  const rawGaId = process.env.NEXT_PUBLIC_GA_ID ?? "";
  // Only allow Measurement ID shape (G-XXXXXXXX) to avoid script injection.
  const gaId = /^G-[A-Z0-9]+$/i.test(rawGaId) ? rawGaId : undefined;

  useEffect(() => {
    trackEvent("page_view", { path: window.location.pathname });
  }, []);

  return (
    <>
      {plausibleDomain ? (
        <Script
          defer
          data-domain={plausibleDomain}
          src="https://plausible.io/js/script.js"
          strategy="afterInteractive"
        />
      ) : null}
      {gaId ? (
        <>
          <Script
            src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
            strategy="afterInteractive"
          />
          <Script id="ga-init" strategy="afterInteractive">
            {`window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','${gaId}');`}
          </Script>
        </>
      ) : null}
      {children}
    </>
  );
}

export function useExperiment(experimentId: string, variants: string[], weights?: number[]) {
  useEffect(() => {
    getExperimentVariant({ id: experimentId, variants, weights });
  }, [experimentId, variants, weights]);
}

More from atroui

Browse all components in this library →