Skip to content

Imperative Tracking

Imperative tracking uses the FanFestSDK.trackEvent() method to track user actions from JavaScript. This gives you full control over when events fire, what data is attached, and how tracking integrates with your application logic.

This approach is ideal for React, Vue, Angular, and other SPA frameworks where content is dynamic and tracking often depends on application state.

trackEvent() API

Signature

typescript
FanFestSDK.trackEvent(payload: TrackEventPayload): Promise<TrackEventResponse>

TrackEventPayload

typescript
interface TrackEventPayload {
  /** The action name or alias (must match a registered mapping) */
  action: string;

  /** Human-readable description of the action */
  description?: string;

  /** Groups related actions into a logical experience or flow */
  externalExperienceId?: string;

  /** Unique identifier for the object being interacted with */
  externalObjectId?: string;

  /** Location data associated with the event */
  location?: LocationData;

  /** Custom key-value metadata */
  metadata?: Record<string, string | number | boolean>;
}

TrackEventResponse

typescript
interface TrackEventResponse {
  /** Whether the event was tracked successfully */
  success: boolean;

  /** Whether the event triggered a loyalty reward */
  didReward: boolean;

  /** Number of points earned from this event */
  points: number;

  /** Toast notification message (if a reward was triggered) */
  notificationMessage?: string;

  /** Toast notification title (if a reward was triggered) */
  notificationTitle?: string;

  /** Additional message from the server */
  message?: string;
}

LocationData

typescript
interface LocationData {
  external_id: string;
  name?: string;
  full_address?: string;
  continent_code?: string;
  continent_name?: string;
  country_code: string;
  country_name: string;
  region_code?: string;
  region_name?: string;
  city?: string;
  zip?: string;
  latitude: number;
  longitude: number;
  types?: string[];
  raw?: string;
}

Basic Usage

javascript
// Minimal call — action name only
await FanFestSDK.trackEvent({
  action: "READ_ARTICLE",
});

// With object ID and description
await FanFestSDK.trackEvent({
  action: "READ_ARTICLE",
  description: "User read featured article",
  externalObjectId: "article-123",
});

// With metadata
await FanFestSDK.trackEvent({
  action: "purchase",
  externalObjectId: "product-456",
  metadata: {
    campaign: "BlackFriday",
    amount: 99.99,
    currency: "USD",
  },
});

Using the Response

trackEvent() returns a promise that resolves with the server response. You can use this to react to rewards:

javascript
const response = await FanFestSDK.trackEvent({
  action: "COMPLETE_QUIZ",
  externalObjectId: "quiz-weekly-trivia",
});

if (response.didReward) {
  console.log(`Earned ${response.points} points!`);
}

INFO

The SDK automatically displays a toast notification when didReward is true. You do not need to show notifications manually.

Framework Integration

React

jsx
function ArticleCard({ articleId, title }) {
  const handleClick = async () => {
    await FanFestSDK.trackEvent({
      action: "READ_ARTICLE",
      description: `Read article: ${title}`,
      externalObjectId: articleId,
      metadata: {
        title,
        category: "featured",
      },
    });

    window.location.href = `/articles/${articleId}`;
  };

  return (
    <div className="article-card">
      <h3>{title}</h3>
      <button onClick={handleClick}>Read More</button>
    </div>
  );
}

Vue 3

vue
<script setup lang="ts">
const props = defineProps<{
  articleId: string;
  title: string;
}>();

async function handleClick() {
  await FanFestSDK.trackEvent({
    action: "READ_ARTICLE",
    description: `Read article: ${props.title}`,
    externalObjectId: props.articleId,
    metadata: {
      title: props.title,
      category: "featured",
    },
  });
}
</script>

<template>
  <div class="article-card">
    <h3>{{ title }}</h3>
    <button @click="handleClick">Read More</button>
  </div>
</template>

Conditional Tracking

javascript
function handleCTAClick(user, product) {
  const action = user.isLoggedIn
    ? "authenticated_purchase"
    : "anonymous_browse";

  FanFestSDK.trackEvent({
    action,
    externalObjectId: product.id,
    metadata: {
      userType: user.isLoggedIn ? "authenticated" : "anonymous",
      category: product.category,
    },
  });
}

Error Handling

trackEvent() is async and can fail if the network is unavailable or the SDK is not initialized. Always handle errors so tracking failures never block user flows:

javascript
async function trackPurchase(productId) {
  try {
    const response = await FanFestSDK.trackEvent({
      action: "purchase",
      externalObjectId: productId,
    });

    if (response.didReward) {
      // Optional: custom reward handling beyond the auto-toast
    }
  } catch (error) {
    // Log but do not block the user flow
    console.warn("Tracking failed:", error);
  }

  // Continue with the purchase regardless of tracking outcome
  completePurchase(productId);
}

When to Use Imperative Tracking

  • React, Vue, Angular, and other SPA frameworks
  • Dynamic content where tracked values come from application state
  • Conditional tracking based on user authentication or feature flags
  • When you need typed metadata values (numbers, booleans — not just strings)
  • When you need the TrackEventResponse to react to rewards
  • When you need location data attached to events
  • Async workflows where tracking is part of a larger operation

For static content and CMS-managed pages, declarative tracking is simpler and requires no JavaScript beyond loading the SDK.

Next Steps

Released under the MIT License.