Adopture

Event Tracking

Learn how to track feature usage, exposure, and user identification

Event Tracking

Learn how to track user interactions and feature usage in your Next.js application using Adopture's React hooks.

Basic Event Tracking

The most common way to track events is using the useTrack hook:

components/FeatureButton.tsx
'use client';

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

export function FeatureButton() {
  const { track } = useTrack();

  const handleClick = () => {
    // SDK automatically determines activation vs usage
    track('feature-button-click', {
      location: 'sidebar',
      timestamp: new Date().toISOString(),
    });
  };

  return (
    <button onClick={handleClick}>
      Use Feature
    </button>
  );
}

Feature Exposure Tracking

Track when users see features using the useExpose hook:

components/FeatureBanner.tsx
'use client';

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

export function FeatureBanner() {
  const { expose } = useExpose();

  useEffect(() => {
    // Track when the banner becomes visible
    expose('new-feature-banner', 'homepage-banner', {
      position: 'top',
      campaign: 'feature-launch',
    });
  }, [expose]);

  return (
    <div className="banner">
      Check out our new feature!
    </div>
  );
}

Automatic Component Tracking

For simpler exposure tracking, use the useComponentTracking hook:

components/ProductCard.tsx
'use client';

import { useComponentTracking, useTrack } from '@adopture/next';

export function ProductCard({ productId }: { productId: string }) {
  const { track } = useTrack();

  // Automatically track when component is visible
  useComponentTracking('product-card-view', {
    exposureChannel: 'product-listing',
    metadata: {
      productId,
      section: 'featured-products',
    },
  });

  const handlePurchase = () => {
    track('product-purchase-click', {
      productId,
      source: 'product-card',
    });
  };

  return (
    <div className="product-card">
      <h3>Product {productId}</h3>
      <button onClick={handlePurchase}>
        Buy Now
      </button>
    </div>
  );
}

User Identification

Identify users to track their journey across sessions:

components/LoginForm.tsx
'use client';

import { useIdentify } from '@adopture/next';
import { useState } from 'react';

export function LoginForm() {
  const { identify } = useIdentify();
  const [email, setEmail] = useState('');

  const handleLogin = async (userId: string) => {
    // Identify the user with their properties
    await identify(userId, {
      email,
      plan: 'pro',
      signupDate: '2024-01-15',
      company: 'Acme Corp',
    });

    // Now all future events will be associated with this user
  };

  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      handleLogin('user-123');
    }}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
      <button type="submit">Login</button>
    </form>
  );
}

Main Tracking Hook

For full control, use the useAdoptureTracking hook which combines all functionality:

components/AdvancedComponent.tsx
'use client';

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

export function AdvancedComponent() {
  const { track, expose, identify, isInitialized } = useAdoptureTracking();

  const handleComplexAction = async () => {
    if (!isInitialized) {
      console.log('Adopture not ready yet');
      return;
    }

    // Track feature usage
    await track('complex-action', {
      step: 'initiated',
      timestamp: new Date().toISOString(),
    });

    // Expose a related feature
    await expose('related-feature', 'action-flow', {
      trigger: 'complex-action',
    });
  };

  return (
    <button onClick={handleComplexAction}>
      Complex Action
    </button>
  );
}

Metadata Best Practices

Include meaningful metadata with your events:

// ✅ Good metadata
track('button-click', {
  buttonType: 'primary',
  location: 'navbar',
  section: 'user-menu',
  variant: 'cta',
  timestamp: new Date().toISOString(),
});

// ❌ Avoid metadata with sensitive information
track('user-action', {
  email: 'user@example.com', // Don't include PII
  password: '***', // Never include passwords
  creditCard: '****', // No financial data
});

Event Naming Conventions

Use consistent naming for your events:

// ✅ Good naming - descriptive and consistent
track('feature-dashboard-opened');
track('export-button-clicked');
track('settings-saved');

// ❌ Inconsistent naming
track('dash_open');
track('clickExport');
track('save-settings');

Error Handling

Handle tracking errors gracefully:

'use client';

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

export function RobustComponent() {
  const { track, isReady } = useTrack();

  const handleAction = async () => {
    try {
      if (!isReady) {
        console.warn('Tracking not ready, action will be queued');
      }

      await track('important-action', {
        timestamp: new Date().toISOString(),
      });
    } catch (error) {
      console.error('Failed to track event:', error);
      // Continue with the user action regardless
    }
  };

  return (
    <button onClick={handleAction}>
      Important Action
    </button>
  );
}

Conditional Tracking

Track events only when certain conditions are met:

'use client';

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

export function ConditionalTracking({ userPlan }: { userPlan: string }) {
  const { track } = useTrack();

  const handlePremiumFeature = () => {
    // Only track for premium users
    if (userPlan === 'premium') {
      track('premium-feature-used', {
        feature: 'advanced-analytics',
        plan: userPlan,
      });
    }
  };

  return (
    <button onClick={handlePremiumFeature}>
      Premium Feature
    </button>
  );
}

Client-Side Only

Remember that all tracking hooks require the 'use client' directive:

'use client'; // Required for all components using Adopture hooks

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

export function ClientComponent() {
  const { track } = useTrack();
  // Component logic...
}

Next Steps

Common Patterns

Form Tracking

const handleSubmit = (formData) => {
  track('form-submitted', {
    formType: 'contact',
    fields: Object.keys(formData),
    timestamp: new Date().toISOString(),
  });
};

Page View Tracking

useEffect(() => {
  expose('page-view', 'navigation', {
    page: router.pathname,
    referrer: document.referrer,
  });
}, [router.pathname]);

Feature Flag Integration

if (featureFlag.isEnabled('new-feature')) {
  expose('new-feature', 'feature-flag');
}