Rybbit
SDKs

JavaScript (Web)

Official JavaScript SDK for Rybbit Analytics

Installation

npm install @rybbit/js
yarn add @rybbit/js

Peer Dependencies

The SDK has an optional peer dependency for session replay functionality:

npm install rrweb
yarn add rrweb

The rrweb package is only required if you enable session replay in your Rybbit dashboard. The SDK will work without it for all other tracking features.

Initialization

rybbit.init() must be called once before any other tracking methods (pageview, event, etc.) can be used. Attempting to call other methods before init will result in errors or no tracking.

Syntax

async rybbit.init(config: RybbitConfig): Promise<void>;

Example

import rybbit from "@rybbit/js";

await rybbit.init({
  analyticsHost: "https://app.rybbit.io/api",
  siteId: "1",
});

Configuration Options

Required Options

OptionTypeDescription
analyticsHoststringURL of your Rybbit analytics instance (e.g., https://rybbit.yourdomain.com/api).
siteIdstringThe Site ID for your website obtained from your Rybbit instance.

Local Configuration Options

These options are configured in your code and control SDK behavior locally:

OptionTypeDefaultDescription
debounceDurationnumber500Debounce time in milliseconds for tracking pageviews after route changes. Set to 0 to disable debouncing (track immediately).
skipPatternsstring[][]Array of path patterns. Pageviews whose path matches any pattern will not be tracked. See Path Matching.
maskPatternsstring[][]Array of path patterns. For matching pageview paths, the original path will be replaced by the pattern itself in tracked data. See Path Matching.
debugbooleanfalseEnable detailed logging to the browser console.
replayPrivacyConfigobject-Privacy settings for session replay. See Session Replay.

Remote Configuration

These settings are controlled through your Rybbit dashboard and cannot be set in the init config:

Dashboard SettingDescriptionDefault
Track Initial PageviewTrack pageview on initial page loadtrue
Track SPA NavigationTrack pageviews on Single Page Application route changestrue
Track URL ParametersInclude URL query strings in tracked datatrue
Track Outbound LinksAutomatically track clicks on external linkstrue
Track Web VitalsTrack Core Web Vitals performance metricsfalse
Capture ErrorsEnable automatic error trackingfalse
Session ReplayEnable session replay recordingfalse
Track Button ClicksAutomatically track button click interactionsfalse
Track CopyAutomatically track copy eventsfalse
Track Form InteractionsAutomatically track form submissions and input changesfalse

If fetching settings fails or times out, the SDK uses sensible defaults.

Tracking Pageviews

Pageviews are tracked automatically based on your dashboard settings. This includes the initial page load and subsequent route changes in Single Page Applications (SPAs).

Syntax

rybbit.pageview(path?: string);

Parameters

  • path (string, Optional):
    • Replaces the detected URL path (window.location.pathname) and query string (window.location.search) for this specific pageview event.
    • Should start with a / (e.g., /virtual/my-custom-page).
    • If path includes its own query string (e.g., /virtual/step?id=123), that query string will be used for the event. If path has no query string, the querystring property will be empty.
    • skipPatterns and maskPatterns will be applied to path.

When to Use Manually

  • Automatic tracking disabled: If you disabled automatic pageview tracking in your dashboard.
  • Virtual Pageviews: In SPAs where a significant view change occurs without a URL change.
  • Specific Timing: If you need to ensure a pageview is tracked only after certain conditions are met.

Example

// Standard manual pageview (usually not needed if auto-tracking is on)
rybbit.pageview();

// Example: Track a step within a multi-step modal
function openUserDetailsModal(userId, step) {
  // ... logic to open and display the modal step ...
  rybbit.pageview(`/users/${userId}/modal/${step}`);
}
openUserDetailsModal("user-abc", "contact-info");

// Example: Track a virtual pageview with its own query parameters
function showFilteredProductList(category, sortBy) {
   let virtualPathWithQuery = `/products/category/${category}?sort=${sortBy}&view=grid`;
   rybbit.pageview(virtualPathWithQuery);
}
showFilteredProductList("electronics", "price_desc");

Tracking Custom Events

Use custom events to track specific user interactions. Examples include button clicks, form submissions, or adding an item to a cart.

Programmatic Tracking

You can trigger events from your JavaScript code.

Syntax

rybbit.event(name: string, properties?: TrackProperties);

Parameters

  • name (string, Required): The name of the event you want to track.
  • properties (object, Optional): An object containing additional key-value pairs related to the event. Values can be a string, number, boolean, or an array of these types.

Example

// Track a simple button click
document.getElementById("cta-button")?.addEventListener("click", () => {
  rybbit.event("cta_click");
});

// Track adding an item to a shopping cart with properties
function addToCart(item) {
  // ... add item ...
  rybbit.event("add_to_cart", {
    itemId: item.id,
    itemName: item.name,
    price: item.price,
    quantity: 1
  });
}

Declarative Tracking with Data Attributes

The SDK automatically listens for clicks on elements with the data-rybbit-event attribute.

  • data-rybbit-event="<event-name>": This attribute makes the element trackable. The value is used as the event name.
  • data-rybbit-prop-<property-name>="<value>": You can add multiple properties to the event by using this attribute format. The SDK collects all attributes starting with data-rybbit-prop- and includes them as key-value pairs in the event data.

Example

<button data-rybbit-event="cta_click">Click Me</button>

<button
  data-rybbit-event="add_to_cart"
  data-rybbit-prop-item_id="product-123"
  data-rybbit-prop-item_name="Classic T-Shirt"
  data-rybbit-prop-price="29.99"
>
  Add to Cart
</button>

Outbound links (links to external domains) are tracked automatically by default based on your dashboard settings. The SDK attaches a global click listener to capture clicks on <a> tags with external href attributes.

Syntax

rybbit.trackOutbound(url: string, text?: string, target?: string);

Parameters

  • url (string, Required): The destination URL of the outbound link.
  • text (string, Optional): The text content of the link. Defaults to "".
  • target (string, Optional): The target attribute of the link (e.g., _blank). Defaults to _self.

When to Use Manually

  • Automatic tracking disabled: If you disabled outbound link tracking in your dashboard.
  • Non-anchor elements: If you trigger navigation to an external site using JavaScript from an element that isn't an <a> tag.

Example

// Manually track an outbound click triggered by a button
document.getElementById("external-service-button")?.addEventListener("click", () => {
  let url = "https://external-service.com";
  rybbit.trackOutbound(url, "Visit External Service", "_blank");
  // Optionally navigate after tracking
  window.open(url, "_blank");
});

Error Tracking

The SDK can automatically capture JavaScript errors and unhandled promise rejections. This feature must be enabled in your Rybbit dashboard.

Automatic Error Capture

When enabled in your dashboard, the SDK will automatically track:

  • Uncaught exceptions (window.error events)
  • Unhandled promise rejections (window.unhandledrejection events)

Manual Error Capture

You can manually capture errors with additional context:

Syntax

rybbit.error(error: Error | ErrorEvent, context?: TrackProperties);

Parameters

  • error (Error | ErrorEvent, Required): The error object to capture.
  • context (object, Optional): Additional context to include with the error.

Example

try {
  // Some risky operation
  processPayment(orderData);
} catch (error) {
  rybbit.error(error, {
    component: "checkout",
    orderId: "order-123",
    userId: currentUser.id
  });
  // Handle error in your UI
  showErrorMessage("Payment failed");
}

// Capture error from async operation
async function fetchUserData(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`);
    return await response.json();
  } catch (error) {
    rybbit.error(error, {
      endpoint: "/api/users",
      userId: userId
    });
    throw error;
  }
}

Manual error capture only works when error tracking is enabled in your dashboard settings. If it's disabled, calling error() will log a warning.

Session Replay

Session replay records user interactions on your website, allowing you to watch how users navigate and interact with your site. This feature requires the rrweb peer dependency.

Installation

npm install rrweb

Enabling Session Replay

Session replay must be enabled in your Rybbit dashboard under. Once enabled, recording starts automatically when the SDK initializes.

Manual Controls

You can manually start, stop, and check the status of session replay:

// Start recording (only works if enabled in dashboard)
rybbit.startSessionReplay();

// Stop recording
rybbit.stopSessionReplay();

// Check if currently recording
const isRecording = rybbit.isSessionReplayActive();
if (isRecording) {
  console.log("Session is being recorded");
}

Privacy Configuration

Session replay includes privacy-focused defaults and configuration options:

await rybbit.init({
  analyticsHost: "https://app.rybbit.io/api",
  siteId: "1",
  replayPrivacyConfig: {
    maskAllInputs: true, // Mask all input values (default: true)
    maskTextSelectors: [
      ".sensitive-data",  // Mask text in elements with this class
      "#credit-card"      // Mask specific element IDs
    ]
  }
});

Privacy Config Options

OptionTypeDescription
maskAllInputsbooleanMask all input values (default: true)
maskTextSelectorsstring[]CSS selectors for elements whose text should be masked
blockClassstringCSS class name to block elements from recording (default: rr-block)
blockSelectorstringCSS selector to block elements from recording
ignoreClassstringCSS class name to ignore elements from recording (default: rr-ignore)
ignoreSelectorstringCSS selector to ignore elements from recording
maskTextClassstringCSS class name to mask text content (default: rr-mask)
collectFontsbooleanWhether to collect font information (default: true)
slimDOMOptionsobject | booleanOptions to reduce DOM snapshot size

User Identification

You can associate tracking events with a specific user ID and optional traits. The ID is persisted in localStorage and will be attached to all subsequent tracking events for that user.

identify

Assigns a user ID with optional traits.

rybbit.identify(userId: string, traits?: Record<string, unknown>);

Parameters:

  • userId (string, Required): The user ID to associate with tracking events.
  • traits (object, Optional): An object containing user attributes/properties.

Example:

// After a user logs in
rybbit.identify("user-xzy-123");

// With traits
rybbit.identify("user-xzy-123", {
  email: "user@example.com",
  plan: "premium",
  signupDate: "2024-01-15"
});

setTraits

Updates traits for the currently identified user without changing the user ID.

rybbit.setTraits(traits: Record<string, unknown>);

Example:

// Update user traits after they upgrade
rybbit.setTraits({
  plan: "enterprise",
  upgradeDate: "2024-03-01"
});

clearUserId

Clears the stored user ID.

rybbit.clearUserId();

Example:

// When a user logs out
rybbit.clearUserId();

getUserId

Retrieves the currently stored user ID.

rybbit.getUserId(): string | null;

Example:

let currentUserId = rybbit.getUserId();
console.log("Current Rybbit User ID:", currentUserId);

Page Change Callbacks

Register callbacks that execute when the page or route changes. This is useful for integrating with third-party tools or triggering custom logic on navigation.

Syntax

rybbit.onPageChange(callback: (newPath: string, previousPath: string) => void): () => void;

Parameters

  • callback (function, Required): Function to execute on page change. Receives:
    • newPath: The new pathname
    • previousPath: The previous pathname

Returns

Returns an unsubscribe function to remove the callback.

Example

// Register a callback
const unsubscribe = rybbit.onPageChange((newPath, previousPath) => {
  console.log(`Navigated from ${previousPath} to ${newPath}`);

  // Example: Track scroll position reset
  window.scrollTo(0, 0);
});

// Later, to remove the callback
unsubscribe();

// Example: Multiple callbacks can be registered
rybbit.onPageChange((newPath) => {
  // Update page title
  document.title = `${newPath} - My Site`;
});

rybbit.onPageChange((newPath, previousPath) => {
  // Log navigation for debugging
  if (process.env.NODE_ENV === 'development') {
    console.log('Navigation:', { from: previousPath, to: newPath });
  }
});

Callbacks are only triggered when the pathname actually changes. Multiple calls to the same path won't trigger callbacks repeatedly.

Opting Out

Users can opt out of all tracking by setting a flag in localStorage or on the window object. When opted out, all tracking calls are silently ignored.

// Opt out via localStorage (persists across sessions)
localStorage.setItem("disable-rybbit", "true");

// Opt out via window flag (current session only)
window.__RYBBIT_OPTOUT__ = true;

To re-enable tracking, remove the localStorage item and reload the page:

localStorage.removeItem("disable-rybbit");

Cleanup

In Single Page Applications or other dynamic environments, you may need to manually clean up the listeners that the SDK sets up.

Syntax

rybbit.cleanup();

What Gets Cleaned Up

  • SPA route change listeners (popstate, hashchange)
  • Outbound link click listeners
  • Data attribute click listeners
  • Error tracking listeners
  • Session replay recording
  • Page change callbacks
  • Resets initialization state

Example

// In React
useEffect(() => {
  rybbit.init({
    analyticsHost: "https://app.rybbit.io/api",
    siteId: "1",
  });

  return () => {
    rybbit.cleanup();
  };
}, []);

Path Matching

These options allow you to control which page paths are tracked and how they appear in your analytics data using wildcard patterns.

Wildcards

  • *: Matches any sequence of characters except the forward slash (/). Useful for matching single path segments.
  • **: Matches any sequence of characters including the forward slash (/). Useful for matching multiple path segments.

Regex Patterns

For more advanced matching, you can use raw regular expressions by prefixing the pattern with re::

skipPatterns: [
  "re:^/users/\\d+/profile$",  // Match numeric user IDs only
  "re:^/api/v[0-9]+/"          // Match any API version prefix
]

skipPatterns

If a page's path matches any pattern in skipPatterns, the pageview for that path will not be sent.

Examples:

  • "/admin/*": Skips /admin/login, /admin/users, but not /admin/settings/profile.
  • "/admin/**": Skips /admin/login, /admin/users, and /admin/settings/profile.
  • "/users/*/profile": Skips /users/123/profile, /users/abc/profile, but not /users/123/settings.
// Example skipPatterns in init
await rybbit.init({
  // ... other options
  skipPatterns: [
    "/admin/**",        // Skip all admin sections
    "/debug",           // Skip exact /debug path
    "/users/*/settings" // Skip settings page for any user
  ]
});

maskPatterns

If a page's path matches a pattern in maskPatterns, the pageview will be sent, but the pathname will be replaced by the pattern string itself. This is useful for grouping similar pages or hiding sensitive IDs.

If a path matches both a skipPatterns and a maskPatterns pattern, skipping takes priority.

Examples:

  • Pattern: "/users/*/profile"
    • /users/123/profile is tracked as pathname: "/users/*/profile".
  • Pattern: "/products/**"
    • /products/electronics/tv-123 is tracked as pathname: "/products/**".
// Example maskPatterns in init
await rybbit.init({
  // ... other options
  maskPatterns: [
    "/users/*/profile",  // Group all user profile views
    "/orders/*"          // Mask specific order IDs
  ]
});