Last updated

Media Event Listeners

The FairShare SDK provides a comprehensive event system for tracking user interactions with media widgets. All media event listeners are accessible through FairShareSDK.media.* and allow you to respond to video playback, image views, and CTA (Call-to-Action) interactions.

Quick Start

// Subscribe to media start events
const unsubscribe = FairShareSDK.media.onStart((payload) => {
  console.log('Media started:', payload.mediaId);
});

// Later, unsubscribe when no longer needed
unsubscribe();

Available Events

EventMethodTrigger
LoadonLoad()Media metadata has loaded and is ready to play
StartonStart()Media playback began (first play only)
PauseonPause()Media playback was paused
ResumeonResume()Media playback resumed after being paused
CompleteonComplete()Media playback finished (reached the end)
CTA ClickonCtaActionClick()User clicked a Call-to-Action button

Event Payloads

Media Event Payload

All media events (onLoad, onStart, onPause, onResume, onComplete) receive this payload:

PropertyTypeDescription
mediaIdstringUnique identifier for the media item
mediaTypestringType of media: "video", "image", "pdf", or "website"
timestampstringISO 8601 timestamp of when the event occurred
currentTimenumberCurrent playback position in seconds (0 for images)
durationnumberTotal duration in seconds (0 for images)
playlistIdstring | nullPlaylist ID if media is part of a playlist
mediaUrlstringURL of the media file
titlestringTitle of the media item

Example payload:

{
  "mediaId": "12345",
  "mediaType": "video",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "currentTime": 0,
  "duration": 120.5,
  "playlistId": "playlist-789",
  "mediaUrl": "https://example.com/video.mp4",
  "title": "Product Demo Video"
}

CTA Click Event Payload

The onCtaActionClick event receives this payload:

PropertyTypeDescription
mediaIdstringMedia ID where the CTA was clicked
playlistIdstring | nullPlaylist ID if applicable
timestampstringISO 8601 timestamp
ctaTypestringType of CTA action: "phone", "cart", "link", or "email"
ctaUrlstring | nullURL for link CTAs
ctaButtonTextstring | nullText displayed on the CTA button
productIdstring | nullProduct/variant ID for cart CTAs

Example payload:

{
  "mediaId": "12345",
  "playlistId": "playlist-789",
  "timestamp": "2024-01-15T10:32:15.000Z",
  "ctaType": "cart",
  "ctaUrl": null,
  "ctaButtonText": "Add to Cart",
  "productId": "variant-456"
}

Subscribing to Events

Global Subscription (All Media)

Subscribe to events from all media widgets on the page:

// Listen to all media load events
FairShareSDK.media.onLoad((payload) => {
  console.log('Media loaded:', payload.mediaId);
});

// Listen to all media start events
FairShareSDK.media.onStart((payload) => {
  console.log('Playback started:', payload.mediaId);
  console.log('Duration:', payload.duration, 'seconds');
});

// Listen to all pause events
FairShareSDK.media.onPause((payload) => {
  console.log('Paused at:', payload.currentTime, 'seconds');
});

// Listen to all resume events
FairShareSDK.media.onResume((payload) => {
  console.log('Resumed at:', payload.currentTime, 'seconds');
});

// Listen to all complete events
FairShareSDK.media.onComplete((payload) => {
  console.log('Media completed:', payload.mediaId);
});

// Listen to all CTA clicks
FairShareSDK.media.onCtaActionClick((payload) => {
  console.log('CTA clicked:', payload.ctaType);
  if (payload.ctaType === 'cart') {
    console.log('Product added:', payload.productId);
  }
});

Filtered Subscription (Specific Media or Playlist)

Subscribe to events only from specific media items or playlists:

// Only events for a specific media ID
FairShareSDK.media.onStart((payload) => {
  console.log('Specific media started:', payload);
}, { mediaId: '12345' });

// Only events for media within a specific playlist
FairShareSDK.media.onPause((payload) => {
  console.log('Playlist media paused:', payload);
}, { playlistId: 'playlist-789' });

// Combined filter (specific media AND playlist)
FairShareSDK.media.onComplete((payload) => {
  console.log('Specific media in playlist completed:', payload);
}, { mediaId: '12345', playlistId: 'playlist-789' });

Unsubscribing from Events

Every subscription method returns an unsubscribe function:

// Store the unsubscribe function
const unsubscribe = FairShareSDK.media.onStart((payload) => {
  console.log('Media started:', payload);
});

// Later, call it to stop receiving events
unsubscribe();

Managing Multiple Subscriptions

// Track all subscriptions
const subscriptions = [];

subscriptions.push(
  FairShareSDK.media.onStart((p) => console.log('Start:', p))
);
subscriptions.push(
  FairShareSDK.media.onPause((p) => console.log('Pause:', p))
);
subscriptions.push(
  FairShareSDK.media.onComplete((p) => console.log('Complete:', p))
);

// Unsubscribe from all at once
function unsubscribeAll() {
  subscriptions.forEach(unsub => unsub());
  subscriptions.length = 0;
}

Event Lifecycle

Understanding when each event fires:

[Media Widget Loads]
        |
        v
    ┌───────┐
    │ LOAD  │  <-- Metadata ready, duration known
    └───┬───┘
        |
        v
    ┌───────┐
    │ START │  <-- First play (only fires once per session)
    └───┬───┘
        |
        v
    ┌───────┐     ┌────────┐
    │ PAUSE │ <-> │ RESUME │  <-- Can repeat many times
    └───┬───┘     └────────┘
        |
        v
   ┌──────────┐
   │ COMPLETE │  <-- Video ended, resets START for replay
   └──────────┘

Important Notes

  • START vs RESUME: START only fires on the first play. All subsequent plays after pausing trigger RESUME.
  • Auto-play: If a video auto-plays when the page loads, START fires immediately. Register listeners early to catch it.
  • Replay: After COMPLETE, if the user replays the video, START fires again.
  • Images: For image media types, LOAD fires when displayed. currentTime and duration will be 0.

CTA Types Reference

TypeDescriptionPayload Fields
linkExternal URL linkctaUrl contains the destination URL
cartAdd to cart actionproductId contains the variant ID
emailEmail/contact formctaButtonText contains button label
phonePhone contactctaButtonText contains button label

Complete Example

<script>
  // Wait for SDK to be ready
  document.addEventListener('DOMContentLoaded', () => {
    // Verify SDK is available
    if (typeof FairShareSDK === 'undefined') {
      console.error('FairShareSDK not loaded');
      return;
    }

    // Track all media interactions
    const analytics = {
      mediaViews: [],
      completions: [],
      ctaClicks: []
    };

    // Track when users start watching
    FairShareSDK.media.onStart((payload) => {
      analytics.mediaViews.push({
        mediaId: payload.mediaId,
        title: payload.title,
        startedAt: payload.timestamp
      });

      // Send to your analytics service
      sendToAnalytics('media_start', payload);
    });

    // Track video completions
    FairShareSDK.media.onComplete((payload) => {
      analytics.completions.push({
        mediaId: payload.mediaId,
        completedAt: payload.timestamp
      });

      sendToAnalytics('media_complete', payload);
    });

    // Track CTA engagement
    FairShareSDK.media.onCtaActionClick((payload) => {
      analytics.ctaClicks.push({
        mediaId: payload.mediaId,
        ctaType: payload.ctaType,
        productId: payload.productId,
        clickedAt: payload.timestamp
      });

      sendToAnalytics('cta_click', payload);

      // Special handling for cart additions
      if (payload.ctaType === 'cart' && payload.productId) {
        console.log('Product added to cart:', payload.productId);
      }
    });

    // Track engagement depth (how much was watched before leaving)
    FairShareSDK.media.onPause((payload) => {
      const percentWatched = (payload.currentTime / payload.duration) * 100;
      sendToAnalytics('media_pause', {
        ...payload,
        percentWatched: percentWatched.toFixed(1)
      });
    });

    function sendToAnalytics(eventName, data) {
      // Replace with your analytics implementation
      console.log(`[Analytics] ${eventName}:`, data);
    }
  });
</script>

Window Events (Advanced)

For advanced use cases, you can listen directly to window CustomEvents:

// Event names
const MEDIA_EVENTS = {
  LOAD: 'FLUID_MEDIA_LOAD',
  START: 'FLUID_MEDIA_START',
  PAUSE: 'FLUID_MEDIA_PAUSE',
  RESUME: 'FLUID_MEDIA_RESUME',
  COMPLETE: 'FLUID_MEDIA_COMPLETE',
  CTA_CLICK: 'FLUID_MEDIA_CTA_CLICK'
};

// Direct window listener
window.addEventListener('FLUID_MEDIA_START', (event) => {
  const payload = event.detail;
  console.log('Media started:', payload);
});

Note: Using FairShareSDK.media.* methods is recommended over direct window listeners as they provide automatic cleanup via unsubscribe functions and type-safe payloads.


Troubleshooting

IssueCauseSolution
Events not firingListener registered after auto-playRegister listeners earlier, or test with pause/resume
FairShareSDK undefinedSDK not loaded yetWait for DOMContentLoaded or check script order
Missing eventsFilter too restrictiveRemove filter object to receive all events
Duplicate eventsMultiple listeners registeredStore and call unsubscribe functions