Adopture

Provider Components

API reference for Adopture provider components

Provider Components API Reference

Complete reference for Adopture provider components that wrap your Next.js application.

AdoptureProvider

Provider component for Next.js App Router applications.

import { AdoptureProvider } from '@adopture/next';

<AdoptureProvider config={config} fallback={fallback} loadingComponent={loading}>
  {children}
</AdoptureProvider>

Props

PropTypeRequiredDescription
childrenReactNodeYour application components
configNextAdoptureConfigConfiguration options
fallbackReactNodeFallback component for errors
loadingComponentReactNodeLoading component during initialization

NextAdoptureConfig Type

interface NextAdoptureConfig {
  apiKey?: string;
  apiUrl?: string;
  debug?: boolean;
  batchSize?: number;
  flushInterval?: number;
  timeout?: number;
}

Configuration Options

OptionTypeDefaultDescription
apiKeystringprocess.env.NEXT_PUBLIC_ADOPTURE_API_KEYYour Adopture API key
apiUrlstring'https://api.adopture.com'API endpoint URL
debugbooleanfalseEnable debug logging
batchSizenumber50Events to batch before sending
flushIntervalnumber5000Interval (ms) to flush events
timeoutnumber10000Request timeout (ms)

Basic Usage

app/layout.tsx
import { AdoptureProvider } from '@adopture/next';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <AdoptureProvider>
          {children}
        </AdoptureProvider>
      </body>
    </html>
  );
}

Advanced Configuration

app/layout.tsx
import { AdoptureProvider } from '@adopture/next';

const adoptureConfig = {
  debug: process.env.NODE_ENV === 'development',
  batchSize: 100,
  flushInterval: 3000,
  timeout: 15000,
};

const LoadingFallback = () => (
  <div className="flex items-center justify-center h-screen">
    <div>Initializing analytics...</div>
  </div>
);

const ErrorFallback = () => (
  <div className="bg-yellow-50 p-4 rounded">
    <p>Analytics temporarily unavailable</p>
  </div>
);

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <AdoptureProvider
          config={adoptureConfig}
          loadingComponent={<LoadingFallback />}
          fallback={<ErrorFallback />}
        >
          {children}
        </AdoptureProvider>
      </body>
    </html>
  );
}

AdopturePagesProvider

Provider component for Next.js Pages Router applications.

import { AdopturePagesProvider } from '@adopture/next';

<AdopturePagesProvider config={config} fallback={fallback} loadingComponent={loading}>
  {children}
</AdopturePagesProvider>

Props

Same as AdoptureProvider but optimized for Pages Router.

Usage

pages/_app.tsx
import { AdopturePagesProvider } from '@adopture/next';
import type { AppProps } from 'next/app';

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

Advanced Configuration

pages/_app.tsx
import { AdopturePagesProvider } from '@adopture/next';
import type { AppProps } from 'next/app';

const adoptureConfig = {
  debug: process.env.NODE_ENV === 'development',
  batchSize: 50,
  flushInterval: 5000,
};

export default function App({ Component, pageProps }: AppProps) {
  return (
    <AdopturePagesProvider
      config={adoptureConfig}
      fallback={<div>Analytics unavailable</div>}
    >
      <Component {...pageProps} />
    </AdopturePagesProvider>
  );
}

AdoptureBootstrap

Component for injecting server-side bootstrap data.

import { AdoptureBootstrap } from '@adopture/next';

<AdoptureBootstrap data={bootstrapData} />

Props

PropTypeRequiredDescription
dataBootstrapDataServer-side bootstrap data

BootstrapData Type

interface BootstrapData {
  config: NextAdoptureConfig;
  sessionId: string;
  timestamp: number;
  initialUserId?: string;
  initialUserProperties?: UserProperties;
}

Usage

app/layout.tsx
import { AdoptureProvider, AdoptureBootstrap } from '@adopture/next';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const bootstrapData = {
    config: {
      apiKey: process.env.NEXT_PUBLIC_ADOPTURE_API_KEY,
      debug: process.env.NODE_ENV === 'development',
    },
    sessionId: 'session-123',
    timestamp: Date.now(),
    initialUserId: 'user-456',
    initialUserProperties: {
      plan: 'premium',
      email: 'user@example.com',
    },
  };

  return (
    <html lang="en">
      <head>
        <AdoptureBootstrap data={bootstrapData} />
      </head>
      <body>
        <AdoptureProvider>
          {children}
        </AdoptureProvider>
      </body>
    </html>
  );
}

useAdopture

Hook to access the Adopture context directly.

import { useAdopture } from '@adopture/next';

const {
  tracker,
  isInitialized,
  isLoading,
  error,
  config
} = useAdopture();

Returns

PropertyTypeDescription
trackerNextAdoptureTracker | nullTracker instance
isInitializedbooleanWhether tracker is initialized
isLoadingbooleanWhether tracker is loading
errorError | nullInitialization error
configNextAdoptureConfig | nullCurrent configuration

Example

'use client';

import { useAdopture } from '@adopture/next';

export function DebugPanel() {
  const { tracker, isInitialized, isLoading, error, config } = useAdopture();

  if (isLoading) {
    return <div>Loading Adopture...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  if (!isInitialized) {
    return <div>Adopture not initialized</div>;
  }

  return (
    <div className="debug-panel">
      <h3>Adopture Debug Panel</h3>
      <p>Status: {isInitialized ? 'Ready' : 'Not Ready'}</p>
      <p>Debug Mode: {config?.debug ? 'On' : 'Off'}</p>
      <p>Batch Size: {config?.batchSize}</p>
      <p>Flush Interval: {config?.flushInterval}ms</p>
    </div>
  );
}

useAdoptureTracker

Hook to access the tracker instance directly.

import { useAdoptureTracker } from '@adopture/next';

const tracker = useAdoptureTracker();

Returns

PropertyTypeDescription
trackerNextAdoptureTracker | nullTracker instance or null

Example

'use client';

import { useAdoptureTracker } from '@adopture/next';

export function AdvancedTracking() {
  const tracker = useAdoptureTracker();

  const handleAdvancedEvent = async () => {
    if (tracker) {
      // Direct access to tracker methods
      await tracker.track('advanced-event', {
        timestamp: Date.now(),
        complex: true,
      });
    }
  };

  return (
    <button onClick={handleAdvancedEvent}>
      Advanced Event
    </button>
  );
}

Environment Configuration

Configure providers through environment variables:

.env.local
# Required
NEXT_PUBLIC_ADOPTURE_API_KEY=your_api_key_here

# Optional - Provider configuration
NEXT_PUBLIC_ADOPTURE_API_URL=https://api.adopture.com
NEXT_PUBLIC_ADOPTURE_DEBUG=true
NEXT_PUBLIC_ADOPTURE_BATCH_SIZE=50
NEXT_PUBLIC_ADOPTURE_FLUSH_INTERVAL=5000
NEXT_PUBLIC_ADOPTURE_TIMEOUT=10000

Error Handling

Provider-Level Error Handling

const ErrorFallback = ({ error }: { error: Error }) => (
  <div className="error-boundary">
    <h2>Analytics Error</h2>
    <p>{error.message}</p>
    <button onClick={() => window.location.reload()}>
      Retry
    </button>
  </div>
);

<AdoptureProvider
  fallback={<ErrorFallback error={new Error('Sample error')} />}
>
  {children}
</AdoptureProvider>

Global Error Handling

'use client';

import { useAdopture } from '@adopture/next';
import { useEffect } from 'react';

export function GlobalErrorHandler() {
  const { error } = useAdopture();

  useEffect(() => {
    if (error) {
      console.error('Adopture initialization failed:', error);
      // Report to error tracking service
      // errorTracker.captureException(error);
    }
  }, [error]);

  return null;
}

Performance Considerations

Lazy Loading

import { lazy, Suspense } from 'react';

const AdoptureProvider = lazy(() =>
  import('@adopture/next').then(mod => ({ default: mod.AdoptureProvider }))
);

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <Suspense fallback={<div>Loading...</div>}>
          <AdoptureProvider>
            {children}
          </AdoptureProvider>
        </Suspense>
      </body>
    </html>
  );
}

Conditional Loading

const shouldLoadAdopture = process.env.NODE_ENV === 'production';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {shouldLoadAdopture ? (
          <AdoptureProvider>
            {children}
          </AdoptureProvider>
        ) : (
          children
        )}
      </body>
    </html>
  );
}

Best Practices

  1. Single Provider: Only use one provider per application
  2. Environment Variables: Use environment variables for configuration
  3. Error Boundaries: Always provide fallback components
  4. Performance: Consider lazy loading for non-critical applications
  5. Development: Use debug mode during development
  6. Testing: Disable or mock providers in tests

TypeScript Support

All provider components are fully typed:

import type {
  NextAdoptureConfig,
  NextAdoptureProviderProps,
  BootstrapData,
  NextAdoptureContext,
} from '@adopture/next';

Migration Guide

From Other Analytics

If migrating from other analytics providers:

// Before (Google Analytics)
<GoogleAnalyticsProvider>
  {children}
</GoogleAnalyticsProvider>

// After (Adopture)
<AdoptureProvider>
  {children}
</AdoptureProvider>

Gradual Migration

For gradual migration, you can run both providers:

<GoogleAnalyticsProvider>
  <AdoptureProvider>
    {children}
  </AdoptureProvider>
</GoogleAnalyticsProvider>

Then gradually replace tracking calls and remove the old provider when ready.