API Reference#

Complete reference for all @pulsora/core methods, properties, and types.

Class: Pulsora#

The main tracking class for browser-based analytics.

class Pulsora {
  constructor();
  init(config: PulsoraConfig): void;
  pageview(options?: PageviewOptions): Promise<void>;
  event(eventName: string, eventData?: Record<string, any>): Promise<void>;
  identify(customerId: string): Promise<void>;
  reset(): void;
  getVisitorFingerprint(): Promise<string | null>;
  getSessionId(): string;
  isIdentified(): boolean;
  isInitialized(): boolean;
  use(extension: PulsoraExtension): void;
}

Methods#

constructor()#

Creates a new Pulsora instance.

constructor(): Pulsora

Example:

const pulsora = new Pulsora();

Returns: A new Pulsora instance

Notes:

  • Multiple instances can be created for different tracking contexts
  • Each instance maintains its own configuration and state

init()#

Initializes the tracker with configuration.

init(config: PulsoraConfig): void

Parameters:

Example:

pulsora.init({
  apiToken: 'pub_abc123',
  debug: true,
  autoPageviews: false,
});

Throws:

  • Error if already initialized
  • Error if apiToken is missing or invalid

Notes:

  • Must be called before any tracking methods
  • Can only be called once per instance

pageview()#

Tracks a pageview event.

pageview(options?: PageviewOptions): Promise<void>

Parameters:

Examples:

// Track current page
await pulsora.pageview();

// Track with custom data
await pulsora.pageview({
  url: '/custom-path',
  title: 'Custom Title',
  referrer: 'https://google.com',
});

// Track virtual pageview
await pulsora.pageview({
  url: '/virtual/modal/settings',
  title: 'Settings Modal',
});

Returns: Promise that resolves when tracking is complete

Notes:

  • If no options provided, uses current page data
  • Automatically includes visitor fingerprint and session ID
  • Respects autoPageviews configuration

event()#

Tracks a custom event.

event(eventName: string, eventData?: Record<string, any>): Promise<void>

Parameters:

  • eventName - Name of the event (required)
  • eventData (optional) - Additional event properties

Examples:

// Simple event
await pulsora.event('button_click');

// Event with properties
await pulsora.event('purchase', {
  product_id: 'SKU123',
  price: 99.99,
  currency: 'USD',
});

// Nested properties
await pulsora.event('form_submit', {
  form_id: 'contact',
  fields: {
    name: true,
    email: true,
    phone: false,
  },
  duration: 45.2,
});

Returns: Promise that resolves when tracking is complete

Best Practices:

  • Use snake_case for event names
  • Keep event names consistent
  • Avoid PII in event data
  • Use meaningful property names

getVisitorFingerprint()#

Gets the visitor's browser fingerprint.

getVisitorFingerprint(): Promise<string | null>

Example:

const fingerprint = await pulsora.getVisitorFingerprint();
console.log(fingerprint); // "fp_1234567890abcdef"

// Use for server-side attribution
await fetch('/api/checkout', {
  method: 'POST',
  body: JSON.stringify({
    visitor_fingerprint: fingerprint,
    product_id: 'pro-plan',
  }),
});

Returns: Promise resolving to fingerprint string or null if not available

Notes:

  • Fingerprint is stable across sessions
  • Generated using browser characteristics
  • No PII included
  • Format: fp_[hash]

getSessionId()#

Gets the current session ID.

getSessionId(): string

Example:

const sessionId = pulsora.getSessionId();
console.log(sessionId); // "session_1234567890abcdef"

// Include in API calls
const response = await api.createOrder({
  session_id: sessionId,
  items: cart.items,
});

Returns: Current session ID string

Notes:

  • Session ID changes after 30 minutes of inactivity
  • Format: session_[timestamp]_[random]

isInitialized()#

Checks if Pulsora has been initialized.

isInitialized(): boolean

Example:

if (!pulsora.isInitialized()) {
  pulsora.init({ apiToken: 'your-token' });
}

// Safe to track
pulsora.event('page_ready');

Returns: true if initialized, false otherwise


use()#

Registers an extension or plugin.

use(extension: PulsoraExtension): void

Parameters:

  • extension - Extension object implementing PulsoraExtension interface

Example:

// Custom extension
const myExtension = {
  name: 'my-extension',
  init(pulsora) {
    // Add custom functionality
    pulsora.customMethod = () => {
      console.log('Custom method called');
    };
  },
};

pulsora.use(myExtension);

Notes:

  • Extensions must be registered before init()
  • Extensions receive the Pulsora instance
  • Used for adding custom functionality

Types#

PulsoraConfig#

Configuration options for initialization.

interface PulsoraConfig {
  apiToken: string; // Required: Your public API token
  endpoint?: string; // Optional: Custom API endpoint
  autoPageviews?: boolean; // Optional: Auto-track pageviews (default: true)
  debug?: boolean; // Optional: Enable debug logging (default: false)
  maxRetries?: number; // Optional: Max retry attempts (default: 10)
  retryBackoff?: number; // Optional: Initial retry delay in ms (default: 1000)
}

Example:

const config: PulsoraConfig = {
  apiToken: 'pub_abc123',
  endpoint: 'https://analytics.mydomain.com/ingest',
  autoPageviews: false,
  debug: process.env.NODE_ENV === 'development',
  maxRetries: 5,
  retryBackoff: 2000,
};

PageviewOptions#

Options for pageview tracking.

interface PageviewOptions {
  url?: string; // Page URL (default: current URL)
  title?: string; // Page title (default: document.title)
  referrer?: string; // Referrer URL (default: document.referrer)
}

Example:

const options: PageviewOptions = {
  url: '/virtual/modal/signup',
  title: 'Signup Modal',
  referrer: '/pricing',
};

EventData#

Type for event properties.

type EventData = Record<string, any>;

Valid property types:

  • string
  • number
  • boolean
  • null
  • undefined
  • Arrays of the above
  • Nested objects

Example:

const eventData: EventData = {
  category: 'video',
  action: 'play',
  label: 'homepage-hero',
  value: 1,
  metadata: {
    duration: 120,
    quality: '1080p',
    autoplay: false,
  },
};

PulsoraExtension#

Interface for creating extensions.

interface PulsoraExtension {
  name: string;
  init(pulsora: Pulsora): void;
}

Example:

const errorTrackingExtension: PulsoraExtension = {
  name: 'error-tracking',
  init(pulsora) {
    window.addEventListener('error', (event) => {
      pulsora.event('javascript_error', {
        message: event.message,
        source: event.filename,
        line: event.lineno,
      });
    });
  },
};

Error Handling#

Common Errors#

InitializationError

// Error: Pulsora already initialized
pulsora.init(config);
pulsora.init(config); // Throws

// Solution: Check if initialized
if (!pulsora.isInitialized()) {
  pulsora.init(config);
}

InvalidTokenError

// Error: Invalid API token format
pulsora.init({ apiToken: 'invalid' });

// Solution: Use valid public token
pulsora.init({ apiToken: 'pub_abc123' });

NetworkError

// Automatic retry with exponential backoff
// After max retries, promise rejects
try {
  await pulsora.event('action');
} catch (error) {
  console.error('Tracking failed:', error);
}

Error Recovery#

// Wrap tracking calls for safety
async function safeTrack(eventName, data) {
  try {
    await pulsora.event(eventName, data);
  } catch (error) {
    // Log error but don't break app
    console.warn('Analytics error:', error);

    // Optional: Send to error tracking service
    errorService.log(error);
  }
}

// Global error boundary
window.pulsora = new Proxy(pulsora, {
  get(target, prop) {
    const original = target[prop];

    if (typeof original === 'function') {
      return (...args) => {
        try {
          return original.apply(target, args);
        } catch (error) {
          console.error('Pulsora error:', error);
          return Promise.resolve();
        }
      };
    }

    return original;
  },
});

CDN Global API#

When using the CDN version, a global window.pulsora object is available.

Global Methods#

window.pulsora.pageview(options);
window.pulsora.event(name, data);
window.pulsora.identify(customerId);
window.pulsora.reset();

Async Queue Pattern#

// Safe to call before script loads
window.pulsora = window.pulsora || {
  event: function () {
    (window.pulsora.q = window.pulsora.q || []).push(arguments);
  },
};

// Events are queued and sent when script loads
window.pulsora.event('early_event');

TypeScript Usage#

Full TypeScript Example#

import {
  Pulsora,
  PulsoraConfig,
  PageviewOptions,
  EventData,
} from '@pulsora/core';

// Initialize with typed config
const config: PulsoraConfig = {
  apiToken: process.env.NEXT_PUBLIC_PULSORA_TOKEN!,
  debug: process.env.NODE_ENV === 'development',
};

const pulsora = new Pulsora();
pulsora.init(config);

// Typed pageview
const pageviewOptions: PageviewOptions = {
  url: '/dashboard',
  title: 'User Dashboard',
};
await pulsora.pageview(pageviewOptions);

// Typed event
interface PurchaseEvent extends EventData {
  product_id: string;
  price: number;
  currency: string;
  quantity: number;
}

const purchaseData: PurchaseEvent = {
  product_id: 'SKU123',
  price: 99.99,
  currency: 'USD',
  quantity: 1,
};

await pulsora.event('purchase', purchaseData);

Custom Type Guards#

// Type guard for checking initialization
function assertInitialized(pulsora: Pulsora): asserts pulsora is Pulsora {
  if (!pulsora.isInitialized()) {
    throw new Error('Pulsora not initialized');
  }
}

// Usage
assertInitialized(pulsora);
pulsora.event('safe_event'); // TypeScript knows it's safe

Performance Considerations#

Async Operations#

All tracking methods are asynchronous and non-blocking:

// Fire and forget pattern
pulsora.event('quick_action');

// Wait for completion if needed
await pulsora.event('critical_action');

// Batch operations
await Promise.all([
  pulsora.event('step_1'),
  pulsora.event('step_2'),
  pulsora.event('step_3'),
]);

Memory Usage#

  • Fingerprint cached after first generation
  • No localStorage used by default
  • Session data in memory only
  • Minimal DOM interaction

Network Optimization#

  • Uses sendBeacon API when available
  • Automatic retry with backoff
  • Request batching for multiple events
  • Gzip compression supported

Browser Compatibility#

Supported Browsers#

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • iOS Safari 14+
  • Chrome Android 90+

Polyfills#

No polyfills required for modern browsers. For older browser support:

<!-- Optional: Promise polyfill for IE11 -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>

Next Steps#