All Skills

Core concepts for Fullstory's Asynchronous API methods. Covers the Async suffix pattern, Promise handling, error handling, and when to use async vs fire-and-forget. Note - this pattern is web-only; mobile platforms use different mechanisms.

E
$npx skills add fullstorydev/fs-skills --skill fullstory-async-methods

Fullstory Asynchronous Methods API

Implementation Files: This document covers core concepts. For code examples, see:

Note: The Async suffix pattern is specific to the web/browser SDK. Mobile SDKs use different asynchronous mechanisms (completion handlers, delegates, listeners).

Overview

Fullstory's Browser API provides asynchronous versions of all methods by appending Async to the method name. These async methods return Promise-like objects that resolve when Fullstory has started and the action completes. This is essential for:

  • Initialization Waiting: Wait for Fullstory to fully bootstrap before taking actions
  • Session URL Retrieval: Get the session replay URL for logging, support tickets, etc.
  • Error Handling: Know if an API call succeeded or failed
  • Sequential Operations: Ensure operations complete in order
  • Conditional Logic: Take action based on Fullstory state

Core Concepts

Sync vs Async Methods

Method TypeReturnsUse When
FS('methodName')undefinedFire-and-forget, don't need result
FS('methodNameAsync')Promise-likeNeed result, error handling, or sequencing

Promise-like Object

The object returned from async methods:

  • Can be awaited
  • Supports .then() chaining
  • Important: .catch() may not work in older browsers without Promise polyfill
  • May reject if Fullstory fails to initialize

Available Async Methods

Every FS method has an async variant:

Sync MethodAsync Method
FS('setIdentity', {...})FS('setIdentityAsync', {...})
FS('setProperties', {...})FS('setPropertiesAsync', {...})
FS('trackEvent', {...})FS('trackEventAsync', {...})
FS('getSession')FS('getSessionAsync')
FS('shutdown')FS('shutdownAsync')
FS('restart')FS('restartAsync')
FS('log', {...})FS('logAsync', {...})
FS('observe', {...})FS('observeAsync', {...})

Return Values

MethodResolves With
getSessionAsyncSession URL string
setIdentityAsyncundefined (completion signal)
setPropertiesAsyncundefined
trackEventAsyncundefined
shutdownAsyncundefined
restartAsyncundefined
observeAsyncObserver object with .disconnect()

Rejection Scenarios

The Promise may reject when:

  • Malformed or missing configuration (no _fs_org)
  • User on unsupported browser
  • Error in rec/settings or rec/page calls
  • Organization over quota
  • Fullstory script blocked by ad blocker (may not reliably reject)

When to Use Async vs Sync

Use Async When:

ScenarioWhy
Need session URLMust wait for URL to be available
Error handling neededNeed to know if call failed
Sequential operationsMust ensure order of operations
Conditional logicNeed result to decide next action
Initialization checksNeed to know when FS is ready

Use Sync (Fire-and-Forget) When:

ScenarioWhy
Simple event trackingDon't need confirmation
Non-critical operationsFailure is acceptable
Performance critical pathsDon't want to add latency
Rapid-fire eventsQueueing handles order
User-facing actionsDon't delay user experience

Best Practices

1. Always Use Timeouts

// Prevent hanging if Fullstory is blocked
const result = await Promise.race([
  FS('getSessionAsync'),
  new Promise((_, reject) => 
    setTimeout(() => reject(new Error('Timeout')), 5000)
  )
]);

2. Don't Block Critical Paths

// BAD: App hangs if FS blocked
await FS('getSessionAsync');
renderApp();

// GOOD: App starts immediately
renderApp();
FS('getSessionAsync').then(url => enrichWithSession(url));

3. Use try/catch, Not .catch()

// GOOD: Works reliably
try {
  const url = await FS('getSessionAsync');
} catch (error) {
  // Handle error
}

// RISKY: .catch() may not work in older browsers
FS('getSessionAsync')
  .then(url => {})
  .catch(err => {});  // May fail silently

4. Handle Sequencing Correctly

// GOOD: Sequential operations
await FS('setIdentityAsync', { uid: user.id });
await FS('trackEventAsync', { name: 'Login' });

// BAD: Race condition
FS('setIdentityAsync', { uid: user.id });
FS('trackEventAsync', { name: 'Login' });  // May fire before identity!

Troubleshooting

Promise Never Resolves

CauseSolution
Fullstory blocked by ad blockerUse timeout wrapper
Script failed to loadCheck network tab
Network issuesImplement fallback behavior

Rejection Errors

CauseSolution
Missing _fs_orgCheck Fullstory setup
Unsupported browserVerify browser compatibility
Over quotaCheck Fullstory account

.catch() Not Working

CauseSolution
No native PromiseUse async/await with try/catch
Promise-like limitationsUse .then() with error callback

Key Takeaways for Agent

When helping developers with Async Methods:

  1. Always emphasize:
    • Use timeouts to prevent hanging
    • Handle rejections gracefully
    • Don't block critical paths on FS
    • Use try/catch, not .catch()
  2. Common mistakes to watch for:
    • Blocking app startup on FS
    • Missing error handling
    • Using async when sync would work
    • Race conditions between calls
    • .catch() without polyfill check
  3. Questions to ask developers:
    • Do you need the result?
    • Is this on a critical path?
    • What should happen if FS fails?
    • Is proper sequencing required?
  4. Platform routing:
    • Web (JavaScript/TypeScript) → See SKILL-WEB.md
    • Mobile platforms → See SKILL-MOBILE.md for platform-specific patterns