Skip to main content

Quick Setup

Install the SDK

npm install @userboost/sdk

Initialize in Your App

// App.js
import React, { useEffect } from "react";
import { UserBoost } from "@userboost/sdk";

function App() {
  useEffect(() => {
    UserBoost.init({
      apiKey: process.env.REACT_APP_USERBOOST_API_KEY,
      debug: process.env.NODE_ENV === "development",
    });
  }, []);

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

export default App;

Component Examples

Track Button Clicks

import { UserBoost } from "@userboost/sdk";

function SignupButton({ user }) {
  const handleClick = () => {
    UserBoost.event("signup_button_clicked", {
      user: { id: user.id },
      properties: {
        button_location: "header",
        user_plan: user.plan || "free",
      },
    });

    // Your signup logic here
  };

  return (
    <button onClick={handleClick} className="btn-primary">
      Get Started Free
    </button>
  );
}

Track Page Views with React Router

// App.js
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { UserBoost } from "@userboost/sdk";

function App() {
  const location = useLocation();
  const user = useCurrentUser(); // Your user hook

  useEffect(() => {
    if (user?.id) {
      UserBoost.event("page_view", {
        user: { id: user.id },
        properties: {
          page: location.pathname,
          referrer: document.referrer,
        },
      });
    }
  }, [location, user]);

  return (
    <Router>
      <Routes>{/* Your routes */}</Routes>
    </Router>
  );
}

Track Form Submissions

import { useState } from "react";
import { UserBoost } from "@userboost/sdk";

function ContactForm() {
  const [formData, setFormData] = useState({
    name: "",
    email: "",
    message: "",
  });

  const handleSubmit = async (e) => {
    e.preventDefault();

    // Track form submission start
    UserBoost.event("contact_form_submitted", {
      user: { id: formData.email }, // Use email as temp ID
      properties: {
        form_type: "contact",
        has_message: !!formData.message,
      },
    });

    try {
      // Submit form
      await submitContactForm(formData);

      // Track success
      UserBoost.event("contact_form_success", {
        user: { id: formData.email },
        properties: {
          response_time: Date.now() - startTime,
        },
      });
    } catch (error) {
      // Track errors
      UserBoost.event("contact_form_error", {
        user: { id: formData.email },
        properties: {
          error_type: error.message,
        },
      });
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
        placeholder="Your name"
      />
      <input
        type="email"
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        placeholder="Your email"
      />
      <textarea
        value={formData.message}
        onChange={(e) => setFormData({ ...formData, message: e.target.value })}
        placeholder="Your message"
      />
      <button type="submit">Send Message</button>
    </form>
  );
}

Custom Hooks

useUserBoost Hook

Create a custom hook for cleaner integration:
// hooks/useUserBoost.js
import { useCallback } from "react";
import { UserBoost } from "@userboost/sdk";
import { useUser } from "./useUser"; // Your user context

export function useUserBoost() {
  const { user } = useUser();

  const track = useCallback(
    (eventName, properties = {}) => {
      if (!user?.id) {
        console.warn("Cannot track event: user not identified");
        return;
      }

      UserBoost.event(eventName, {
        user: {
          id: user.id,
          email: user.email,
          name: user.name,
          traits: {
            plan: user.plan,
            type: user.type,
            signup_date: user.createdAt,
          },
        },
        properties: {
          ...properties,
        },
      });
    },
    [user]
  );

  return { track, identify, user };
}

Usage with Custom Hook

// components/FeatureCard.jsx
import { useUserBoost } from "../hooks/useUserBoost";

function FeatureCard({ feature }) {
  const { track } = useUserBoost();

  const handleFeatureClick = () => {
    track("feature_clicked", {
      feature_name: feature.name,
      feature_category: feature.category,
      is_premium: feature.isPremium,
    });

    // Navigate to feature
  };

  return (
    <div className="feature-card" onClick={handleFeatureClick}>
      <h3>{feature.name}</h3>
      <p>{feature.description}</p>
    </div>
  );
}

Advanced Patterns

Track User Onboarding Flow

// components/OnboardingWizard.jsx
import { useState, useEffect } from "react";
import { UserBoost } from "@userboost/sdk";

function OnboardingWizard({ user }) {
  const [currentStep, setCurrentStep] = useState(1);
  const [startTime] = useState(Date.now());

  // Track onboarding start
  useEffect(() => {
    UserBoost.event("onboarding_started", {
      user: { id: user.id },
      properties: {
        total_steps: 4,
      },
    });
  }, [user.id]);

  const handleStepComplete = (stepNumber, stepData) => {
    UserBoost.event("onboarding_step_completed", {
      user: { id: user.id },
      properties: {
        step_number: stepNumber,
        step_name: stepData.name,
        time_spent: Date.now() - startTime,
        ...stepData,
      },
    });

    if (stepNumber === 4) {
      // Track onboarding completion
      UserBoost.event("onboarding_completed", {
        user: { id: user.id },
        properties: {
          total_time: Date.now() - startTime,
          completion_rate: "100%",
        },
      });
    }

    setCurrentStep(stepNumber + 1);
  };

  return (
    <div className="onboarding-wizard">
      {currentStep === 1 && (
        <ProfileSetup
          onComplete={(data) =>
            handleStepComplete(1, {
              name: "profile_setup",
              has_avatar: !!data.avatar,
              company_size: data.companySize,
            })
          }
        />
      )}
      {currentStep === 2 && (
        <TeamInvitation
          onComplete={(data) =>
            handleStepComplete(2, {
              name: "team_invitation",
              members_invited: data.invitedCount,
              skipped: data.skipped,
            })
          }
        />
      )}
      {/* More steps... */}
    </div>
  );
}

Track Feature Usage

// hooks/useFeatureTracking.js
import { useEffect, useRef } from "react";
import { UserBoost } from "@userboost/sdk";
import { useUser } from "./useUser";

export function useFeatureTracking(featureName) {
  const { user } = useUser();
  const startTime = useRef(Date.now());
  const tracked = useRef(false);

  useEffect(() => {
    // Track feature view
    if (user?.id && !tracked.current) {
      UserBoost.event("feature_viewed", {
        user: { id: user.id },
        properties: {
          feature: featureName,
        },
      });
      tracked.current = true;
    }

    // Track time spent when component unmounts
    return () => {
      if (user?.id && tracked.current) {
        const timeSpent = Date.now() - startTime.current;
        UserBoost.event("feature_time_spent", {
          user: { id: user.id },
          properties: {
            feature: featureName,
            time_spent_ms: timeSpent,
            time_spent_readable: `${Math.round(timeSpent / 1000)}s`,
          },
        });
      }
    };
  }, [user?.id, featureName]);
}

// Usage in components
function AnalyticsDashboard() {
  useFeatureTracking("analytics_dashboard");

  return <div>{/* Your analytics dashboard */}</div>;
}

Track User Errors

// hooks/useErrorTracking.js
import { useEffect } from "react";
import { UserBoost } from "@userboost/sdk";
import { useUser } from "./useUser";

export function useErrorTracking() {
  const { user } = useUser();

  useEffect(() => {
    const handleError = (error, errorInfo) => {
      if (user?.id) {
        UserBoost.event("javascript_error", {
          user: { id: user.id },
          properties: {
            error_message: error.message,
            error_stack: error.stack,
            component_stack: errorInfo.componentStack,
            page: window.location.pathname,
          },
        });
      }
    };

    // Global error handler
    window.addEventListener("error", (event) => {
      handleError(event.error, { componentStack: "global" });
    });

    return () => {
      window.removeEventListener("error", handleError);
    };
  }, [user?.id]);
}

// Use in your main App component
function App() {
  useErrorTracking();

  return <ErrorBoundary>{/* Your app */}</ErrorBoundary>;
}

Environment Configuration

Development vs Production

// config/userboost.js
const getUserBoostConfig = () => {
  const isDevelopment = process.env.NODE_ENV === "development";

  return {
    apiKey: isDevelopment
      ? process.env.REACT_APP_USERBOOST_TEST_KEY
      : process.env.REACT_APP_USERBOOST_LIVE_KEY,
    debug: isDevelopment,
    flushInterval: isDevelopment ? 1000 : 10000, // Faster in dev
    endpoint: isDevelopment
      ? "http://localhost:8080/v1"
      : "https://api.userboo.st/v1",
  };
};

// App.js
import { getUserBoostConfig } from "./config/userboost";

function App() {
  useEffect(() => {
    UserBoost.init(getUserBoostConfig());
  }, []);
}

TypeScript Support

Typed Events

// types/userboost.ts
export interface UserEventData {
  id: string;
  email?: string;
  name?: string;
  plan?: "free" | "pro" | "enterprise";
  [key: string]: any;
}

export interface SignupEventData extends UserEventData {
  source: "homepage" | "pricing" | "blog" | "referral";
  utm_campaign?: string;
  trial_days?: number;
}

export interface FeatureEventData extends UserEventData {
  feature: string;
  feature_category: "analytics" | "collaboration" | "automation";
  is_first_use?: boolean;
}
// components/SignupForm.tsx
import { UserBoost } from "@userboost/sdk";
import { SignupEventData } from "../types/userboost";

interface SignupFormProps {
  source: SignupEventData["source"];
}

function SignupForm({ source }: SignupFormProps) {
  const handleSignup = async (userData: any) => {
    // Type-safe event tracking
    const eventData: SignupEventData = {
      id: userData.id,
      email: userData.email,
      name: userData.name,
      source,
      plan: "free",
    };

    UserBoost.event("user_signed_up", {
      user: {
        id: eventData.id,
        email: eventData.email,
        name: eventData.name,
      },
      properties: {
        source: eventData.source,
        plan: eventData.plan,
      },
    });
  };

  return <form onSubmit={handleSignup}>{/* Form fields */}</form>;
}

Testing Your Integration

Test Component

// components/TestUserBoost.jsx
import { useState } from "react";
import { UserBoost } from "@userboost/sdk";

function TestUserBoost() {
  const [events, setEvents] = useState([]);

  const sendTestEvent = () => {
    const testEvent = {
      name: "test_event_" + Date.now(),
      data: {
        id: "test_user_123",
        test: true,
        timestamp: new Date().toISOString(),
      },
    };

    UserBoost.event(testEvent.name, {
      user: { id: testEvent.data.id },
      properties: {
        test: testEvent.data.test,
        timestamp: testEvent.data.timestamp,
      },
    });
    setEvents([...events, testEvent]);
  };

  const enableDebug = () => {
    UserBoost.debug(true);
    console.log("UserBoost debug mode enabled");
  };

  if (process.env.NODE_ENV !== "development") {
    return null; // Only show in development
  }

  return (
    <div
      style={{
        position: "fixed",
        bottom: 20,
        right: 20,
        padding: 10,
        background: "#f0f0f0",
      }}
    >
      <h4>UserBoost Test Panel</h4>
      <button onClick={enableDebug}>Enable Debug</button>
      <button onClick={sendTestEvent}>Send Test Event</button>
      <div>
        <strong>Events Sent: {events.length}</strong>
        {events.map((event, i) => (
          <div key={i}>{event.name}</div>
        ))}
      </div>
    </div>
  );
}

export default TestUserBoost;
Add to your main App component in development:
function App() {
  return (
    <div>
      {/* Your app content */}
      {process.env.NODE_ENV === "development" && <TestUserBoost />}
    </div>
  );
}

Best Practices

1. Initialize Once

Always initialize UserBoost in your root App component, not in individual components.

2. Track User Journey

Focus on tracking meaningful user actions that indicate progress through your product.

3. Use Custom Hooks

Create reusable hooks like useUserBoost for consistent tracking patterns.

4. Handle Edge Cases

Always check if user is available before tracking events.

5. Environment Configuration

Use different API keys and settings for development vs production.

6. Debug Mode

Enable debug mode in development to verify events are being sent correctly.
Ready to track your React app? Install the SDK and start with the basic setup above. Check your UserBoost dashboard to see events coming in!
I