Skip to main content

Overview

This guide covers practical patterns for agentic apps, copilots, and modern SaaS: authentication, core product events, onboarding, and framework hooks.

Implementation workflow

1

Plan your events

Define activation, success, and failure events before coding
2

Install SDK

Add Trodo via CDN, npm, or a tag manager
3

Configure auto-events

Enable the bundle, then disable noisy categories
4

Add custom events

Instrument workflows, agents, and conversions
5

Identify users

Call identify() at login or signup
6

Set people properties

Plan, role, workspace, feature flags
7

Verify and iterate

Use Live Events and sample profiles

Common patterns

Authentication flow

Trodo.track('signup_started', {
  signup_method: 'email',
  referral_source: getReferralSource()
});

Trodo.track('signup_completed', {
  signup_method: 'email',
  time_to_complete_seconds: 45
});

Trodo.identify(user.id);

Trodo.people.set({
  email: user.email,
  name: user.name,
  signup_date: new Date().toISOString(),
  signup_method: 'email'
});

Trodo.people.set_once({
  first_seen: new Date().toISOString(),
  original_referrer: document.referrer
});

Agent run lifecycle

Trodo.track('agent_run_started', {
  workflow_id: 'weekly_digest',
  surface: 'in_app',
  model: 'gpt-4o'
});

Trodo.track('tool_call_completed', {
  workflow_id: 'weekly_digest',
  tool_name: 'fetch_crm',
  latency_ms: 820
});

Trodo.track('agent_run_completed', {
  workflow_id: 'weekly_digest',
  duration_seconds: 36,
  outcome: 'success',
  output_chars: 2400
});

Trodo.track('agent_run_failed', {
  workflow_id: 'weekly_digest',
  error_class: 'rate_limited',
  retry_count: 2
});

Onboarding flow

const STEPS = [
  'welcome',
  'connect_data',
  'first_prompt',
  'invite_team',
  'done'
];

function trackOnboardingStep(step, extra = {}) {
  const i = STEPS.indexOf(step);
  Trodo.track('onboarding_step_completed', {
    step_name: step,
    step_number: i + 1,
    total_steps: STEPS.length,
    ...extra
  });
  Trodo.people.set({
    onboarding_step: step,
    onboarding_progress_pct: Math.round(((i + 1) / STEPS.length) * 100)
  });
}

function completeOnboarding() {
  Trodo.track('onboarding_completed', {
    total_time_seconds: timeSinceStart
  });
  Trodo.people.set({
    onboarding_completed: true,
    onboarding_completed_at: new Date().toISOString()
  });
}

Error tracking

function trackProductError(error, context) {
  Trodo.track('client_error', {
    error_type: error.name,
    error_message: error.message,
    context,
    page: window.location.pathname
  });
}

Framework-specific patterns

React (session + identity)

import { useEffect } from 'react';
import { useAuth } from './auth';

export function TrodoIdentity() {
  const { user, isReady } = useAuth();

  useEffect(() => {
    if (!isReady || !user) return;
    Trodo.identify(user.id);
    Trodo.people.set({
      email: user.email,
      plan: user.plan,
      workspace_id: user.workspaceId
    });
  }, [isReady, user]);

  return null;
}

Next.js App Router

'use client';

import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';

export function AnalyticsProvider({ children }) {
  const pathname = usePathname();
  const searchParams = useSearchParams();

  useEffect(() => {
    Trodo.track('spa_navigation', {
      page_path: pathname,
      query_string: searchParams.toString()
    });
  }, [pathname, searchParams]);

  return children;
}

Vue 3 Composition API

import { watch } from 'vue';
import { useRoute } from 'vue-router';

export function useTracking() {
  const route = useRoute();

  watch(
    () => route.fullPath,
    (path) => {
      Trodo.track('spa_navigation', { page_path: path });
    }
  );

  return {
    track: (name, props) => Trodo.track(name, props)
  };
}

Groups (companies, workspaces)

Trodo.identify(user.id);

await Trodo.set_group('company', user.companyId);

const company = Trodo.get_group('company', user.companyId);
await company.set({
  name: user.companyName,
  plan: user.companyPlan
});

Trodo.track('report_exported', { format: 'csv' });
Use add_group / remove_group when a user can belong to multiple IDs under one key.

Testing your implementation

Debug mode

script.setAttribute('debug', 'true');

// npm
await Trodo.init({ siteId: 'YOUR_SITE_ID', debug: true });

Verification checklist

1

Live events

Dashboard → Live Events while you use the product
2

Profiles

Confirm identify() updates the right user
3

Custom events

Activation and completion events fire once per logical action
4

PII

No secrets in event properties; forms stay metadata-only for auto-events

Common issues

  • Site ID and domain allowlist
  • Ad blockers and privacy extensions
  • Console errors or blocked network calls
  • Call identify() after the SDK is ready
  • Use a string ID
  • Validate JSON-serializable properties
  • Avoid double script injection
  • Debounce high-frequency handlers if you mirror auto-events manually

Next steps

SDK reference

Full method documentation

Insights

Build reports