npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@giof/react-umami

v2.6.12

Published

Lightweight Umami Analytics component for React (~2.6kB) with dry-run testing and debug features

Readme

@giof/react-umami – Umami Analytics for React

A React component for Umami Analytics with built-in dry-run testing, debug logging, and SSR safety.

🧪 Features dry-run mode for clean development - test your tracking without polluting production data!

📦 Bundle Size

  • Your bundle impact: ~2.6 kB (minified + gzipped)
  • npm package size: 26.8 kB (includes documentation - not bundled into your app)

CI npm version License: MIT

🚀 Installation

Install the package via pnpm, npm, or yarn:

pnpm add @giof/react-umami
# or
npm install @giof/react-umami
# or
yarn add @giof/react-umami

📊 Usage

Add the component to your React application:

// In your main app component or layout
import { UmamiAnalytics } from '@giof/react-umami';

export default function App() {
  return (
    <div>
      {/* Your app content */}
      <UmamiAnalytics />
    </div>
  );
}

Next.js Usage

App Router (Recommended)

⚠️ Important for Next.js + App Router: You MUST use a client wrapper component to avoid build errors caused by mixing server and client components. See the complete Next.js example for details.

For Next.js 13+ with App Router, you need to create a client wrapper component to avoid SSR/client-side mixing issues:

Step 1: Create a client wrapper component

// components/ClientUmamiAnalytics.tsx
'use client';

import dynamic from 'next/dynamic';

// Dynamically import UmamiAnalytics with SSR disabled
const UmamiAnalytics = dynamic(
  () => import('@giof/react-umami').then((mod) => ({ default: mod.UmamiAnalytics })),
  { 
    ssr: false,
    loading: () => null 
  }
);

interface ClientUmamiAnalyticsProps {
  websiteId?: string;
  src?: string;
  domains?: string[];
  autoTrack?: boolean;
  dryRun?: boolean;
  debug?: boolean;
}

export default function ClientUmamiAnalytics(props: ClientUmamiAnalyticsProps) {
  return <UmamiAnalytics {...props} />;
}

Step 2: Use the wrapper in your layout

// app/layout.tsx
import ClientUmamiAnalytics from '@/components/ClientUmamiAnalytics';

export default function RootLayout({ 
  children 
}: { 
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <head />
      <body>
        {children}
        <ClientUmamiAnalytics 
          dryRun={process.env.NODE_ENV === 'development'}
          debug={process.env.NODE_ENV === 'development'}
        />
      </body>
    </html>
  );
}

Pages Router (Legacy)

For Next.js Pages Router, you can use the component directly:

// pages/_app.tsx
import { UmamiAnalytics } from '@giof/react-umami';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <UmamiAnalytics />
    </>
  );
}

Create React App / Vite Usage

// src/App.tsx
import { UmamiAnalytics } from '@giof/react-umami';

function App() {
  return (
    <div className="App">
      {/* Your app content */}
      <UmamiAnalytics />
    </div>
  );
}

export default App;

⚙️ Configuration

Environment Variables

Configure your Umami analytics through environment variables:

# Universal (works with all frameworks - server-side and build-time)
UMAMI_WEBSITE_ID=your-website-id-here
UMAMI_SCRIPT_URL=https://your-umami-instance.com/script.js

Framework-specific client-side variables (required for browser access):

# Next.js (client-side access requires NEXT_PUBLIC_ prefix)
NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-website-id-here
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://your-umami-instance.com/script.js

# Create React App (client-side access requires REACT_APP_ prefix)
REACT_APP_UMAMI_WEBSITE_ID=your-website-id-here
REACT_APP_UMAMI_SCRIPT_URL=https://your-umami-instance.com/script.js

💡 Pro Tip: For Next.js, you can use both! Use UMAMI_* for server-side and NEXT_PUBLIC_UMAMI_* for client-side access.

The component will check environment variables in this order:

Website ID:

  1. UMAMI_WEBSITE_ID (recommended - works everywhere)
  2. NEXT_PUBLIC_UMAMI_WEBSITE_ID (Next.js)
  3. REACT_APP_UMAMI_WEBSITE_ID (Create React App)

Script URL:

  1. UMAMI_SCRIPT_URL (recommended - works everywhere)
  2. NEXT_PUBLIC_UMAMI_SCRIPT_URL (Next.js)
  3. REACT_APP_UMAMI_SCRIPT_URL (Create React App)
  4. https://cloud.umami.is/script.js (default fallback)

Props

You can also configure the component through props:

<UmamiAnalytics 
  websiteId="your-website-id" 
  src="https://your-umami-instance.com/script.js"
  domains={['example.com', 'www.example.com']}
  autoTrack={false}
/>

| Prop | Type | Default | Description | |------|------|---------|-------------| | websiteId | string | process.env.UMAMI_WEBSITE_ID | Your Umami website ID | | src | string | process.env.UMAMI_SCRIPT_URL or https://cloud.umami.is/script.js | The URL of your Umami script | | domains | string[] | undefined | Restrict tracking to specific domains | | autoTrack | boolean | true | Whether to automatically track page views | | dryRun | boolean | false | 🧪 Enable dry run mode - no real events sent to Umami | | debug | boolean | false | 🔍 Enable debug logging - detailed console output |

Note: The component checks multiple environment variable names for maximum compatibility across frameworks.

🧪 Dry Run Mode

Built-in dry-run testing for clean development!

What is Dry Run Mode?

When dryRun={true}, the component:

  • 🚫 Never loads external scripts - no network requests to Umami servers
  • 🎭 Creates a mock tracker - your app works exactly the same
  • 📝 Logs all events to console - see exactly what would be tracked
  • 🛡️ Protects your data - no test/dev events pollute production analytics

Perfect for Development

// Environment-aware setup
<UmamiAnalytics 
  websiteId="your-website-id"
  dryRun={process.env.NODE_ENV === 'development'}
  debug={process.env.NODE_ENV === 'development'}
/>

What you'll see in console:

UmamiAnalytics [DRY RUN]: Would track event: button_click {
  button: "signup",
  location: "header",
  userId: "123"
}

Testing Made Easy

// Test your analytics without external dependencies
describe('Analytics Integration', () => {
  it('tracks user signup', () => {
    render(<App />);
    
    fireEvent.click(screen.getByText('Sign Up'));
    
    // Verify tracking calls in dry run mode
    expect(console.log).toHaveBeenCalledWith(
      'UmamiAnalytics [DRY RUN]: Would track event:',
      'signup',
      { source: 'header' }
    );
  });
});

Privacy & Compliance

// Respect user consent while maintaining functionality
<UmamiAnalytics 
  websiteId="your-website-id"
  dryRun={!userConsent.analytics}
  debug={!userConsent.analytics}
/>

Why This Matters

Other libraries force you to choose:

  • Pollute production data with test events
  • Complex mocking setup for testing
  • No visibility into what's being tracked

With dry run mode:

  • Clean production data guaranteed
  • Zero-config testing
  • Full transparency of tracking behavior
  • Same API in development and production

🚀 Advanced Usage Examples

Development & Testing

// Perfect for development - see everything that's happening
<UmamiAnalytics 
  websiteId="your-website-id"
  debug={true}
  dryRun={true}  // No real events sent in development
/>

Event Tracking with Utilities

import { UmamiAnalytics, trackEvent, trackPageView } from '@giof/react-umami';

// Track custom events
const handleButtonClick = () => {
  trackEvent('button_click', { 
    button: 'signup',
    location: 'header' 
  });
};

// Track page views manually
const handleNavigation = (path: string) => {
  trackPageView(path, 'Custom Page Title');
};

Advanced Hook Usage

import { useUmami } from '@giof/react-umami';
import { useEffect } from 'react';

function MyComponent() {
  const { track, trackPage, isLoaded, updateConfig } = useUmami();

  // Override configuration at runtime
  useEffect(() => {
    if (process.env.NODE_ENV === 'development') {
      updateConfig({ dryRun: true, debug: true });
    }
  }, [updateConfig]);

  const handleClick = () => {
    track('user_action', { component: 'MyComponent' });
  };

  return <button onClick={handleClick}>Track Me</button>;
}

Self-Hosted Umami Configuration

// Using environment variables for self-hosted Umami
<UmamiAnalytics 
  domains={['yoursite.com', 'www.yoursite.com']}
/>
# .env file
UMAMI_WEBSITE_ID=your-website-id-here
UMAMI_SCRIPT_URL=https://analytics.yourcompany.com/script.js

Production Configuration

// Perfect for production - minimal setup, maximum reliability
<UmamiAnalytics 
  domains={['yoursite.com', 'www.yoursite.com']}
  autoTrack={true}
/>

✨ Features

🧪 Dry Run Mode

Test analytics integration without sending real events. Perfect for development, testing, and respecting user privacy.

🔍 Debug Logging

Detailed console output for development and troubleshooting. See exactly what's happening under the hood.

🛡️ SSR Safety

Built-in server-side rendering protection for Next.js, Remix, and other SSR frameworks. Includes Next.js App Router integration guide.

⚙️ Runtime Configuration

Override settings dynamically with the useUmami hook. Perfect for consent management.

🎯 Event Tracking Helpers

Simple trackEvent() and trackPageView() utilities for custom analytics.

🌐 Framework Agnostic

Works seamlessly with Next.js, Create React App, Vite, Remix, and any React setup.

🔧 Environment Variables

Universal UMAMI_WEBSITE_ID with automatic framework fallbacks for maximum compatibility.

📘 Full TypeScript Support

Complete type definitions included. IntelliSense and type safety out of the box.

📦 Zero Dependencies

No external dependencies. Lightweight and fast.

🧹 Auto Cleanup

Automatic script removal on component unmount. No memory leaks.

🚫 Duplicate Prevention

Smart script injection prevents conflicts and duplicate loading.

🏠 Domain Restrictions

Limit tracking to specific domains for enhanced security.

🛠️ Development

Clone and set up the project:

# Clone repository
git clone https://github.com/giof-se/umami.git
cd umami

# Install dependencies
pnpm install

# Run tests
pnpm test

# Format code
pnpm fmt

# Lint code
pnpm lint

🧪 Testing

Run tests with:

# Run tests once
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run tests with coverage
pnpm test:coverage

🚢 Releasing

This project uses automated versioning and changelog generation:

Automated Workflow

  1. Push your changes to the main branch
  2. Version is automatically bumped based on commit message types:
    • feat: or feature: for minor version bump
    • BREAKING CHANGE: or major: for major version bump
    • All other changes result in patch version bump
  3. Changelog is automatically generated from commit messages
  4. New version is tagged and published to GitHub Packages

Commit Message Format

For best results with autoversioning, follow the Conventional Commits format:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Example commit messages:

  • feat: add domain restriction support (triggers minor version bump)
  • fix: correct data attribute handling (triggers patch version bump)
  • feat: add XYZ with BREAKING CHANGE: requires new config (triggers major version bump)

Improved CI/CD Pipeline

The CI/CD pipeline follows these steps:

  1. The Autoversion workflow runs when changes are pushed to the main branch
  2. It automatically increments the version based on commit messages
  3. The Publish workflow creates a GitHub release and publishes the package

The workflow has been enhanced to handle different trigger methods:

  • Direct tag pushes
  • Manual workflow dispatch with version input
  • Automated workflow runs from the autoversion workflow

Comparison

| Feature | @giof/react-umami | Other Libraries | |---------|----------------------|-----------------| | Dry Run Testing | ✅ | ❌ | | Debug Logging | ✅ | Limited | | SSR Safety | ✅ | Manual setup | | Runtime Config | ✅ | Static only | | Framework Support | Universal | Framework-specific | | TypeScript | Full support | Varies | | Dependencies | Zero | Varies |

Support

License

MIT © giof-se