A lightweight React component for Umami Analytics — the privacy-focused, open-source alternative to Google Analytics.
Zero runtime dependencies. Full TypeScript support. Works with React 18.2+ and 19.
pnpm add @danielgtmn/umami-reactimport UmamiAnalytics from '@danielgtmn/umami-react';
function App() {
return (
<>
<UmamiAnalytics
url="https://analytics.example.com"
websiteId="your-website-id"
/>
{/* Your app content */}
</>
);
}The component renders nothing — it only injects the Umami tracking script.
| Prop | Type | Default | Description |
|---|---|---|---|
url |
string |
UMAMI_URL env var |
Your Umami instance URL |
websiteId |
string |
UMAMI_ID env var |
Your website tracking ID |
debug |
boolean |
false |
Log debug info to console |
lazyLoad |
boolean |
false |
Load script on first user interaction |
onlyInProduction |
boolean |
true |
Skip loading in development |
domains |
string[] |
— | Restrict tracking to specific domains |
scriptAttributes |
Record<string, string> |
— | Additional <script> attributes |
All props can also be set via environment variables:
UMAMI_URL=https://analytics.example.com
UMAMI_ID=your-website-id
UMAMI_DEBUG=false
UMAMI_LAZY_LOAD=trueUse the useUmami hook for custom events, pageviews, and user identification:
import { useUmami } from '@danielgtmn/umami-react';
function MyComponent() {
const { track, trackPageview, identify } = useUmami();
return (
<button onClick={() => track('signup', { plan: 'pro' })}>
Sign up
</button>
);
}const {
track, // track(eventName, eventData?)
trackPageview, // trackPageview(pageviewData?)
trackPageviewWithUTM, // trackPageviewWithUTM(utmParams, additionalData?)
trackPageviewAsync, // trackPageviewAsync(utmId, fetcherFn, additionalData?)
identify, // identify(userId) or identify(sessionData)
} = useUmami();const { trackPageviewWithUTM } = useUmami();
trackPageviewWithUTM({
utm_source: 'newsletter',
utm_medium: 'email',
utm_campaign: 'spring-sale',
});Fetch UTM parameters from your backend before tracking:
import { useUmami, UTMFetcher } from '@danielgtmn/umami-react';
const fetchUTM: UTMFetcher = async (utmId) => {
const res = await fetch(`/api/utm/${utmId}`);
return res.json();
};
// Fetches UTM data, then tracks the pageview
// Falls back to basic pageview if the fetch fails
await trackPageviewAsync('campaign-123', fetchUTM);const { identify } = useUmami();
// With a string ID
identify('user-123');
// With session data
identify({ userId: 'user-123', plan: 'pro' });
// Both
identify('user-123', { plan: 'pro' });To manually control pageview tracking, disable Umami's auto-tracking:
<UmamiAnalytics
url="https://analytics.example.com"
websiteId="your-website-id"
scriptAttributes={{ 'data-auto-track': 'false' }}
/>// app/layout.tsx
import UmamiAnalytics from '@danielgtmn/umami-react';
export default function RootLayout({ children }) {
return (
<html>
<body>
<UmamiAnalytics
url="https://analytics.example.com"
websiteId="your-website-id"
/>
{children}
</body>
</html>
);
}// src/App.tsx
import UmamiAnalytics from '@danielgtmn/umami-react';
function App() {
return (
<>
<UmamiAnalytics
url="https://analytics.example.com"
websiteId="your-website-id"
/>
{/* Your app */}
</>
);
}All types are exported:
import type {
UmamiAnalyticsProps,
UmamiConfig,
PageviewData,
UTMFetcher,
} from '@danielgtmn/umami-react';pnpm install # Install dependencies
pnpm dev # Watch mode
pnpm build # Production build
pnpm test # Run tests
pnpm test:coverage # Tests with coverage
pnpm lint # Lint
pnpm type-check # Type check
pnpm size # Check bundle sizeCommits follow Conventional Commits. Git hooks (Husky) run type-check, lint, and tests before each commit.
- Fork the repo
- Create your branch (
git checkout -b feat/my-feature) - Make sure all checks pass (
pnpm test:run && pnpm lint && pnpm type-check) - Commit using conventional commit format
- Open a Pull Request