Documentation

Next.js

Add Loamly to your Next.js application

Next.js is the most popular React framework, and Loamly integrates seamlessly with both the App Router and Pages Router. This guide covers both approaches.

App Router (Next.js 13+)

For Next.js 13+ with the App Router, add the Loamly script to your root layout using the Script component:

// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://app.loamly.ai/t.js?d=yourdomain.com"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

Strategy options

  • afterInteractive (recommended): Loads after the page becomes interactive
  • lazyOnload: Loads during browser idle time
  • beforeInteractive: Loads before hydration (not recommended for analytics)

Pages Router

For Next.js with the Pages Router, add the script to your _app.tsx:

// pages/_app.tsx
import Script from 'next/script';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Script
        src="https://app.loamly.ai/t.js?d=yourdomain.com"
        strategy="afterInteractive"
      />
      <Component {...pageProps} />
    </>
  );
}

Track custom events

Create a utility function to track events with TypeScript support:

// lib/analytics.ts

declare global {
  interface Window {
    loamly?: {
      event: (name: string, properties?: Record<string, unknown>) => void;
      page: (properties?: { path?: string; title?: string }) => void;
    };
  }
}

export function trackEvent(
  name: string,
  properties?: Record<string, unknown>
) {
  if (typeof window !== 'undefined' && window.loamly) {
    window.loamly.event(name, properties);
  }
}

export function trackPageView(path?: string, title?: string) {
  if (typeof window !== 'undefined' && window.loamly) {
    window.loamly.page({ path, title });
  }
}

Then use it in your components:

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

import { trackEvent } from '@/lib/analytics';

export function SignupButton() {
  const handleClick = () => {
    trackEvent('signup_clicked', {
      location: 'hero',
      variant: 'primary'
    });
  };

  return (
    <button onClick={handleClick}>
      Start Free Trial
    </button>
  );
}

Server Components

Loamly tracking runs entirely on the client. For Server Components, wrap any interactive tracking in a Client Component:

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

import { trackEvent } from '@/lib/analytics';
import Link from 'next/link';

interface Props {
  href: string;
  children: React.ReactNode;
  eventName?: string;
}

export function TrackableLink({ href, children, eventName }: Props) {
  const handleClick = () => {
    if (eventName) {
      trackEvent(eventName, { href });
    }
  };

  return (
    <Link href={href} onClick={handleClick}>
      {children}
    </Link>
  );
}

Environment variables

For different domains in development vs production, use environment variables:

// .env.local
NEXT_PUBLIC_DOMAIN=localhost:3000

// .env.production
NEXT_PUBLIC_DOMAIN=yourdomain.com
// app/layout.tsx
<Script
  src={`https://app.loamly.ai/t.js?d=${process.env.NEXT_PUBLIC_DOMAIN}`}
  strategy="afterInteractive"
/>

Development tracking

By default, Loamly filters out localhost traffic. If you want to test tracking in development, add your localhost domain to your workspace settings.