Skip to main content
The Staminads Web SDK captures session data, tracks engagement, and sends events to your workspace. It’s lightweight (~18KB gzipped), privacy-focused, and works across all modern browsers.

Installation

Add the configuration and script to your HTML:
<script>
window.StaminadsConfig = {
  workspace_id: 'ws_your_workspace_id',
  endpoint: 'https://your-staminads-server.com'
};
</script>
<script async src="https://your-staminads-server.com/sdk/staminads.min.js"></script>
Place the config script in the <head> and the SDK script before the closing </body> tag for optimal performance.

Configuration

Set window.StaminadsConfig before loading the SDK:
window.StaminadsConfig = {
  // Required
  workspace_id: 'ws_your_workspace_id',
  endpoint: 'https://your-staminads-server.com',

  // Optional
  debug: false,                    // Enable console logging
  sessionTimeout: 30 * 60 * 1000,  // 30 minutes (default)

  // Features
  trackSPA: true,                  // Auto-track SPA navigation
  trackScroll: true,               // Track scroll depth
};

Configuration Options

OptionTypeDefaultDescription
workspace_idstringrequiredYour workspace identifier
endpointstringrequiredAPI endpoint URL
debugbooleanfalseEnable debug logging
sessionTimeoutnumber1800000Session timeout in ms (30 min)
trackSPAbooleantrueAuto-track single page app navigation
trackScrollbooleantrueTrack scroll depth milestones
crossDomainsstring[][]Domains to share sessions with
crossDomainExpirynumber120Cross-domain link expiry in seconds
crossDomainStripParamsbooleantrueRemove _stm param from URL after reading

Cross-Domain Tracking

By default, sessions are isolated per domain. When a visitor navigates from blog.example.com to shop.example.com, the SDK would create a new session on the shop domain — losing the connection to the original visit. Cross-domain tracking solves this by sharing session identity across domains, so you get:
  • Accurate session counts — One visitor journey = one session, not multiple
  • Complete user paths — See the full journey from blog article to checkout
  • Correct attribution — UTM parameters and referrer data stay with the session
window.StaminadsConfig = {
  workspace_id: 'ws_your_workspace_id',
  endpoint: 'https://your-staminads-server.com',

  // List all domains that should share sessions
  crossDomains: ['shop.example.com', 'blog.example.com'],
  crossDomainExpiry: 120,        // Link valid for 2 minutes (default)
  crossDomainStripParams: true   // Remove _stm param after reading (default)
};
All domains must use the same workspace_id and have the SDK installed with the same crossDomains configuration.

How It Works

  1. When a user clicks a link to a configured domain, the SDK appends a _stm parameter with encrypted session data
  2. On the target domain, the SDK reads the parameter and continues the same session
  3. The parameter is stripped from the URL automatically (if crossDomainStripParams: true)

Manual URL Decoration

For programmatic navigation, use decorateUrl():
// Decorate a URL with session data
const decoratedUrl = Staminads.decorateUrl('https://shop.example.com/checkout');
// Returns: https://shop.example.com/checkout?_stm=eyJzIjoi...

// Use with programmatic navigation
window.location.href = decoratedUrl;
Cross-domain linking only works for domains in the crossDomains array. Links to other domains are not decorated.

API Reference

Session Information

// Get current session ID
const sessionId = await Staminads.getSessionId();

// Get persistent visitor ID
const visitorId = await Staminads.getVisitorId();

// Get authenticated user ID (if set)
const userId = await Staminads.getUserId();

// Get active engagement time (milliseconds)
const focusDuration = await Staminads.getFocusDuration();

// Get total time since session start (milliseconds)
const totalDuration = await Staminads.getTotalDuration();

// Get current config
const config = Staminads.getConfig();

Page Views

Page views are tracked automatically, but you can trigger them manually for SPAs:
// Track current page
await Staminads.trackPageView();

// Track specific URL
await Staminads.trackPageView('/custom/path');

Goals

Track conversions and goals with optional value:
// Simple goal
await Staminads.trackGoal({
  action: 'purchase'
});

// Goal with value
await Staminads.trackGoal({
  action: 'purchase',
  id: 'order-456',
  value: 99.99,
  currency: 'USD',
  properties: {
    plan: 'premium'
  }
});
FieldTypeRequiredDescription
actionstringYesGoal name/action
idstringNoUnique goal identifier
valuenumberNoMonetary value
currencystringNoCurrency code (USD, EUR, etc.)
propertiesobjectNoCustom key-value pairs

Custom Dimensions

Set custom dimensions (1-10) for advanced segmentation. There are two ways to set dimensions:

Via URL Parameters (Automatic)

Custom dimensions can be set via URL parameters stm_1 through stm_10. They are automatically captured when the SDK initializes:
https://example.com/page?stm_1=campaign_a&stm_2=variant_b&stm_3=source_x
This is useful for:
  • Campaign tracking links
  • A/B test variant assignment
  • Affiliate tracking
  • Any scenario where you want to pass dimension values via URL
Priority rule: Existing dimension values take priority over URL parameters. If a dimension is already set (e.g., from a previous page in the session), the URL parameter will NOT overwrite it.

Via JavaScript (Programmatic)

// Set single dimension
await Staminads.setDimension(1, 'premium');
await Staminads.setDimension(2, 'returning');

// Set multiple dimensions
await Staminads.setDimensions({
  1: 'premium',
  2: 'returning',
  3: 'mobile-app'
});

// Get dimension value
const value = await Staminads.getDimension(1);

// Clear all dimensions
await Staminads.clearDimensions();
Custom dimensions are sent as stm_1 through stm_10 in events. Label them in Workspace Settings > Custom Dimensions for readable reports.

User Identification

Associate sessions with authenticated users for cross-device tracking and user-level analytics:
// Set user ID after login
await Staminads.setUserId('user_12345');

// Get current user ID
const userId = await Staminads.getUserId();

// Clear user ID on logout
await Staminads.setUserId(null);
BehaviorDescription
PersistenceUser ID persists across page reloads and sessions
Max length256 characters
ResetCalling reset() clears the user ID
Consent required: Linking analytics data to user identifiers requires explicit user consent under GDPR, ePrivacy Directive, and similar privacy regulations. Only call setUserId() after obtaining valid consent for analytics tracking. Ensure your privacy policy discloses this data collection.
Set the user ID immediately after login (and consent) to ensure all subsequent events are associated with the user.

Control Methods

// Pause tracking (e.g., for cookie consent)
await Staminads.pause();

// Resume tracking
await Staminads.resume();

// Reset session (start fresh, clears user ID)
await Staminads.reset();

Debugging

// Get debug information
const debug = Staminads.debug();

console.log(debug);
// {
//   session: { id: '...', visitor_id: '...', ... },
//   config: { workspace_id: '...', ... },
//   focusState: 'FOCUSED',
//   isTracking: true,
//   queueLength: 0
// }

Automatic Tracking

The SDK automatically tracks the following without any code:
EventTriggerData Captured
screen_viewPage load, SPA navigationPath, referrer, UTM params, previous page
pingHeartbeat (10-30s intervals)Duration, scroll depth
scroll25%, 50%, 75%, 100% milestonesMax scroll percentage

UTM Parameters

UTM parameters are automatically captured from URLs:
ParameterDescription
utm_sourceTraffic source (google, facebook)
utm_mediumMarketing medium (cpc, email)
utm_campaignCampaign name
utm_termPaid search keywords
utm_contentAd variation

Ad Click IDs

The SDK automatically detects and captures ad network click IDs:
ParameterNetwork
gclidGoogle Ads
gbraid, wbraidGoogle Ads (iOS)
fbclidMeta (Facebook, Instagram)
msclkidMicrosoft Ads
ttclidTikTok Ads
li_fat_idLinkedIn Ads
twclidTwitter/X Ads
dclidGoogle Display & Video 360

Focus State Tracking

The SDK tracks engagement using a focus state machine:
StateDescription
FOCUSEDTab is visible and active
BLURREDTab is visible but not focused
HIDDENTab is hidden or minimized
Only FOCUSED time counts toward engagement duration, giving you accurate TimeScore calculations.

Offline Support

Events are queued when offline and sent when connectivity returns:
  • Queue holds up to 50 events
  • Events expire after 24 hours
  • Uses Beacon API with Fetch fallback
  • Handles Safari Private Mode gracefully

Privacy & Compliance

  • No cookies — Uses localStorage with memory fallback
  • No PII — Does not collect personal identifiable information
  • Bot filtering — Automatically excludes crawlers and bots