Documentation

Complete Documentation

Everything you need to master Segmently - from installation to advanced experimentation

Quick Start

  1. 1

    Install the Snippet

    Add the Segmently script to your website's <head> section.

  2. 2

    Create Your First Project

    Projects organize your experiments and generate API keys for tracking.

  3. 3

    Design Your Experiment

    Define variants, set targeting rules, and configure goals using our visual editor or code.

  4. 4

    Launch & Analyze

    Start your experiment and watch real-time analytics to determine the winning variant.

Dashboard Features

Sites

Organize experiments by website or application

What is a Site?

A Site represents one website or application. Each site has its own API key, experiments, and analytics. If you have multiple websites, create a separate site for each.

Creating a Site:

  • Click “+ New Site” from the Sites page
  • Enter the site URL (e.g., “https://mysite.com”)
  • Click “Create Site”
  • Site is created with a unique API key instantly

Site Page Sections:

  • Experiments: List of all experiments (active, paused, archived)
  • Quick Actions: Start, Pause, Resume, Archive, Reinstate, View Analytics, Edit
  • API Key & Installation (Accordion): Copy snippet code for website installation
  • Integration Guides (Accordion): Platform-specific instructions

Site Limits by Tier:

  • Free: 1 site
  • Professional: 1 site
  • Business: 3 sites
  • Enterprise: Unlimited sites

Site Deletion:

  • Navigate to Site → Settings
  • Scroll to “Danger Zone”
  • Click “Delete Site” (requires confirmation)
  • ⚠️ Warning: Deletes ALL experiments and analytics data permanently

Experiments Overview

Complete guide to A/B testing experiments

What is an Experiment?

An experiment is an A/B test where you show different versions (variants) of a page to visitors and measure which performs better. Segmently handles assignment, tracking, and statistical analysis automatically.

Experiment Creation Process:

  • Step 1: Details (name, description, hypothesis)
  • Step 2: Variants (Control + variations)
  • Step 3: Targeting (URL rules, device types)
  • Step 4: Goals (conversion metrics)
  • Step 5: Review & Launch

Experiment States:

  • Draft: Being configured, not visible to visitors
  • Live: Running and tracking visitors
  • Paused: Temporarily stopped (data preserved)
  • Archived: Completed/ended (removed from active list)

Quick Actions Menu (3-dot icon):

  • ▶️ Start (Draft → Live)
  • ⏸️ Pause (Live → Paused)
  • ▶️ Resume (Paused → Live)
  • 📦 Archive (Any state → Archived)
  • ♻️ Reinstate (Archived → Draft)
  • 📊 View Analytics (All states)
  • ✏️ Edit (Draft/Paused only)
  • 🗑️ Delete (Permanent removal)

Experiment Limits by Tier:

  • Free: 1 experiment
  • Professional: 1 experiment
  • Business: 2 experiments
  • Enterprise: Unlimited experiments

Live Events

Real-time feed of every visitor interaction across your site

What is the Live Events Feed?

The Live Events page gives you a real-time stream of every visitor interaction across a selected site. The feed polls every three seconds and prepends new events at the top so the most recent activity is always visible. Access it via the "Live" link in the dashboard header.

Filters:

  • Event type pills: All, page_view, conversion, assignment, time_on_page, and any custom events your snippet fires
  • Visitor ID search: Type a partial visitor ID to trace a specific user across multiple events (case-insensitive substring match)
  • Date range: All time, Today, Last 1 hour, Last 24 hours, or Last 7 days

Table Columns:

  • Event: Colored badge showing the event type (page_view, conversion, etc.)
  • Visitor ID: Shortened unique identifier for the visitor so you can trace them across rows
  • Experiment / Variant: The experiment name and variant the visitor is assigned to (blank if no active experiment)
  • Time: Relative timestamp (e.g., "2m ago")

Stats Bar:

  • Total events loaded in the current session
  • Unique visitor count
  • Conversion count from the loaded events

Pause & Resume:

Click the Pause button to freeze the feed. New events are still fetched in the background but are not displayed until you click Resume, so you can inspect a specific moment without items shifting positions.

Availability: Available on Professional, Business, and Enterprise plans.

Experiment Configuration Tabs

Details Tab

Basic experiment information and hypothesis

Fields:

  • Experiment Name: Internal identifier (e.g., "Homepage Hero Test")
  • Description: What you're testing and why
  • Hypothesis: Expected outcome (e.g., "Changing CTA color to green will increase conversions by 15%")
  • Activation Delay: Time before revealing experiment (prevents flicker)

Activation Delay Options:

  • Immediate (0ms): Show changes instantly
  • Fast (100ms): Brief wait for scripts
  • Standard (500ms): Allow dependencies to load
  • Safe (1000ms): Ensure all assets loaded
  • Custom: Enter any millisecond value

Why Activation Delay Matters:

If your site uses JavaScript that modifies the DOM after page load (e.g., React, Vue, Angular), setting an activation delay ensures Segmently's changes are applied AFTER your framework initializes, preventing conflicts or reverts.

Best Practices:

  • Use descriptive names (searchable, clear purpose)
  • Write specific hypotheses (measurable, testable)
  • Start with 100ms delay for most sites
  • Increase to 500ms if using React/Vue/Angular

Variants Tab

Create and configure experiment variations

What are Variants?

Variants are different versions of your page shown to visitors. Every experiment has a Control (original) and one or more Variations (your changes).

Control Variant:

  • Always exists (cannot be deleted)
  • Represents the original page (baseline)
  • Can be customized like any other variant!
  • ⚠️ Control does NOT mean "unchanged site" - it's just another variant

Creating Variations:

  • Click "+ Add Variation"
  • Enter variation name (e.g., "Green Button", "Shorter Form")
  • Set traffic weight (percentage of visitors)
  • Add changes using Visual Editor or Custom Code

Traffic Weights:

  • Must sum to 100% across all variants
  • 50/50 split: Control 50%, Variation A 50%
  • 33/33/34 split: 3 variants equally distributed
  • Custom: 25/75, 10/45/45, etc.

Change Types:

  • Hide Element: Remove from DOM
  • Replace Text: Change wording
  • Custom CSS: Style modifications
  • Custom JavaScript: Advanced DOM manipulation

Visual Editor Integration:

  • Click "Visual Editor" button
  • Website loads in iframe
  • Hover over elements (blue highlight)
  • Click to select element
  • CSS selector auto-generated
  • Apply changes and save

Selected Element Tiles:

  • Each tile prefers the first direct text node of the selected element
  • If none exists, it falls back to the first immediate child element text
  • If still empty, it uses the first descendant element's direct text before final fallback
  • Container-wide concatenated text is avoided for cleaner labels
  • This improves identification for nested structures and non-visible elements

Nested Element Reliability:

  • When parent and child are both selected, parent changes apply first
  • Child element changes apply after parent to prevent unintended overrides
  • Saved element changes reapply when reopening the modal after elements are ready
  • HTML updates prioritize exact selector matches before using safe fallback
  • Selected elements default to visible unless you explicitly choose hidden or removed
  • Selected elements with empty HTML (not edited) are ignored to prevent child wipe
  • Pending selected-element apply cycles are preserved across snippet reinitialization
  • Preview-link mode applies selected elements with the same retry/depth safeguards
  • Clearing custom CSS removes previously applied inline properties for that selector
  • Localhost preview bypasses session cache to always load fresh experiment changes
  • If your page is highly dynamic, keep Activation Delay at 100-500ms for best consistency

On-Site Test Panel:

  • When previewing an experiment, a floating Test Panel appears in the bottom-right corner of your page
  • Shows the active experiment name and the currently selected segment
  • Use the segment dropdown to switch to any other segment without editing the URL manually
  • Click View Original to remove the preview parameter and see the unmodified site
  • Click Dashboard to open the experiment in a new tab
  • Minimize the panel with the ▼ button; its state is remembered across page navigations in the same session
  • The panel is CSS-isolated and cannot conflict with your site's styles

Targeting Tab

Control where and to whom experiments are shown

URL Targeting:

  • Exact: https://example.com/pricing (only this URL)
  • Contains: /product/ (anywhere in URL)
  • Starts With: https://example.com/blog/ (all blog posts)
  • Ends With: /checkout (any checkout page)
  • Regex: ^https://example\.com/product/[0-9]+$ (advanced)

Multiple URL Rules:

  • Add multiple rules (OR logic)
  • Experiment runs if ANY rule matches
  • Example: Target /checkout OR /cart

Device Targeting:

  • All Devices: Desktop, mobile, tablet (default)
  • Desktop Only: Screen width ≥ 1024px
  • Mobile Only: Screen width < 768px
  • Tablet Only: 768px ≤ width < 1024px

Location Targeting:

  • Target visitors by country using ISO 3166-1 alpha-2 codes (e.g. US, GB, DE)
  • Only visitors from selected countries are bucketed into the experiment
  • Leave the list empty to include all countries (default)
  • Visitors whose country cannot be detected are always allowed through

Traffic Percentage:

  • Control what % of visitors see experiment
  • 100%: All matching visitors participate
  • 50%: Only half of visitors see experiment
  • 10%: Run on small sample before full rollout
  • Useful for testing impact before wide deployment

How Targeting Works:

  1. Visitor lands on your website
  2. Snippet checks current URL against rules
  3. If no match, experiment is skipped
  4. If match, check device type
  5. If device matches, check visitor country against geo targeting rules
  6. If country matches (or no geo rules set), check traffic percentage
  7. Assign to variant using deterministic hashing
  8. Apply changes and track events

Audience Tab

Control who triggers your experiments and when

Visitor Type

Restrict the experiment to a specific audience:

  • All Visitors: everyone who lands on a matching page
  • New Visitors: no prior visit cookie present, first session only
  • Returning Visitors: prior visit cookie present, visited before

Behavioral Triggers (Professional+)

Behavioral triggers delay experiment activation until the visitor performs a specific action mid-session. Because changes apply to an already-visible page, anti-flicker CSS is intentionally bypassed for behavioral experiments.

Scroll Depth: fires once the visitor has scrolled past a set percentage of the page.
Time on Page: fires after the visitor has spent N seconds on the page.
Element Click: fires when a matching CSS selector is clicked (e.g. .add-to-cart, #open-chat).
Referral Source Gate: evaluated at page load. If the visitor's source does not match the configured set, no variant is assigned.

Each trigger fires at most once per page visit. Multiple triggers can be combined; the first async trigger to fire activates the experiment.

Full documentation available below. The Behavioral Targeting section covers every trigger in detail: how detection works, configuration options, common use cases, and step-by-step testing instructions for each trigger type.

Goals Tab

Define success metrics and conversion tracking

What are Goals?

Goals define what "success" means for your experiment. Most experiments track conversions (purchases, signups, clicks), but you can also track custom events and multi-page funnels.

Primary Conversion Goal: How It Connects to Analytics

💡 The Primary Conversion Goal is the direct source of the Conversions tile and Conversion Rate shown on your analytics dashboard. When a visitor triggers your goal (clicks a button, submits a form, reaches a thank-you page, or fires a custom JS event), the snippet sends a conversion event to the API, which is exactly what the analytics tile counts. There is no separate system; the goal is the conversion counter.

  • The main metric you're optimizing for
  • Used for winner determination in analytics
  • Without a Primary Goal set, conversions are only recorded if you manually call window.Segmently.track('conversion') in your own code
  • Secondary goals also fire as conversion events (with a different goal_name in metadata) and contribute to the same count

Goal Types:

  • Click Element: Tracks clicks on a CSS selector (e.g. #buy-button)
  • Form Submit: Tracks when a matching form is submitted
  • Page View: Tracks when a visitor reaches a specific URL (e.g. /thank-you)
  • Custom Event: Tracks a named JS event fired via window.Segmently.track()

Page View Goal Setup:

1. Choose "Page View" as goal type
2. Enter conversion URL: /thank-you
3. Snippet fires a conversion event whenever
   a bucketed visitor lands on that URL

Custom Event Goal:

// Fire from your own JavaScript
window.Segmently.track('purchase_complete', {
  revenue: 99.99 // Use the 'revenue' key to pipe to Dashboard Analytics total
});
// The event name must match what you entered
// in the "Event Name" field of the goal config

Best Practices:

  • Set a Primary Goal before launching; without one, the Conversions tile will always show 0
  • Choose ONE clear primary goal per experiment (e.g. purchase, signup, not both)
  • Make sure the goal is binary (yes/no per visitor per session)
  • Test goal firing in the browser console before launching

Multi-Page Funnel Goals (Professional+)

Track sequential page visits as a multi-step conversion funnel

What are Funnel Goals?

Funnel goals let you define an ordered sequence of pages a visitor must visit, in order, to count as a conversion. Unlike a single-page goal, funnels reveal where visitors drop off across a multi-step flow (e.g., landing page → product page → checkout → confirmation).

Requires Professional plan or higher. The section is visible in the experiment wizard for all plans, but funnel evaluation is only active for Professional, Business, and Enterprise accounts.

Adding Funnel Steps:

  1. Open the Metrics tab in the experiment wizard
  2. Scroll to the Multi-Page Funnel Goals section
  3. Click + Add Step for each page in the flow
  4. Fill in the three fields for each step (see below)
  5. Steps are evaluated in order, top to bottom

Step Fields:

  • Step Label: A human-readable name shown in analytics (e.g., "Landing Page", "Add to Cart", "Checkout", "Purchase Confirmed")
  • URL (contains): The URL path pattern that defines this step (see URL matching rules below)
  • Event Name (optional): A custom event name that can also satisfy this step (e.g., add_to_cart). Either the URL match or the event fires; whichever comes first counts.

URL Field: Matching Rules

  • Empty value or / → matches the root domain homepage only (i.e., pathname === "/"). Both are treated identically, so leaving the field blank and entering / produce the same result.
  • Any other value (e.g., /checkout, /product) → matches any URL whose pathname contains that string.
  • Matching is case-sensitive and path-only (the hostname is ignored).

Example: E-commerce Funnel

Step 1: Landing Page
  Label: Landing
  URL: /            ← matches homepage only
  Event: (empty)

Step 2: Product Page
  Label: Product
  URL: /product     ← matches /product, /products/123, etc.
  Event: (empty)

Step 3: Added to Cart
  Label: Add to Cart
  URL: /cart
  Event: add_to_cart  ← fires if JS calls Segmently.track('add_to_cart')

Step 4: Checkout
  Label: Checkout
  URL: /checkout
  Event: (empty)

Step 5: Purchase Confirmed
  Label: Confirmed
  URL: /thank-you
  Event: purchase

Triggering Funnel Events Manually:

For steps where a URL visit isn't enough (e.g., a single-page checkout), use the JS API to fire a step event:

// Fire a named event to satisfy a funnel step
window.Segmently.track('add_to_cart');

// With optional metadata (Use the 'revenue' key to automatically aggregate revenue in Analytics)
window.Segmently.track('conversion', { revenue: 99.99, currency: 'USD' });

How to Test Funnel Goals:

  1. Create an experiment with funnel steps and set status to Draft
  2. Open your site with the preview URL: yoursite.com?segmently_preview=your-slug:your-segment-id
  3. Navigate through each page in order (e.g., visit homepage → /product → /checkout → /thank-you)
  4. On pages that use event-based steps, open the browser console and run: window.Segmently.track('your_event_name');
  5. After completing all steps, check Dashboard → Analytics for your experiment to see funnel completion data
  6. To verify events are being recorded, check the network tab in DevTools for POST requests to /api/v1/events/track

Funnel Analytics (What You'll See):

  • Per-variant completion rate at each step
  • Drop-off percentage between consecutive steps
  • Overall funnel completion rate (step 1 through final step)
  • Comparison across Control and all Variants

Tips & Limitations:

  • Steps must be completed in sequence; visiting step 3 before step 2 does not count
  • A visitor who completes only steps 1 and 2 is counted as a drop-off at step 3
  • The same visitor completing the funnel multiple times is deduplicated (counted once)
  • Leave the URL blank (not /) when you want the step satisfied purely by a custom event
  • For SPA sites where URLs don't change on navigation, rely entirely on event-based steps

Advanced Tab

Custom code, experiment scheduling, and third-party integrations

Experiment Scheduling (Business+):

  • Start Date: Set a future date/time to automatically activate the experiment
  • End Date: Set a date/time after which the experiment automatically pauses
  • Auto-pause at significance: Toggle to have the experiment pause itself once a variant reaches 95% statistical confidence (requires 30+ visitors per variant)
  • Scheduling checks run every 60 seconds server-side; no manual intervention needed
  • Useful for timed promotions, product launches, and campaigns across time zones
  • You can schedule an experiment from the ellipsis menu on the site page: click the three-dot menu next to any draft experiment and choose Schedule

Cross-Domain Tracking:

  • Keeps a visitor in their assigned variant when they navigate from one of your domains to another (e.g. a marketing site to a separate checkout domain)
  • Requires the Segmently snippet to be installed on every domain you want to track across, all using the same site API key
  • Enable it in the Advanced tab, then enter a comma-separated list of the domains you want to bridge (e.g. store.example.com, checkout.example.com)
  • The snippet automatically appends ?_sgmt_vid=<visitor_id> to every outbound link pointing to your listed domains; a MutationObserver handles links added dynamically after page load (SPAs, lazy-loaded content)
  • When the visitor lands on the second domain, that domain's snippet reads _sgmt_vid, adopts the visitor ID (matching the existing assignment record), then strips the parameter from the URL bar so it never appears in the address bar or gets bookmarked
  • Both domains must be on the same Segmently project; the same API key is shared across all of them

Integrations (Business+):

  • Slack Webhook: Enter a Slack Incoming Webhook URL to receive a notification when your experiment reaches statistical significance
  • GA4 Measurement ID: Enter your GA4 Measurement ID (e.g., G-XXXXXXX); the snippet automatically calls gtag('event', 'experiment_impression') when a visitor is bucketed, syncing experiment and variant names into GA4
  • Mixpanel Project Token: Enter your Mixpanel Project Token; the snippet calls mixpanel.track('$experiment_started') automatically (requires Mixpanel SDK already on page)
  • Outbound Webhook URL: Enter any HTTPS endpoint; Segmently will POST a JSON payload for each configured experiment event (experiment.started, experiment.paused, significance.reached)
  • GA4 and Mixpanel forwarding only fires if the respective library (window.gtag / window.mixpanel) is already loaded on the client page

Custom JavaScript:

// Example: Change button text dynamically
document.querySelector('.cta-button')
  .textContent = 'Start Free Trial';

// Example: Add click event listener
document.querySelector('.hero-cta')
  .addEventListener('click', () => {
    window.Segmently.trackConversion();
  });

Custom CSS:

.hero-section {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  padding: 80px 20px;
}

.cta-button {
  background-color: #10b981;
  color: white;
  font-weight: bold;
  border-radius: 8px;
}

Execution Order:

  1. Anti-flicker CSS injected (hides page)
  2. Experiment configuration fetched
  3. Variant assigned to visitor
  4. Integration events forwarded (GA4, Mixpanel)
  5. Visual Editor changes applied
  6. Custom CSS injected
  7. Custom JavaScript executed
  8. Wait for activation delay
  9. Anti-flicker removed (page revealed)

Best Practices:

  • Test code in browser console first
  • Use querySelector carefully (may not exist yet)
  • Add error handling for missing elements
  • Keep code minimal (performance impact)
  • Comment complex logic for future reference
  • Use the built-in Prism syntax highlighting to quickly validate selectors, properties, and JavaScript tokens while editing

⚠️ Warning:

Custom code executes on every page view. Ensure it's efficient and doesn't break functionality. Always test in preview mode before launching!

Integrations Tab (Business+)

Connect experiments to Slack, GA4, Mixpanel, and custom webhooks

The Integrations tab lets you forward experiment data to external analytics and notification tools. All integration settings are saved per-experiment inside the integrations field.

Slack Notifications (Professional+):

There are two levels of Slack integration: org-level (15 event types) and per-experiment override.

  • Org-level (recommended): Configure a single Slack webhook and choose which of the 15 event types to receive; go to Organization → Features & Integrations. Covers experiment lifecycle, project events, member changes, and billing alerts.
  • Per-experiment override: Paste a Slack Incoming Webhook URL here to send notifications for this experiment only. Fires on experiment.started, experiment.paused, experiment.archived, and significance.reached.
  • The significance.reached event fires automatically (exactly once per experiment) when a variant's two-proportion z-test confidence first crosses 95%.
  • Message includes experiment name, winning variant, confidence level, and a direct link to the results page.
  • Create Incoming Webhooks at api.slack.com/apps → your app → Incoming Webhooks.

Google Analytics 4 (Business+):

  • Enter your GA4 Measurement ID (format: G-XXXXXXXXXX)
  • The Segmently snippet auto-fires gtag('event', 'experiment_impression', { experiment_name, variant_name }) when each visitor is bucketed
  • Requires the GA4 global site tag (window.gtag) to already be present on your page
  • Use BigQuery Export or GA4 Explore reports to cross-segment with experiment variants

Mixpanel (Business+):

  • Enter your Mixpanel Project Token
  • The snippet fires mixpanel.track('$experiment_started', { experimentName, variantName }) automatically
  • Requires the Mixpanel SDK (window.mixpanel) to be loaded on your page before the Segmently snippet runs

Outbound Webhook (Business+):

  • Enter any HTTPS endpoint URL
  • Choose which events to subscribe to: experiment.started, experiment.paused, significance.reached
  • Segmently POSTs a JSON payload with experiment ID, variant info, timestamp, and event type
  • Useful for custom dashboards, CRM updates, or CI/CD pipeline triggers

All integrations require a Business plan or higher, except Slack which is available on Professional+. Integration config is stored in the integrations JSONB column on the experiment record.

Behavioral Targeting

What Is Behavioral Targeting?

Activate experiments only after a visitor does something, not just by visiting a URL

Standard A/B testing evaluates targeting rules at the moment a visitor lands on a page. If their URL, device, and location match, they are bucketed immediately and the experiment changes render before the page is revealed (anti-flicker protection).

Behavioral targeting is different. Instead of bucketing at page load, the experiment waits for the visitor to take a specific action mid-session. Only once that action occurs does the variant assignment happen and the experiment changes appear.

Why this matters for revenue:

  • Show an upsell offer only to visitors who have already scrolled through your pricing page (proven intent)
  • Display a discount popup only to visitors who have been on the checkout page for 30 seconds (hesitation signal)
  • Personalize the CTA copy for visitors who clicked your paid ad (traffic source is known)
  • Test a chat button variant only after the visitor clicks a specific help link (contextual relevance)

Key difference from standard experiments:

  • Behavioral experiments do not use anti-flicker CSS — the page is already visible when the trigger fires
  • Changes appear naturally in context, mid-session, without any page reload
  • Variant assignment is still persistent — a visitor is assigned once and stays in that variant on future visits
  • URL targeting and device targeting still apply before any behavioral trigger is evaluated

Available on: Professional and above.

Visitor Type: New vs. Returning

Restrict an experiment to first-time visitors or to visitors who have been to your site before

The Visitor Type filter lets you limit who can be bucketed into an experiment based on whether they have visited your site before.

How detection works:

When the Segmently snippet loads, it checks for a cookie named _seg_visitor in the visitor's browser. This cookie is set on first visit and persists for 1 year.

  • All Visitors (default): Everyone who matches URL and device targeting is eligible. The cookie is not checked.
  • New Visitors only: Only visitors whose browser does not have the _seg_visitor cookie are bucketed. Returning visitors are excluded entirely — they will not see the experiment at all.
  • Returning Visitors only: Only visitors whose browser already has the _seg_visitor cookie are bucketed. First-time visitors are excluded entirely.

Use cases:

  • New Visitors only: Test first-impression variations (hero copy, onboarding flow, first-session discount offers)
  • Returning Visitors only: Test loyalty offers, personalized re-engagement messages, or features that only make sense once the visitor already knows your product

Testing tip: To simulate a new visitor, clear your browser cookies or use a fresh incognito window. To simulate a returning visitor, visit the site in a regular window at least once first, then reload.

Important caveats:

  • Cookie-based detection can be affected by privacy settings, browser extensions, or private browsing. Some visitors who have visited before may appear as "new" if their cookies were cleared.
  • Visitor type is checked alongside behavioral triggers. A returning visitor excluded by the "New Visitors only" filter will not be bucketed even if they scroll to the trigger depth.

Scroll Depth Trigger

Activate the experiment once the visitor scrolls past a percentage of the page height

The scroll depth trigger fires when the visitor has scrolled far enough that the bottom of their visible viewport is at or below a set percentage of the total page height.

How it is measured:

(window.scrollY + window.innerHeight) / document.documentElement.scrollHeight ≥ threshold / 100

This means the trigger fires when the visible fold of the page (not just the scroll position) crosses the threshold. A visitor on a large monitor viewing a short page may trigger 90% scroll depth without scrolling at all.

Configuration options:

  • Presets: 25%, 50%, 75%, 90% — one click to set
  • Custom: any value from 5% to 100% in 5% increments using the range slider, or type a specific value

When to use each threshold:

  • 25%: Engagement intent — visitor scrolled below the fold. Good for above-the-fold variations that should only apply if the visitor is engaging.
  • 50%: Mid-content interest — visitor has read a good portion. Good for mid-article CTA tests.
  • 75%: High engagement — visitor is close to the end. Good for exit-style offers before they leave.
  • 90%: Near completion — visitor has consumed nearly all content. Good for post-read upsells or subscription prompts.

Use cases:

  • Show a sticky CTA bar only after 50% scroll (ensures the visitor has read enough context)
  • Test a newsletter signup variant that appears at 75% instead of on page load
  • Replace a pricing section CTA for visitors who scrolled past testimonials
How to test: Open the page and scroll down. The trigger fires the moment your viewport crosses the threshold depth. You do not need to pause at that point. If you have set 50%, scroll until you estimate you're halfway through the page — the experiment changes should appear immediately at that point.

Time on Page Trigger

Activate the experiment after the visitor has been on the page for a set number of seconds

The time on page trigger uses a setTimeout that starts the moment the snippet initializes on the page. When the configured number of seconds elapses, the variant is assigned and changes are applied.

Configuration options:

  • Presets: 5s, 10s, 15s, 30s, 60s
  • Custom: any value from 1 to 600 seconds (10 minutes maximum)

When to use each duration:

  • 5–10 seconds: Visitor has paused on the page and is reading. Useful for "need help?" chat prompts or soft upsells.
  • 15–30 seconds: Visitor is genuinely engaged with content. Good for mid-session offer reveals or personalized CTAs.
  • 30–60 seconds: Visitor is a strong reader or researcher. Use for late-session offers, exit-intent equivalents, or free-trial conversion prompts.
  • 60+ seconds: Highly engaged sessions. Suitable for content subscribers, course learners, or product evaluators.

Important behavior: The timer starts when the page loads. Navigating away and returning resets the timer (each page load is a fresh session event). The trigger fires regardless of whether the visitor is actively interacting — it is a pure time measurement, not an activity measurement.

Use cases:

  • Show a "Still thinking about it?" offer after 30 seconds on the pricing page
  • Test a persistent header CTA that appears after 15 seconds vs. one that appears immediately
  • Display a live chat invite variant at 10 seconds for visitors on the support page
How to test: Set the time trigger to 5 seconds (even if your production value is 30 seconds), activate the experiment, and load the page. Wait 5 seconds without interacting. The experiment changes should appear automatically. Set the value back to your intended duration after confirming it works.

Element Click Trigger

Activate the experiment when the visitor clicks a specific element on the page

The element click trigger listens for a click anywhere on the document and checks whether the clicked element (or any of its ancestors) matches a CSS selector you specify. If the selector matches, the trigger fires and the experiment activates.

How to write the CSS selector:

You can target any element using standard CSS selector syntax. The selector is evaluated using element.closest(selector), which means clicking a child of the target element will still match.

Selector examples:

  • #add-to-cart — element with ID "add-to-cart"
  • .btn-checkout — any element with class "btn-checkout"
  • button[data-action="upgrade"] — button with a data attribute
  • nav a.pricing-link — anchor with class inside nav
  • [data-testid="open-chat"] — element with a test ID attribute
  • form.contact-form button[type="submit"] — submit button inside a specific form

How to find the right selector:

  1. Open your website in Chrome DevTools (right-click any element and choose "Inspect")
  2. Look for an id attribute on the element — if present, #the-id is the most reliable selector
  3. If no ID, look for a unique class: .unique-class-name
  4. If neither, use a data attribute: [data-action="checkout"]
  5. Right-click the element in the DevTools Elements panel and choose "Copy selector" for an auto-generated selector (though these can be fragile)

Use cases:

  • Apply a checkout-specific variant to visitors who have clicked "Add to Cart"
  • Show a personalized upsell section the moment a visitor opens the pricing dropdown
  • Change CTA copy only after a visitor has clicked the live demo button (high-intent signal)
  • Test two versions of the post-click thank-you message for visitors who submit a contact form
How to test: Set the selector, activate the experiment, and load the page in your browser. Click the element identified by the selector. The experiment variant should apply within milliseconds of the click. If changes do not appear, verify the selector matches the element by running document.querySelector('your-selector') in the browser console — it should return the element, not null.

Referral Source Gate

Block the experiment entirely for visitors who did not arrive from a specific traffic source

The referral source gate is different from the other triggers. Rather than firing mid-session, it evaluates synchronously at page load as a pre-filter. If the visitor's source does not match your selected set, the experiment is skipped entirely — no bucket assignment, no trigger listeners, nothing.

How source detection works:

The snippet reads two signals: document.referrer (the URL of the page the visitor came from) and UTM parameters in the current URL (utm_source, utm_medium, utm_campaign). UTM params take precedence when present.

Source categories:

Organic: Referrer is a search engine (google.com, bing.com, yahoo.com, duckduckgo.com, baidu.com, yandex.com) with no UTM parameters present. Visitors who "googled" their way to your site.
Paid: utm_medium is "cpc", "ppc", "paid", "paid_search", or "paidsocial"; or utm_source is "google" with any UTM present. Visitors from Google Ads, Meta Ads, and other paid channels.
Social: Referrer is a social platform (facebook.com, twitter.com, x.com, instagram.com, linkedin.com, pinterest.com, tiktok.com, reddit.com, youtube.com) or utm_medium is "social". Organic social posts and shares.
Email: utm_medium is "email" or utm_source is "email" or "newsletter". Visitors arriving from email campaigns.
Direct: document.referrer is empty and no UTM parameters are present. Visitors who typed the URL directly, used a bookmark, or followed an untagged link in a desktop app.
Other: Any source that does not match the above categories. Includes referrals from partner sites, internal links between domains, or unrecognized UTM values.

Use cases:

  • Show a channel-specific landing page variant only to paid traffic (Paid gate)
  • Test organic-only messaging without polluting the data with paid visitors
  • Show a "welcome back from our newsletter" variant exclusively to email subscribers (Email gate)
  • Run a social-proof heavy variant only for social referrals who may not know your brand yet
How to test each source:
  • Paid: append ?utm_medium=cpc to your URL
  • Social: append ?utm_medium=social
  • Email: append ?utm_medium=email
  • Organic: visit from a Google search (in production) or use ?utm_source=google without a medium to simulate organic detection (referrer-only detection may not work in localhost tests)
  • Direct: open a fresh incognito tab and type the URL manually with no query params
  • Other: use any UTM value not in the above matched sets, such as ?utm_medium=partner

Combining Triggers: Evaluation Order

How multiple triggers interact and which one wins

You can enable multiple behavioral triggers on the same experiment. Understanding the evaluation order is essential for predicting when the experiment activates.

Order of evaluation:

  1. URL targeting (always first) — the current page URL must match at least one of the experiment's URL rules. If it does not match, the experiment is not even loaded.
  2. Device targeting — the visitor's device type (desktop, mobile, tablet) must match. Evaluated at page load.
  3. Geographic targeting — if you have selected specific countries, the visitor's country must be in the set. Evaluated at page load.
  4. Visitor type check — if set to "New Visitors only" or "Returning Visitors only", the cookie is checked at page load. Excluded visitors are skipped.
  5. Referral Source Gate — evaluated synchronously at page load. If enabled and the visitor's source does not match, the experiment stops here. No other triggers are set up.
  6. Async triggers (scroll, time, click) — if the visitor passes all gates above, Segmently sets up event listeners for every enabled async trigger. Whichever trigger fires first activates the experiment.

What "first to fire" means:

If you have both Scroll Depth set to 50% and Time on Page set to 30 seconds, the experiment will activate the instant either condition is met. A highly engaged visitor who scrolls fast may hit 50% scroll depth at 10 seconds — the scroll trigger fires first. A visitor who doesn't scroll but keeps the tab open will hit the 30-second timer instead.

Practical combinations:

Scroll + Time: Ensures the experiment reaches any engaged visitor — whether they engage by scrolling or just by staying. Good for ensuring high coverage without requiring specific scroll behavior.
Referral Source (Paid) + Time on Page (30s): Target paid traffic visitors who are still on the page after 30 seconds. High-intent, high-cost audience segment that deserves a personalized experience.
Referral Source (Email) + Scroll (75%): Show a loyalty offer only to email subscribers who have read most of the content — the most engaged returning audience.

Each async trigger fires at most once per page visit. Once the experiment activates (any trigger fires), all other trigger listeners are removed.

Testing Behavioral Experiments

Step-by-step guide to verifying that each trigger type works correctly in your experiment

General setup for all behavioral trigger tests:

  1. Create your experiment in the wizard with behavioral triggers configured
  2. Add at least one segment with visible visual changes (e.g., change a heading text or background color so you can confirm activation)
  3. Set the experiment status to Active
  4. Open your website in a regular browser (not the visual editor preview — behavioral triggers are live-mode only)
  5. Trigger the condition described below for each trigger type
  6. Confirm the experiment changes appear on the page

Testing Scroll Depth:

1. Set scroll depth to 50% for an easy test (adjust back after)

2. Load the matching URL in your browser

3. Scroll down slowly until you estimate you are halfway through the page

4. Experiment changes should appear precisely when the threshold is crossed — no interaction needed beyond scrolling

5. If changes do not appear, open the browser console and look for any Segmently error messages

Testing Time on Page:

1. Set the time trigger to 5 seconds for testing (set it to the real value after)

2. Load the matching URL in your browser

3. Stay on the page without navigating away

4. After 5 seconds, the experiment changes should appear automatically

5. The timer resets on page reload — every visit starts fresh

Testing Element Click:

1. Verify your selector in the browser console first: document.querySelector('.your-selector') must return the element (not null)

2. Load the matching URL in your browser

3. Click the element identified by your selector

4. Experiment changes should appear immediately after the click fires

5. Clicking a child element (e.g., an icon inside a button) will also match — clicks bubble up to the parent

Testing Referral Source:

Append the appropriate UTM parameters to your page URL to simulate different sources:

  • Paid traffic: ?utm_medium=cpc
  • Social traffic: ?utm_medium=social
  • Email traffic: ?utm_medium=email
  • Direct traffic: visit the URL with no UTM params in a fresh tab with no referring page

The referral gate evaluates at page load. If the source does not match, no triggers will fire at all — this is the expected behavior.

No anti-flicker in behavioral experiments: Because the page is already visible when a behavioral trigger fires, the snippet does not hide the page with body { opacity: 0 } for these experiments. Changes appear as a natural transition mid-session. This is intentional behavior, not a bug. If you need the transition to be smoother, add a CSS transition to the elements you are change in your segment's custom CSS (e.g. transition: all 0.3s ease).

Behavioral Targeting: Important Caveats

Edge cases, limitations, and things to know before relying on behavioral experiments in production

  • Client-side evaluation only. All trigger detection (scroll, time, click, referral) happens in the visitor's browser, not on the server. This means trigger logic runs after the JavaScript bundle loads. On very slow connections or pages with large bundles, the snippet may initialize slightly late.
  • Persistent assignment after first trigger. Once a visitor is bucketed into a behavioral experiment, their assignment is permanent. Future page visits will apply the same variant immediately at page load (not behavioral trigger) because the assignment already exists.
  • One activation per page load. Triggers fire at most once per page visit. If the visitor reloads the page, the timer resets, the scroll position resets, and trigger listeners are re-established fresh.
  • Async triggers are independent. Scroll depth, time on page, and element click are all active simultaneously once the referral gate passes and visitor type matches. Whichever fires first wins and removes the other listeners.
  • URL targeting still applies. Behavioral triggers only register on pages that match the experiment's URL targeting rules. If the visitor navigates to a non-matching page, no triggers will fire on that page.
  • Traffic percentage applies before triggers. If your experiment is set to 50% traffic, only 50% of visitors who match all other criteria will be considered for bucketing — and only those visitors get trigger listeners. The other 50% are excluded before any triggers are evaluated.
  • Referral source uses UTM params first. When UTM params are present, referrer domain matching is ignored. Always use UTM tags on your paid and email campaigns for accurate source classification.
  • Private browsing affects visitor type detection. In incognito or private mode, cookies are session-scoped. A returning visitor using private mode may appear as a new visitor.

Attribute Targeting

What Is Attribute Targeting?

Restrict an experiment to visitors who match custom key-value attributes you set via the JavaScript API

Attribute targeting lets you define rules based on data your application already knows about the visitor. You push that data into Segmently once per page load using window.Segmently.setAttributes(), and then the snippet evaluates those attributes against your experiment rules before deciding whether to bucket the visitor.

Why attribute targeting matters for revenue:

  • Only show a pricing experiment to visitors on a paid plan, never to trial users
  • Run a checkout redesign exclusively for visitors whose cart value exceeds $100
  • Test a loyalty offer for visitors who have logged in more than 5 times
  • Segment enterprise visitors from SMB visitors using your own account data

How it works:

  1. You call window.Segmently.setAttributes({plan: 'pro', loginCount: 8}) in your app code
  2. The snippet stores these attributes in memory for the current page session
  3. When evaluating experiments, the snippet checks all attribute rules against the stored values
  4. If every rule passes (AND logic), the visitor is eligible for the experiment
  5. If any rule fails, the visitor is skipped entirely: no assignment is made and the original site is shown

Key facts:

  • Attribute rules are AND-gated: all rules must pass for the visitor to be bucketed
  • Evaluation happens before the assignment API call, so excluded visitors never count against your traffic quota
  • Attributes are evaluated in both standard and behavioral-trigger experiments
  • Experiments without attribute rules are unaffected: the gate only runs when at least one rule is configured
  • Available on: Professional and above

Operators Reference

Seven comparison operators cover all common targeting scenarios

Each attribute rule consists of three fields: Key (the attribute name), Operator, and Value (not used for exists / not_exists).

OperatorPasses when...Example ruleNotes
equalsAttribute value exactly matches the rule value (string comparison)plan equals proBoth sides coerced to string before comparing
not_equalsAttribute value does NOT match the rule valueplan not_equals freeUseful for excluding a specific segment
containsAttribute value includes the rule value as a substringemail contains @company.comCase-sensitive substring check
greater_thanAttribute value (as number) is strictly greater than the rule valueloginCount greater_than 5Non-numeric values fail this check
less_thanAttribute value (as number) is strictly less than the rule valuecartValue less_than 50Non-numeric values fail this check
existsThe attribute key is present with a non-null, non-undefined valueuserId existsNo value field needed; detects logged-in users
not_existsThe attribute key is NOT present, or its value is null/undefineduserId not_existsNo value field needed; detects anonymous visitors

All string comparisons are case-sensitive. Numeric operators (greater_than, less_than) parse both sides via parseFloat(). If either side is not a valid number, the rule fails (visitor excluded).

Usage Examples

Real-world patterns for setting attributes and building targeting rules

1. Target paid-plan users only

In your app code, after the user session loads:

window.Segmently.setAttributes({
  plan: currentUser.plan  // e.g. 'free', 'pro', 'business'
})

Then in the Audience tab, add a rule: plan equals pro

2. Only show experiment to logged-in users

if (currentUser) {
  window.Segmently.setAttributes({ userId: currentUser.id })
}

Audience tab rule: userId exists

3. High-value cart experiment

window.Segmently.setAttributes({
  cartValue: cart.total  // numeric, e.g. 149.99
})

Audience tab rule: cartValue greater_than 100

4. AND logic — multiple rules

Add two rules to the same experiment: both must pass.

window.Segmently.setAttributes({
  plan: 'pro',
  country: 'US',
  loginCount: 12
})

Rules: plan equals pro AND loginCount greater_than 5 — both must pass.

5. Exclude a specific cohort

window.Segmently.setAttributes({
  role: currentUser.role  // 'admin', 'member', etc.
})

Rule: role not_equals admin — admins never see the experiment variant.

When to call setAttributes()

Call setAttributes() as early as possible in your page lifecycle, before the Segmently snippet evaluates experiments. The best place is immediately after your user session resolves. Attributes set after the snippet has already run the experiment evaluation loop will not affect the current page; they will take effect on the next page load.

Attribute keys are case-sensitive

The key you use in setAttributes() must exactly match the key you enter in the targeting rule. plan and Plan are treated as different keys.

Maximum 10 rules per experiment

Each experiment supports up to 10 attribute rules. Rules are evaluated with AND logic: all rules must pass for a visitor to be bucketed.

Reserved key names are ignored

The keys __proto__, constructor, and prototype are reserved JavaScript property names and are silently ignored by setAttributes(). Use descriptive application-specific key names instead.

Multivariate Testing (MVT)

What is Multivariate Testing (MVT)?

Test multiple page elements at once — Segmently generates every combination automatically as a separate test cell

Standard A/B testing compares two or more complete page versions. MVT tests multiple individual elements simultaneously by generating every possible combination of your element variations as separate test cells.

Example setup:

  • Section 1 — Hero Headline: Variation A, Variation B
  • Section 2 — CTA Button: Red, Green
  • Section 3 — Hero Image: Photo, Illustration

Segmently auto-generates: 2 × 2 × 2 = 8 test cells, each receiving approximately 12.5% of included traffic.

What results tell you:

  • Which combination of elements performs best overall (the winning cell)
  • How significant the lift is for each cell vs. the Control combination

Plan requirement: MVT is available on Business and Enterprise plans.

MVT vs A/B Testing: When to Use Each

Choose the right test type based on your traffic volume and what you want to learn

Use A/B testing when:

  • You want to test one big change (new hero, redesigned pricing section)
  • Traffic is moderate (a few hundred visitors total can be sufficient)
  • You have a focused hypothesis and want a clear answer quickly
  • You are comparing completely different layouts or user flows

Use MVT when:

  • You want to optimize several small elements at once (headline, CTA copy, image)
  • Traffic is high enough to fill all cells (plan for 1,000+ visitors per cell)
  • You want to find the best combination rather than the best single change
  • You want to reduce the number of sequential A/B tests needed

Key trade-off: MVT gives you richer data but requires significantly more traffic. Cell count grows fast — 3 sections with 3 variations each creates 27 cells, each getting only ~3.7% of traffic.

Creating an MVT Experiment

Enable MVT in the Basics tab, then define sections and variations in the MVT Sections tab

Step 1: Select Test Type (Basics Tab)

  • Open the experiment wizard and go to the Basics tab
  • Find the Test Type field
  • Toggle from A/B Test to Multivariate Test (MVT)
  • A plan badge confirms this requires Business or Enterprise

Step 2: Add Sections (MVT Sections Tab)

  • The MVT Sections tab replaces the Variants tab in the wizard
  • Click Add Section to create a test element (e.g., "Hero Headline")
  • Each section represents one element of your page being tested
  • Each new section starts with a Control variation (your current content)

Step 3: Add Variations per Section

  • Within each section, click Add Variation
  • Name each variation descriptively (e.g., "Shorter Headline", "Red CTA")
  • Optionally add CSS changes, JavaScript, or HTML per variation
  • Each section needs at least 2 variations (Control + at least one more)

Step 4: Launch

  • The Review tab shows total sections, total cells, and all variation labels
  • Set status to Live to auto-generate all mvt-cell-* variants
  • Segmently divides traffic equally among all generated cells

Test Cells and Traffic Distribution

How Segmently calculates cell count and divides traffic across all element combinations

Cell count formula:

Total cells = product of each section's variation count (Control counts as one variation).

  • 2 sections × 2 variations each = 4 cells (25% traffic each)
  • 3 sections × 2 variations each = 8 cells (12.5% each)
  • 3 sections with 2, 3, and 2 variations = 2 × 3 × 2 = 12 cells (~8.3% each)

Traffic distribution:

  • Traffic is split equally across all cells
  • You control total exposure via the Traffic Percentage slider (Audience tab)
  • Example: 50% traffic with 8 cells means each cell sees 6.25% of all visitors

Cell count warning:

  • The wizard shows a warning when your setup exceeds 12 cells
  • More cells requires more traffic before results reach significance
  • A practical baseline: aim for 1,000+ visitors per cell before drawing conclusions
  • Keep setups focused — 2 to 3 sections with 2 variations each is a solid starting point

Launching and Reviewing Results

Set the experiment live and interpret per-cell performance from the analytics dashboard

Launching:

  • Set status to Live from the experiment list or detail page
  • Segmently automatically creates one variant per cell (named mvt-cell-1, mvt-cell-2, etc.)
  • Each cell corresponds to one unique combination of section variations
  • Visitors are bucketed into a cell on first encounter and stay in it persistently

Reading results:

  • The Analytics view shows visitor count, conversions, conversion rate, and confidence per cell
  • Compare all cells to identify which combination drives the highest conversion rate
  • Look for cells where confidence exceeds 95% before declaring a winner
  • The cell with the best combination across all sections is your winning variant

After the experiment:

  • Implement the winning combination directly on your site
  • Archive the experiment when done to keep your experiment list clean
  • Use the insights to inform future A/B tests targeting individual elements

Feature Flags

What Are Feature Flags?

Instantly turn features on or off for any percentage of your visitors, without deploying new code

Feature flags (also called feature toggles) let you control which visitors see a new feature at runtime. You deploy the code with the flag off, then enable it for a percentage of visitors directly from the Segmently dashboard, no code push needed.

Feature flags vs A/B experiments:

  • Flags: On/off toggle for code-level feature availability. No visual editor, no variant comparison. Best for gradual rollouts and kill switches.
  • Experiments: Compare two or more versions of a page or element with statistical analysis. Best for measuring which design or copy performs better.

Plan requirement: Feature flags are available on Professional, Business, and Enterprise plans.

Creating and Managing Flags

Create flags from your project page and manage them from the flags list

To create a flag:

  1. Open your project in the Segmently dashboard
  2. Click "Feature Flags" in the project navigation
  3. Click "New Flag"
  4. Enter a name and a unique flag key (e.g. new-checkout-ui)
  5. Set the initial rollout percentage and status, then save

Flag states:

  • Active: The flag is live. isEnabled() returns true for visitors within your rollout percentage.
  • Inactive: The flag is off for everyone. isEnabled() always returns false.
  • Archived: Permanently disabled. Use this when a flag is no longer needed.

Rollout percentage: Controls the fraction of visitors for whom the flag is enabled. Set to 100% to enable for all visitors, or start lower (e.g. 5%) for a gradual rollout.

Using Flags in Your Code

The Segmently snippet exposes isEnabled() and getAllFlags() on window.Segmently

Once the snippet is installed, you can evaluate flags using the JavaScript SDK. All flags for a project are fetched in a single request and cached for the page lifetime, so calling isEnabled() multiple times has no extra network cost.

Check a single flag:

const enabled = await window.Segmently.isEnabled('new-checkout-ui')

if (enabled) {
  // show new checkout flow
} else {
  // show original checkout
}

Get all flags at once:

const flags = await window.Segmently.getAllFlags()
// flags = { "new-checkout-ui": true, "dark-mode": false, ... }

if (flags['dark-mode']) {
  document.body.classList.add('dark')
}

Both methods are async and return a Promise. Make sure the Segmently snippet has loaded before calling them. If the snippet is in your <head>, it is available by the time your inline scripts run. For dynamically loaded scripts, wait for the segmently-snippet-ready postMessage event.

Visitor consistency: A visitor assigned to the enabled cohort at 50% rollout will always receive the same result on every page visit. Assignments are deterministic and persistent.

Kill Switch: Disabling a Flag Instantly

Turn off any feature for all visitors in seconds, with no code deploy required

The kill switch is one of the most valuable properties of feature flags. If a new feature causes errors or unexpected behavior in production, you can disable it for all visitors immediately from the dashboard, no git commit or deployment needed.

To kill switch a flag:

  1. Open the flag from your project's Flags page
  2. Change the status from "Active" to "Inactive"
  3. Click "Save Changes"

Within seconds, isEnabled() will return false for all visitors. The flag and its configuration are preserved so you can re-enable it when the issue is resolved.

Best practice: Wrap every significant new feature in a flag before shipping. The cost is minimal and the safety net is invaluable.

Auto-Winner Detection & Alerts

Auto-Winner Detection

Segmently watches your active experiments around the clock and alerts you the instant a variant reaches statistical significance

The background scheduler runs every 60 seconds and evaluates every active experiment in your organization. When a variant achieves 95% statistical confidence over the control, an alert is instantly created and appears in your bell notification center.

How the winner check works:

  • Uses a two-proportion z-test comparing the conversion rate of each variant against the control
  • Requires at least 30 unique visitors per variant before a winner can be declared (prevents false positives on low traffic)
  • A result is declared significant when the z-score exceeds 1.96, corresponding to 95% confidence
  • Each experiment only ever produces one winner alert (a flag prevents duplicate notifications)

What the alert shows:

  • The name of the winning variant
  • Conversion lift over the control (positive or negative percentage)
  • Confidence percentage (e.g., 99.9%)
  • A direct link to the experiment's analytics page

Plan availability: Auto-winner detection is available on Professional, Business, and Enterprise plans.

Alert Bell (Notification Center)

A live bell icon in the dashboard header shows your unread alert count and expands to a full notification panel

The bell icon appears in the top navigation bar of every dashboard page. An orange badge on the bell shows the exact count of unread alerts. Clicking the bell opens a slide-out panel listing all recent alerts.

Interacting with alerts:

  • View: Click the bell to open the notification panel
  • Mark read: Alerts are automatically marked as read when you open the panel
  • Mark all read: Use the "Mark all read" button at the top of the panel to clear all alerts at once
  • Go to experiment: Each alert contains a link that navigates directly to the experiment's analytics page

Alert types shown in the panel:

  • Winner Detected: A variant has reached 95% confidence, including variant name, lift, and confidence score
  • Max Duration Exceeded: An experiment has run longer than its configured maximum duration without finding a winner

The bell panel polls for new alerts while you are using the dashboard, so you will see incoming notifications without needing to refresh the page.

Maximum Duration Alert

Set a time limit on any experiment and get notified if it runs out of time before finding a winner

Some experiments run for weeks without reaching significance. The Maximum Duration alert gives you a clear deadline: set the maximum number of days you are willing to run the test, and Segmently notifies you when that time is up.

Setting a maximum duration:

  1. Open your experiment and navigate to the Advanced tab
  2. Find the Maximum Experiment Duration field
  3. Enter the maximum number of days (e.g., 14 for a two-week cap)
  4. Save (or save on final review when creating a new experiment)

How the duration check works:

  • The timer starts from activated_at, the exact moment the experiment was started
  • If activated_at + max_duration_days is in the past and no winner has been found, an alert is created
  • The alert fires only once per experiment and only if no winner alert has already been sent

What to do when you receive this alert:

  • Extend the test: If traffic is lower than expected, increase the duration and let it continue
  • Pause or archive: If the data shows no meaningful difference, call it a draw and move on
  • Review for setup issues: Check targeting rules and goal configuration to confirm data is being collected correctly

This field is optional. Experiments without a maximum duration run indefinitely until you manually pause or archive them.

Slack & Webhook Notifications for Winner Detection

Get notified in Slack or via a custom webhook the moment an experiment winner is detected

In addition to in-app alerts, Segmently can push winner notifications to your team's Slack channel or any HTTPS endpoint. This means your team is alerted even when no one is logged into the dashboard.

Setting up Slack notifications:

  1. Go to Settings (top navigation) and open the Organization tab
  2. In the Integrations section, paste your Slack Incoming Webhook URL
  3. Enable the Winner detected notification toggle
  4. Save settings. Segmently will now send a Slack message the next time a winner is found

Per-experiment Slack override:

You can also set a Slack webhook directly on each experiment from the Integrations tab in the experiment editor. A webhook set at the experiment level fires unconditionally on winner detection regardless of org-level preferences, useful for high-priority tests with dedicated channels.

What the Slack message contains:

  • Experiment name and site name
  • Winning variant name
  • Conversion lift and confidence percentage
  • A link to the analytics page for immediate review

Plan requirement: Org-level Slack notifications require a Professional plan or higher.

Alert Reliability & Deduplication

Every alert fires exactly once per experiment, even if the scheduler runs hundreds of times

The scheduler is designed to be idempotent: once an alert has been sent for an experiment, it will never send again for the same event, no matter how many times the background job runs.

How deduplication works:

  • Winner alerts: controlled by a winner_alert_sent flag on the experiment. The scheduler skips experiments where this flag is true
  • Duration alerts: controlled by a duration_alert_sent flag. Same skip logic applies
  • Flags are set atomically when the alert row is created, so there is no risk of double-firing even under concurrent scheduler runs

What an alert row contains (stored in the database):

  • alert_type: winner_detected or max_duration_exceeded
  • message: human-readable description of the alert
  • read: updated when you open the notification panel
  • created_at: timestamp of detection

Alerts are scoped to your organization so all team members see the same notification center, regardless of who is logged in at the time the alert fires.

Core Features

Experiment Lifecycle Management

Full control over experiment status from draft to archived

Experiment States:

  • Draft: Being configured, not live yet
  • Live: Running and tracking visitors
  • Paused: Temporarily stopped (data preserved)
  • Archived: Completed/ended (removed from active list)

Quick Actions:

  • ▶️ Start: Launch draft experiments
  • ⏸️ Pause: Temporarily stop tracking
  • ▶️ Resume: Continue paused experiments
  • 📦 Archive: Move to archived list
  • ♻️ Reinstate: Restore archived experiments

View Options:

  • Active experiments shown by default
  • Archived experiments in collapsible section
  • Count badge shows archived experiments (e.g., "3 Archived")

Anti-Flicker Protection

Zero flickering for experiment participants with customizable activation delays

How It Works:

  • Snippet injects CSS to hide page content immediately
  • Fetches experiment configuration and variant assignment
  • Applies changes (DOM manipulation, CSS injection)
  • Waits for activation delay (0ms, 100ms, 500ms, 1s, or custom)
  • Removes anti-flicker to reveal final result

Activation Delay Options:

  • Immediate (0ms): Show changes instantly
  • Fast (100ms): Brief wait for scripts to load
  • Standard (500ms): Allow dependencies to initialize
  • Safe (1000ms): Ensure all assets loaded
  • Custom: Set your own timing

Failsafe:

  • 5-second timeout always reveals content (prevents permanent hiding)
  • Users assigned to variant ONLY see their variant (never original first)
  • All segments can be customized (Control is NOT special)

Creating Experiments

Design and launch A/B tests with URL targeting, device segmentation, geo targeting, and traffic control

Experiment Setup:

  • Create unlimited variants with custom names
  • Set traffic allocation (50/50, 33/33/34, custom weights)
  • Control traffic percentage (run on 10%, 50%, 100%)

URL Targeting:

  • Exact match: https://example.com/page
  • Contains: /product/ anywhere in URL
  • Starts with: https://example.com/blog/
  • Ends with: .html or /checkout
  • Regex: Advanced pattern matching

Device Targeting:

  • Desktop only, mobile only, or tablet only
  • All devices (default)

Geo / Country Targeting:

  • Target by country using ISO 3166-1 alpha-2 codes (US, GB, DE, CA, etc.)
  • Visitors from non-listed countries are excluded from the experiment
  • Leave empty to allow all countries (default)

Visual Editor (Detailed Guide)

Point-and-click interface powered by snippet-based element selection

What is the Visual Editor?

The Visual Editor lets you select elements on your website by hovering and clicking - just like Optimizely. No CSS selector knowledge required! It uses the Segmently snippet already installed on your site.

How It Works (Technical):

  1. Visual Editor opens your website in iframe
  2. Snippet detects it's in iframe and sends "ready" message
  3. Editor enables selection mode in snippet
  4. Snippet adds hover overlay and click handlers
  5. User hovers → blue highlight appears
  6. User clicks → element data sent to editor
  7. Editor displays CSS selector and element details
  8. User applies changes (hide, text, CSS)

Opening Visual Editor:

  • Go to Experiment → Variants tab
  • Select a variant (Control or Variation)
  • Click "Visual Editor" button
  • Enter URL to edit (or use target URL)
  • Modal opens with your website loaded

Element Selection:

  • Hover: Blue overlay highlights element
  • Click: Element selected, details shown
  • Info Displayed: Tag name, classes, ID, text content
  • CSS Selector: Auto-generated (e.g., .hero-section .cta-button)
  • Manual Override: Edit selector if auto-gen isn't specific enough

Change Types You Can Apply:

  • Hide Element: display: none (removes from page)
  • Replace Text: Change button text, headlines, etc.
  • Custom CSS: Color, size, position, fonts, etc.
  • Custom JavaScript: Advanced DOM manipulation

⚠️ Snippet Required:

If you see "Segmently Snippet Required" banner, the snippet isn't installed on your website yet. Add it to the <head> tag and refresh. Visual Editor only works when snippet is present!

Why This Approach?

  • ✅ Works with modern SPAs (React, Next.js, Vue, Angular)
  • ✅ No CORS issues (snippet runs on your domain)
  • ✅ No browser extension required
  • ✅ No bookmarklet to paste
  • ✅ Works automatically (snippet already installed)
  • ✅ Identical to Optimizely's approach

Troubleshooting:

  • Element selection not working? Check if snippet is installed (view browser console for "✅ Segmently loaded")
  • Wrong element selected? CSS selector may need refinement - edit manually
  • Changes not showing? Check selector matches intended element (use browser DevTools)
  • Website not loading? Check for X-Frame-Options header blocking iframes

Best Practices:

  • Test selectors in browser DevTools first (document.querySelector)
  • Use specific selectors (avoid body > div > div)
  • Prefer classes over IDs when possible
  • Preview changes before saving
  • Test on mobile/desktop if targeting multiple devices

Alternative: Manual CSS Selectors:

If Visual Editor isn't working or you prefer manual control, you can enter CSS selectors directly in the Variants tab. Use browser DevTools to find selectors: Right-click element → Inspect → Copy selector.

Analytics & Results Dashboard (Complete Guide)

Understand metrics, statistical significance, and winner determination

Accessing Analytics:

  • Experiment-Specific: Experiment menu → "View Analytics" (available for all states)
  • Overall Dashboard: Main navigation → "Analytics" (cross-site view)

Key Metrics Explained:

1. Total Visitors

  • Count of unique visitors assigned to each variant
  • Tracked via page_view events
  • Visitor = unique visitor_id (determined by fingerprinting or cookie-free ID)
  • Same visitor seeing page multiple times = 1 visitor (not multiple)

2. Conversions

  • Count of visitors who completed your goal
  • Tracked via conversion events (trackConversion() or URL-based)
  • Multiple conversions from same visitor = 1 conversion
  • Binary metric: Either converted or didn't

3. Conversion Rate

  • Formula: (Conversions / Total Visitors) × 100
  • Expressed as percentage (e.g., 5.2%)
  • Primary metric for winner determination
  • Example: 52 conversions / 1000 visitors = 5.2%

4. Statistical Significance

  • Measures confidence that a variant's improvement is real and not due to random chance
  • Calculated using a two-proportion z-test, the industry-standard method for A/B test analysis
  • Compares each treatment variant's conversion rate against the Control variant
  • Formula: z = |p2 − p1| / √(pPooled × (1−pPooled) × (1/n1 + 1/n2))
  • Expressed as a percentage confidence level (e.g., 95%, 99%)
  • 95%+ = Statistically significant; winner is declared
  • <95% = Inconclusive; keep collecting data
  • Requires at least 10 visitors per variant to compute (returns 0 otherwise)

5. Confidence Level

  • Directly derived from the z-test p-value: confidence = (1 − pValue) × 100
  • Capped at 99.9% to prevent misleading "100% certain" displays
  • 95% confidence = 95 in 100 experiments would show the same outcome
  • 99% = Very strong result; rare to be wrong
  • When significance is first reached, a significance.reached Slack / webhook notification fires automatically (once per experiment)

6. Duration

  • Number of days experiment has been running
  • Calculated from launch date to now
  • Minimum 7-14 days recommended for most tests
  • Accounts for weekly traffic patterns

7. Average Time on Page

  • Average seconds visitors spend on page
  • Engagement metric (higher = more engaged)
  • Tracked automatically by snippet
  • Excludes bounces (<5 seconds)

8. Bounce Rate

  • Percentage of visitors who left without interaction
  • Formula: (Bounces / Total Visitors) × 100
  • Lower = better (means people engage)
  • Bounce = <5 seconds on page or immediate exit

9. Revenue (Optional)

  • Total revenue attributed to each variant
  • Tracked via trackConversion({ value: 99.99 })
  • Useful for e-commerce experiments
  • Shows average order value per variant

Winner Determination Logic:

  1. Fetch all variant analytics (visitors, conversions, conversion rate)
  2. Run a two-proportion z-test comparing each treatment variant against Control
  3. Winner = the treatment variant with the highest z-test confidence that also beats Control's conversion rate
  4. If the winning confidence ≥ 95%, a winner is declared and the banner is shown
  5. If no variant reaches 95% confidence, show "No clear winner yet; collect more data"
  6. The first time 95% is reached, a one-time significance.reached notification fires via Slack / outbound webhook

Winner Callout Banner:

  • Green banner at top when winner found
  • Shows variant name and conversion rate
  • Displays confidence level (e.g., "97% confidence")
  • Only appears when 95%+ threshold met

Variant Performance Comparison:

  • Side-by-side cards for each variant
  • Shows all key metrics in one view
  • Visual bars indicate conversion rate differences
  • Best performer highlighted with border/badge
  • Sort by visitors, conversions, or rate

Overall Analytics Dashboard:

  • Cross-site view of all experiments
  • Filter by: Site, Status, Time Range (7d/30d/90d/all)
  • Sortable table by: Date, Visitors, Conversions, Rate
  • Quick links to experiment-specific analytics
  • Summary stats: Total experiments, active, paused, archived

When to Stop an Experiment:

  • ✅ Winner declared with 95%+ confidence
  • ✅ Run for at least 7-14 days (capture weekly patterns)
  • ✅ Sufficient sample size (1000+ visitors recommended)
  • ⚠️ Don't stop early just because one variant looks better
  • ⚠️ Statistical significance may be false positive with small sample

Best Practices:

  • Run experiments for full weeks (Mon-Sun)
  • Don't peek at results daily (increases false positives)
  • Wait for 95% confidence before declaring winner
  • Consider external factors (holidays, promotions)
  • Validate with secondary metrics (time on page, bounce rate)
  • Document learnings even if no clear winner

Event Tracking Implementation

Backend tracking for page views, conversions, and bounces

Key Metrics:

  • Total visitors per variant
  • Conversion count & rate
  • Statistical significance (95% confidence threshold)
  • Winner determination with confidence level

Engagement Metrics:

  • Average time on page
  • Bounce rate
  • Revenue per variant (optional)

Timeline Visualization:

  • Daily visitor trends
  • Conversion rate over time
  • Export to CSV and JSON

Automatic Tracking:

  • Page views (tracked automatically when snippet loads)
  • Bounce events (user leaves without interaction)
  • Stored in PostgreSQL with JSONB metadata

Database Schema:

  • events table: id, project_id, visitor_id, experiment_id, variant_id
  • event_name: 'page_view', 'conversion', 'bounce'
  • event_data: JSONB field for extensibility
  • created_at: timestamp for analysis

Batch Tracking:

  • POST /api/v1/events/batch endpoint
  • Insert multiple events with transactions
  • Reduces server load for high-volume sites

Assignment Tracking:

  • Deterministic variant assignment (consistent hashing)
  • hash(visitor_id + experiment_id) % 100 < traffic_percentage
  • Stored in assignments table (UNIQUE constraint)
  • Prevents duplicate assignments
  • Weight-based variant distribution

Manual Tracking:

// Track conversion
window.Segmently.trackConversion();

// Track with value
window.Segmently.trackConversion({
  value: 99.99
});

Conversion Tracking

Track purchases, sign-ups, and custom goals

Automatic Tracking:

  • Page views (tracked automatically)
  • Bounce events (user leaves without interaction)

Manual Tracking:

// Track conversion
window.Segmently.trackConversion();

// Track with value
window.Segmently.trackConversion({
  value: 99.99
});

Site Configuration:

  • Unified Conversion Rules with named events (conversion, login, registration)
  • Single condition or multi-step sequence detection
  • URL, URL parameter, localStorage, and cookie detection methods
  • Real-time condition tester for URL and URL parameter rules

Settings & Account Management

Settings Tabs

Complete account management across 5 specialized tabs

1. Profile Settings:

  • Update name, email, organization
  • View current subscription tier
  • Account creation date

2. Security:

  • Change password (requires current password)
  • Password requirements: 6+ characters
  • Password reset via email (when email service enabled)

3. Team & Permissions:

  • View all team members with roles and status
  • Transfer ownership (owner only)
  • Suspend/activate members (owner only)
  • Remove team members (owner only)
  • Seat count display (e.g., "2/2 seats")

4. Notifications:

  • Email notifications toggle
  • Experiment results alerts
  • Weekly reports (when available)
  • Security alerts

5. Billing:

  • View current plan and pricing
  • Manage subscription (cancel, reactivate)
  • Access Stripe Customer Portal
  • View payment history and invoices
  • Upgrade/downgrade plans

Team Management & Invitations

Collaborate with intelligent invitation flow, roles, and permissions

Team Invitation System:

  • Secure Tokens: 32-byte cryptographically secure tokens
  • 7-Day Expiration: Invitations expire after one week for security
  • Email Verification: Checks if invited email already has an account
  • Intelligent Routing: Automatically directs users to login or signup
  • One-Click Acceptance: Seamless team joining experience

Invitation Acceptance Flow (3 States):

  • Existing User: Redirects to login with email pre-filled, then auto-accepts invitation and adds to team
  • New User: Shows invitation-focused signup form (displays team name and role), creates account, auto-logs in, joins team immediately
  • Already Logged In: Auto-accepts invitation and redirects to dashboard with success message

Why This Matters:

  • No duplicate accounts created by mistake
  • Existing users don't need to create new credentials
  • New users see the exact team they're joining before signup
  • Zero friction - users land on dashboard immediately after joining
  • Perfect for collaborative A/B testing teams

Team Roles:

  • Owner: Full control, can transfer ownership, invite/remove members
  • Admin: Manage experiments and settings (future enhancement)
  • Member: View and edit experiments (future enhancement)

Member Status Badges:

  • Active (Green): Can access all features
  • Suspended (Red): Login/API access disabled
  • Pending (Amber): Invitation sent but not yet accepted

Owner Actions:

  • Invite Member: Send invitation email with secure token
  • Cancel Invitation: Revoke pending invitations before acceptance
  • Transfer Ownership: Make another member the owner
  • Suspend Member: Temporarily block access (no login, API disabled)
  • Activate Member: Restore suspended account
  • Remove Member: Delete from team permanently (with restrictions)

Team Member Removal Rules (Critical Business Logic):

  • Cannot Remove Yourself: Owner must transfer ownership first before leaving
  • Must Have One Member: Organizations must have at least one active member
  • Must Have One Admin: At least one owner/admin must remain
  • Owner-Only Action: Only owners can remove team members
  • UI Feedback: Disabled remove button shows reason (e.g., "Last admin", "You")

Why Removal Rules Matter:

  • Prevents accidental organization lockout
  • Ensures continuous access to sites and experiments
  • Protects data ownership and billing continuity
  • Forces proper ownership transfer process

Team Limits by Tier:

  • Free: 0 additional members (just you)
  • Professional ($599/mo): 1 team member
  • Business ($999/mo): 2 team members
  • Enterprise ($9,999/mo): Unlimited team members

Invitation Security:

  • Tokens validated on every acceptance attempt
  • Expired invitations automatically rejected
  • One-time use tokens (cannot reuse after acceptance)
  • Email verification prevents unauthorized access
  • Invitation cancellation instantly invalidates tokens

Use Cases:

  • Agencies: Collaborate with clients on their experiments
  • Marketing Teams: Multiple marketers managing A/B tests
  • Product Teams: Engineers, designers, PMs working together
  • Organizations: Each organization maintains separate team structure
  • Multiple Organizations: Enterprise users can create additional organizations and switch between them from the header menu

Multiple Organizations (Enterprise)

Create and switch between independent organizations from one login. Enterprise plans only.

Enterprise accounts can create and switch between multiple organizations. Each organization operates independently with its own sites, experiments, team members, and billing.

How to Create a New Organization:

  1. Open the header menu (top right)
  2. Click your organization name to open the org switcher
  3. Click New organization
  4. Enter a name and press Enter or click Create

How to Switch Organizations:

  1. Open the header menu
  2. Click your current organization name to open the org switcher
  3. Click any organization in the list to switch to it

Each Organization Has Its Own:

  • Sites and experiments
  • Team members and roles
  • Subscription and billing
  • API keys and integrations
  • Analytics data

Common Use Cases:

  • Agencies: Separate organizations per client to keep data isolated
  • Enterprise teams: Different business units with independent billing
  • White-label: Brand-specific organizations for resellers

Available on Enterprise plans only. Non-Enterprise users can still be added as members of Enterprise-owned organizations by their team owners.

Site Configuration

Conversion Rules, event tracking, API keys, and experiment management

Each site has a configuration page where you define how the Segmently snippet detects and tracks events from visitor activity. Conversion Rules are a unified system for tracking conversions, logins, and registrations all in one place.

Conversion Rules

A Conversion Rule fires a named event when a visitor completes a specific action. Each rule has a Name (shown in analytics), an Event Type, and one or more detection conditions.

Event types:

  • Conversion — a purchase, goal completion, or revenue action. Powers conversion rates and winner detection in analytics.
  • Login — a visitor authenticated into an existing account.
  • Registration — a visitor created a new account.

Single Condition vs Multi-step Sequence:

  • Single Condition — rule fires when one detection condition is met. Pick a detection method and enter a value.
  • Multi-step Sequence — rule fires only after the visitor completes multiple steps in order. Each step is its own detection condition evaluated sequentially.

4 detection methods:

  • Page URL — fires when the visitor lands on a specific relative path. Example: /checkout/success, /thank-you, /order-complete
  • URL Parameter — fires when a specific query parameter is present. Example: parameter payment_intent matches ?payment_intent=pi_xxx
  • localStorage Key — reads a value your app writes to browser localStorage. Works with strings and JSON objects. Example key: orderComplete
  • Cookie Name — reads a cookie your server or client sets on completion. Example: order_completed

JSON objects (localStorage and Cookie):

Enable Parse as JSON when the stored value is an object (e.g. {order_id: 123, amount: 99.99}). Use Property Path with dot notation to read nested fields: amount, user.id, cart.items.length. Leave Property Path empty to check existence only.

Test This Condition (URL and URL Parameter only):

Type any URL into the test input on a Page URL or URL Parameter rule and get an instant badge: Would fire or Would not fire. Verify your rules match the exact URLs you expect before saving.

Other Site Settings

  • View and copy your API key (required in the Segmently snippet data-api-key attribute)
  • View all active, paused, and archived experiments for the site
  • Quick status changes: start, pause, archive, reinstate

Subscription & Billing

Stripe integration with full subscription management

Payment Processing:

  • Powered by Stripe (secure, PCI compliant)
  • Credit cards, debit cards, digital wallets
  • Automatic billing on renewal
  • Instant plan activation

Subscription Management:

  • Cancel anytime (access until period end)
  • Annual plan cancellations stop auto-renewal only (no prorated refunds)
  • Reactivate canceled subscriptions
  • View upcoming renewals and amounts
  • Access payment history and invoices

Stripe Customer Portal:

  • Update payment methods securely
  • Download invoices and receipts
  • View billing history
  • Manage subscription details

Plan Changes:

  • Upgrade instantly (prorated billing)
  • Downgrade at period end
  • Limits enforced immediately

Free Tier Branding

Powered by Segmently badge on free accounts

Badge Appearance:

  • Bottom-right corner of client websites
  • Segmently logo with "Powered by Segmently" text
  • Links to segmently.us
  • Small, non-intrusive design

Technical Implementation:

  • Iframe isolation (prevents CSS/JS removal)
  • MutationObserver reattaches if removed
  • All styles use !important (no override)
  • Only shown when subscription_tier === 'free'

Removal:

  • Upgrade to Professional or higher
  • Badge instantly removed from all sites
  • Snippet automatically checks tier on load

Subscription Tiers & Limits

Free, Professional, Business, Enterprise plans, unlimited visitors on all paid plans

Free Tier ($0/mo):

  • Up to 5,000 visitors/month
  • Snippet and project access only (no experiments), 1 site, 1 owner
  • 3 days data retention
  • “Powered by Segmently” badge (required)
  • Community support

Professional ($599/mo):

  • Unlimited visitors
  • 1 experiment, 1 site, 1 team member
  • 7 days data retention
  • Full analytics, funnel goals, Slack notifications
  • No branding, priority support

Business ($999/mo):

  • Unlimited visitors
  • 2 experiments, 1 site, 2 team members
  • 30 days data retention
  • Advanced analytics, GA4/Mixpanel/webhook integrations, REST API

Enterprise ($9,999/mo):

  • Unlimited visitors, experiments, sites, team members
  • 1 year data retention
  • Dedicated account manager, 99.99% SLA, custom webhook integrations

Limit Enforcement:

  • “+ New Site” button disabled when at limit
  • “+ New Experiment” button disabled when at limit
  • “Invite Member” button disabled when at limit
  • Upgrade prompts with tier-specific messaging
  • Badge shows current usage (e.g., “1/1 Sites”)
  • Experiment data is automatically purged after each tier's retention window

Security & Privacy

Enterprise-grade security and GDPR compliance

Authentication:

  • JWT tokens with 30-day expiration
  • Database validation on every request
  • Auto-logout on account suspension/deletion
  • Bcrypt password hashing (cost 10+)

Privacy:

  • No cookies stored on visitor browsers
  • No cross-site tracking
  • GDPR compliant by design
  • Full data ownership

API Security:

  • API key validation on every event
  • Rate limiting per IP address
  • Input sanitization (XSS protection)
  • Disabled accounts = disabled API keys instantly

URL Targeting

Precise control over where experiments run

Match Types:

Exact: https://example.com/pricing
Only matches this exact URL

Contains: /product/
Matches any URL with /product/ anywhere

Starts With: https://example.com/blog/
Matches all blog posts

Ends With: /checkout
Matches any checkout page

Regex: ^https://example\.com/product/[0-9]+$
Advanced pattern matching

Experiments only run on matching URLs - visitors won't be tracked elsewhere

Integrations

Connect Segmently to the tools your team already uses, so experiment data flows automatically into your analytics platform, Slack workspace, or custom systems.

Google Analytics 4 (GA4) Sync

Automatically forward experiment variant data into GA4 so you can segment any metric (revenue, sign-ups, scroll depth) by which variant each visitor saw

GA4 integration requires a Business plan or higher. Configure it inside each experiment under the Integrations tab.

What GA4 sync does

When a visitor is bucketed into a variant, the Segmently snippet fires a gtag('event', 'experiment_impression', …) call into your existing GA4 property, no extra tagging needed. You provide your Measurement ID once, and experiment data flows automatically into GA4 alongside all your existing events.

// Segmently fires this automatically on variant assignment
gtag('event', 'experiment_impression', {
  experiment_id:   'hero-headline-test',
  experiment_name: 'Hero Headline Test',
  variant_id:      'abc123-...',
  variant_name:    'Variant A'
});

How data flows to GA4

👤 Visitor loads your page
⚡️ Segmently snippet runs (synchronous)
🎯 Variant assigned (or recalled from cookie)
✨ Visual changes applied, zero flicker
🔍 Is window.gtag present on the page?
✅ Yes: event fired
📊 GA4 receives event
ReportsExploreBigQuery
⏭ No: skipped silently

Event parameter reference

ParameterTypeExample valueNotes
experiment_idstringhero-headline-testURL-safe slug of your experiment
experiment_namestringHero Headline TestHuman-readable experiment display name
variant_idstringabc123-...UUID of the assigned variant
variant_namestringVariant AHuman-readable variant name (Control, Variant A, etc.)

How it works (under the hood)

  1. Visitor loads your page; the Segmently snippet runs synchronously in <head>.
  2. Snippet checks for a seg_visitor_id cookie → creates a UUID if absent. This ID persists across visits and sessions.
  3. Snippet hashes visitor_id + experiment_id to produce a stable bucket (0–99). Same visitor always gets the same variant.
  4. If the bucket is within the experiment's traffic percentage, the visitor is assigned a weighted variant. Assignment is written to a persistent cookie for future visits.
  5. Visual changes (CSS, DOM, JS) for the assigned variant are applied before the page is revealed, zero flicker guaranteed.
  6. The snippet checks window.gtag. If present, it immediately calls gtag('event', 'experiment_impression', …).
  7. The event appears in GA4 under Reports → Realtime within seconds and in standard reports within 24–48 hours.
Important: GA4 forwarding only fires if window.gtag is initialized before the Segmently snippet runs. Load gtag.js in <head> above the Segmently script tag. Standard GA4 installations do this automatically.

Why connect experiments to GA4?

📊 Segment any GA4 metric by variant

Filter purchases, sign-ups, scroll depth, session duration (every metric GA4 tracks) by which variant was shown. Full business impact beyond a conversion rate.

🔀 Cross-channel attribution

A visitor bucketed Monday and converting Friday via email is still attributed to the correct variant in GA4's user-scoped session model.

💰 Revenue split by variant

On Shopify, WooCommerce, or GA4 Enhanced Ecommerce, see actual revenue per variant: "Variant B drove $4,200 vs $2,700 for Control over 30 days."

👥 Build audiences by variant

Create GA4 Audiences of users who saw a specific variant, then retarget them, exclude them from future tests, or personalize follow-up campaigns.

🗄️ BigQuery deep analysis

GA4-to-BigQuery exports land experiment_impression in raw event tables. Write SQL joining variant with LTV, revenue, or any custom business event.

📈 Dashboard blending

In Looker Studio, blend Segmently analytics with GA4 data on the shared experiment_name dimension for executive-ready dashboards.

Setup (4 steps)

  1. Go to your experiment → Integrations tab.
  2. Enter your GA4 Measurement ID (format: G-XXXXXXXXXX).Find it: GA4 → Admin → Data Streams → your web stream → Measurement ID.
  3. Save. The setting applies to all new visitor sessions immediately.
  4. Verify: GA4 → Reports → Realtime, load your page in a fresh incognito window, check for experiment_impression in the event list.

Register custom dimensions in GA4 (recommended)

Custom event parameters don't appear in standard GA4 reports automatically. Register them so experiment_name and variant_name are available as dimensions everywhere in GA4.

  1. GA4 → Admin → Custom definitions → Custom dimensions → Create custom dimension.
  2. Add all four: experiment_name, variant_name, experiment_id, variant_id, each with Scope: Event and the matching parameter name.
  3. Custom dimensions apply going forward only; they are not retroactively applied to past data.

Free GA4 supports up to 50 event-scoped custom dimensions. GA4 360 supports up to 125.

Build a variant comparison in GA4 Explore

  1. GA4 → Explore → create a new Free Form report.
  2. Dimensions: add experiment_name and variant_name.
  3. Metrics: add your key conversion event (e.g. purchase, sign_up) or session/engagement metrics.
  4. Drag variant_name into the Columns slot for automatic side-by-side comparison.
  5. Add a filter: Event name exactly matches experiment_impression to scope to experiment visitors only.

BigQuery: revenue by variant (SQL example)

If you export GA4 to BigQuery, this query breaks down revenue per variant. Replace the dataset and date range as needed.

SELECT
  ep_variant.value.string_value           AS variant_name,
  COUNT(DISTINCT user_pseudo_id)          AS unique_users,
  ROUND(SUM(ep_revenue.value.double_value), 2)   AS total_revenue,
  ROUND(
    SUM(ep_revenue.value.double_value) /
    NULLIF(COUNT(DISTINCT user_pseudo_id), 0), 2
  )                                       AS revenue_per_user
FROM
  `your_project.analytics_XXXXXXXX.events_*`
  CROSS JOIN UNNEST(event_params) AS ep_variant
  CROSS JOIN UNNEST(event_params) AS ep_revenue
WHERE
  _TABLE_SUFFIX BETWEEN '20260101' AND '20260131'
  AND ep_variant.key = 'variant_name'
  AND ep_revenue.key = 'value'
  AND EXISTS (
    SELECT 1 FROM UNNEST(event_params) ep
    WHERE ep.key = 'experiment_name'
      AND ep.value.string_value = 'Hero Headline Test'
  )
GROUP BY variant_name
ORDER BY total_revenue DESC;

Slack Notifications

Get real-time alerts in Slack when experiments start, reach significance, or when team and billing events occur, at the org level or per experiment

Org-level Slack notifications and per-experiment Slack webhooks are available on the Professional plan and higher. Configure them separately; one governs your whole workspace, the other overrides a single experiment.

Two levels of Slack integration

Org-Level (Recommended)

  • ✅ One webhook URL covers your entire workspace
  • ✅ 15 event types: pick exactly what you want
  • ✅ Covers experiments, projects, team, and billing
  • ✅ Toggle each event type on/off independently
  • ℹ️ Configure at Organization → Features & Integrations

Per-Experiment Override

  • ✅ Different webhook per experiment (e.g. different Slack channel)
  • ✅ Auto-fires on 4 core lifecycle events for that experiment
  • ✅ Bypasses org-level preference checks; fires unconditionally
  • ℹ️ Configure inside each experiment's Integrations tab

Org-level event types (15 total)

experiment.startedAn experiment is launched (status → active)
experiment.pausedAn experiment is paused
experiment.archivedAn experiment is archived
significance.reachedA variant first crosses 95% statistical confidence
experiment.createdA new experiment is created (any status)
experiment.deletedAn experiment is permanently deleted
project.createdA new site is created
project.deletedA site is deleted
member.invitedA team invitation is sent
member.joinedAn invited member accepts and joins
member.removedA member is removed from the team
team.ownership_transferredOwnership is transferred to another member
subscription.upgradedThe org upgrades to a higher plan
subscription.downgradedThe org downgrades to a lower plan
payment.failedA Stripe payment attempt fails

Per-experiment events (always fires when webhook URL set)

  • experiment.started: experiment goes live
  • experiment.paused: experiment is paused
  • experiment.archived: experiment is archived
  • significance.reached: a variant first hits 95% confidence (fires once per experiment lifetime)

The significance message includes the winning variant name, confidence level (e.g. 96.4%), and a direct link to the experiment results page in your dashboard.

How to create a Slack Incoming Webhook

Segmently uses Slack's standard Incoming Webhooks, a simple HTTP endpoint tied to a specific Slack channel. Here's how to create one:

  1. Go to api.slack.com/apps and click Create New AppFrom scratch.
  2. Name the app (e.g. "Segmently Alerts") and choose your Slack workspace.
  3. In the left sidebar, click Incoming Webhooks, then toggle "Activate Incoming Webhooks" to On.
  4. Click Add New Webhook to Workspace, choose the channel you want notifications delivered to (e.g. #ab-testing-alerts), and click Allow.
  5. Copy the Webhook URL; it looks likehttps://hooks.slack.com/services/TXXXXXXXX/BXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX
  6. Paste this URL into Segmently:
    • Org-level: Organization → Features & Integrations → Slack Webhook URL
    • Per-experiment: Experiment → Integrations tab → Slack Webhook URL
  7. Click Test Webhook in Segmently to verify a test message arrives in your Slack channel.

Example Slack messages

significance.reached

🏆 Segmently: Experiment hero-headline-test has a winner! Variant Variant B reached 96.4% confidence. View results →

experiment.started

▶️ Segmently: Experiment pricing-page-cta is now live.

payment.failed

⚠️ Segmently: A payment attempt failed for your subscription. Please update your payment method.

Tips & best practices

  • Create a dedicated Slack channel like #segmently-alerts to avoid noise in general channels.
  • Use different webhook URLs (different channels) for experiment events vs. billing events; you can mix one org-level URL for billing/team events and per-experiment URLs for experiment channels.
  • The significance.reached event fires exactly once per experiment; it will not re-trigger if confidence fluctuates below 95% and comes back up.
  • If you rotate your Slack app or delete the webhook, update the URL in Segmently immediately; stale webhook URLs cause silent delivery failures.
  • Org-level notifications respect each toggle independently, so you can receive only the events that matter to your team. Visit Organization → Features & Integrations to fine-tune.

Outbound Webhooks

POST experiment events to any HTTPS endpoint and connect Segmently to your own systems, CRMs, or CI/CD pipelines

Outbound webhooks require an Enterprise plan. Configure per experiment under the Integrations tab.

Enter any HTTPS endpoint and Segmently will POST a JSON payload whenever the selected event fires for that experiment. Useful for updating a CRM record, logging results to an internal dashboard, triggering a CI/CD step, or sending data to a custom data warehouse.

Subscribed events (per experiment)

  • experiment.started
  • experiment.paused
  • significance.reached

Example payload

{
  "event":           "significance.reached",
  "experiment_id":   "exp_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "experiment_name": "hero-headline-test",
  "variant_id":      "var_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "variant_name":    "Variant B",
  "confidence":      0.964,
  "timestamp":       "2026-03-02T14:23:00Z"
}
  • The endpoint must respond with a 2xx status code within 10 seconds.
  • Segmently makes one delivery attempt; there is no automatic retry on failure.
  • Use a service like webhook.site to inspect payloads during testing.

Mixpanel Integration

Stream experiment impressions into Mixpanel as first-class events, enabling variant-level funnel analysis, cohort retention, and user-level behavioral breakdowns

Mixpanel integration requires a Business plan or higher. Configure it inside each experiment under the Integrations tab.

What Mixpanel integration does

When a visitor is bucketed into an experiment variant, the Segmently snippet calls mixpanel.track('$experiment_started', …) , Mixpanel's standard A/B testing event name, with your experiment and variant details as properties. Because Mixpanel is user-centric (not session-centric like GA4), this event gets attached to the same Mixpanel user profile your site already tracks. You can then break any downstream Mixpanel event (purchases, feature activations, retention milestones) by which experiment variant that user was assigned to.

// Segmently fires this automatically on variant assignment
mixpanel.track('$experiment_started', {
  'Experiment name': 'Hero Headline Test',
  'Experiment ID':   'hero-headline-test',
  'Variant name':    'Variant A',
  'Variant ID':      'abc123-...'
});

The event name $experiment_started uses Mixpanel's reserved prefix ($) for A/B testing events; this makes it compatible with Mixpanel's built-in A/B testing reports and experiments UI if you use Mixpanel Experiments.

How data flows to Mixpanel

👤 Visitor loads your page
⚡️ Segmently snippet runs (synchronous)
🎯 Variant assigned (or recalled from cookie)
✨ Visual changes applied, zero flicker
🔍 Is window.mixpanel present?
✅ Yes: event tracked
📊 Mixpanel receives event
FunnelsCohortsRetention
⏭ No: skipped silently

GA4 vs Mixpanel: Which Integration Should You Use?

CapabilityGA4Mixpanel
Data modelSession-basedUser / event-based
Funnel analysis✅ (Explore)✅ Best-in-class
Cohort retention⚠️ Limited✅ Purpose-built
User-level query⚠️ Via BigQuery only✅ Built into UI
Revenue tracking✅ Enhanced Ecommerce✅ Custom revenue property
Free tier✅ Unlimited hits✅ 20M events/mo free
Best forSEO, ads, revenue, blendingProduct analytics, retention, activation

You can enable both GA4 and Mixpanel for the same experiment; they operate independently and complement each other.

Event property reference

Property nameTypeExample valueNotes
Experiment namestringHero Headline TestHuman-readable display name
Experiment IDstringhero-headline-testURL-safe slug of the experiment
Variant namestringVariant AHuman-readable variant name (Control, Variant A, etc.)
Variant IDstringabc123-...UUID of the assigned variant

How it works (under the hood)

  1. Visitor loads your page; Segmently snippet runs synchronously in <head>.
  2. Snippet checks for a seg_visitor_id cookie → creates a UUID if absent.
  3. Variant is assigned by hashing visitor_id + experiment_id to produce a stable 0–99 bucket. Same visitor always receives the same variant.
  4. Visual changes are applied before the page is revealed (anti-flicker CSS removed only after changes are in place).
  5. The snippet checks window.mixpanel. If the Mixpanel JS SDK is initialized, it calls mixpanel.track('$experiment_started', …).
  6. Mixpanel attaches the event to the identified Mixpanel user (if mixpanel.identify() has been called) or to the anonymous distinct_id for that visitor.
  7. This means variant assignment is tied to a Mixpanel user profile; any future conversion event on that profile can be broken down by Variant name.
Important: window.mixpanel must be initialized before the Segmently snippet runs. Load the Mixpanel JS SDK in <head> above the Segmently script tag and call mixpanel.init('YOUR_TOKEN') before any page logic.

What Mixpanel unlocks for your experiments

🔢 User-level variant breakdown

Mixpanel is user-centric; every downstream event from a user is linked to their experiment assignment. Filter any insight by variant without writing SQL.

🌊 Funnel analysis by variant

Build a funnel (Sign Up → Onboard → Activate → Pay) and instantly compare completion rates between Control and Variant A. Mixpanel shows drop-off at each step per variant.

🔄 Retention by variant

See "did users who saw Variant B return on Day 7 at a higher rate than Control?" Mixpanel Retention charts make this a 5-minute analysis.

🎯 Cohort building

Create a cohort of all users who received "Variant A" in "Hero Headline Test", then run any Mixpanel analysis scoped to only that cohort across any time period.

⚡️ Real-time event stream

Mixpanel's Live View shows each $experiment_started event as it fires, including all experiment properties, for instant verification after saving the integration.

📊 Segmentation in any report

Add "Variant name" as a breakdown dimension in any Mixpanel Insights chart (bar charts, line charts, pie charts) to compare variant performance on any metric.

Setup (4 steps)

  1. Go to your experiment → Integrations tab.
  2. Enter your Mixpanel Project Token.Find it: Mixpanel → Settings (⚙️ top-right) → Project settings → Project token.
  3. Save. The setting applies to all new visitor sessions immediately.
  4. Verify: Mixpanel → Activity Feed or Live View, load your page, and watch for a $experiment_started event appearing in real-time.

Registering variant as a Super Property (optional, recommended)

Super Properties in Mixpanel are key-value pairs that are automatically attached to every future eventthe user fires during that session. Registering the assigned variant as a Super Property means you don't need to filter by $experiment_started first; every downstream event already carries the variant information.

// Add this after your Segmently snippet if you want variant
// attached to every subsequent Mixpanel event automatically.
// window.Segmently.getVariant() returns the variant key for
// the first active experiment, or null if unassigned.

const variant = window.Segmently?.getVariant?.('hero-headline-test');
if (variant) {
  mixpanel.register({
    'AB Test: Hero Headline': variant  // e.g. 'control', 'variant_a'
  });
}

Super Properties persist in the user's browser until mixpanel.unregister() is called. Use descriptive property names (e.g. 'AB Test: Hero Headline') to avoid collisions across multiple experiments.

Build a funnel comparison in Mixpanel

  1. Mixpanel → Funnels → create a new funnel.
  2. Step 1: Event = $experiment_started. Add filter: Experiment name = Hero Headline Test.
  3. Add subsequent steps: your key conversion events (e.g. sign_up, checkout_completed).
  4. Click Breakdown → select Variant name.
  5. Mixpanel will render each variant as a separate bar in the funnel, showing conversion rate at each step per variant.

Create a variant cohort in Mixpanel

  1. Mixpanel → CohortsCreate cohort.
  2. Condition: User did event $experiment_started where Variant name = Variant A.
  3. Save the cohort (e.g. “Hero Test: Variant A”).
  4. Use this cohort as a filter in any Mixpanel Insights, Retention, or Funnel report; instantly scoping that report to only users who saw Variant A.
  5. Create matching cohorts for Control and any other variants to compare them side-by-side.

Retention analysis by variant

  1. Mixpanel → Retention → create a new retention report.
  2. Birth event: $experiment_started (filtered to your experiment name).
  3. Return event: your key engagement/activation event (e.g. session_started, feature_used).
  4. Click BreakdownVariant name.
  5. Mixpanel shows Day 1, Day 7, Day 14, Day 30 retention curves for each variant, revealing which variant drives longer-term engagement, not just first-session conversion.

Heatmaps & Session Recordings

Understand exactly what visitors click, how far they scroll, and where they move, then replay entire sessions to see your site through their eyes.

What Are Heatmaps?

Heatmaps aggregate visitor behaviour across thousands of sessions into a single visual layer overlaid on your page

Every click, scroll, and mouse movement your visitors make is captured by the Segmently snippet and aggregated server-side. The heatmap dashboard renders this data as a colour gradient overlay on top of a screenshot-accurate view of your page. Hot spots (red, orange) show high activity; cold spots (blue, transparent) show low activity.

Heatmaps answer questions that A/B test numbers alone cannot, such as: Are visitors clicking a non-clickable element? Do they ever reach your CTA? Are they reading the pricing section before they leave?

Heatmap types available:

  • Click Heatmap: radial gradient dot for every click recorded
  • Scroll Depth: horizontal bar chart showing what percentage of visitors reached each 5% scroll increment
  • Mouse Moves: density map of cursor movement paths (Business+)
  • Top Elements: ranked table of CSS selectors by total click count

Plan requirements:

FeatureFreeProfessionalBusinessEnterprise
Click HeatmapNoYesYesYes
Scroll DepthNoYesYesYes
Top ElementsNoYesYesYes
Mouse Move HeatmapNoNoYesYes
Session RecordingsNoNoNoYes

Setup: Zero Configuration Required

The Segmently snippet (v1.6.0+) tracks all heatmap events automatically. There is nothing extra to install or configure.

As long as the standard Segmently snippet is on your page and your plan includes heatmaps, tracking begins automatically on every page load. No separate script tag, no extra API calls, no manual initialisation.

What the snippet tracks (based on your plan tier):

  • Clicks: every click on any element, with normalised x/y coordinates relative to the page (0–1 range)
  • Scroll depth: the maximum scroll percentage reached during each page visit (e.g., max_depth: 75 means the visitor scrolled 75% down the page)
  • Mouse moves: sampled every 100ms, normalised coordinates (Business+)
  • Rage clicks: when a visitor clicks the same element 3 or more times within two seconds (signals frustration or confusion)
  • Dead clicks: clicks that land outside of any interactive element (a, button, input, select, textarea, label)
  • Session recordings: full DOM snapshots and mutation events streamed as compressed chunks (Enterprise)

Verify tracking is active:

  1. Open your site in a browser and open DevTools (F12)
  2. Go to the Network tab and filter by batch
  3. Click around your page. You should see POST /api/v1/events/batch requests firing.
  4. In the request payload you will see events with event_name: "heatmap_click", "heatmap_scroll", etc.

Note: The snippet waits until the page is fully loaded before enabling heatmap tracking. This ensures coordinate calculations are accurate and do not conflict with the anti-flicker protection used by A/B experiments.

Click Heatmap

See every place visitors click, with intensity indicating how many clicks each area received

The click heatmap overlays a radial gradient blur on a 900×540 canvas for every recorded click, scaled to the actual page dimensions. Areas that receive many clicks accumulate brighter, larger gradients. The result is an immediate visual understanding of where visitor attention and interaction concentrate.

Using the click heatmap dashboard:

  1. Navigate to Dashboard > Heatmaps from the main navigation
  2. Select your Site from the dropdown
  3. Choose the Page URL you want to analyse (populated from actual click data)
  4. Select a Device filter: Desktop, Mobile, or Tablet
  5. The canvas updates automatically with no reload required.

Rage clicks and dead clicks:

  • Rage click: three or more rapid clicks on the same element. Usually indicates a broken CTA, a slow-loading page, or user frustration. The snippet auto-detects these and sends a separate heatmap_rage_click event.
  • Dead click: a click that lands on a non-interactive element (text, image, blank area). High dead-click rates on a specific area can indicate that visitors expect something to be clickable but it is not.

Reading the intensity scale:

  • Red/orange: very high click density (most popular area)
  • Yellow/green: moderate click density
  • Blue/transparent: low or zero clicks

Data window: The default view shows the last 30 days. Heatmap data is aggregated in daily snapshots by the background scheduler, so new clicks typically appear within a few minutes during active testing periods.

Scroll Depth Heatmap

Discover how far down your pages visitors actually scroll, broken into 5% increments

The scroll depth chart shows what percentage of visitors reached each vertical slice of the page. The snippet records the maximum scroll depth for each page view in the max_depth field. Server-side aggregation then buckets these values into 5% steps (0–5%, 5–10%, …, 95–100%).

How to interpret scroll data:

  • The top bar (0–5%) always shows close to 100%; nearly every visitor sees the very top of the page
  • A sharp drop at a specific depth means visitors are leaving at that point; your content above that fold is not compelling enough to scroll further
  • If your CTA is at 70% depth but only 20% of visitors reach it, that is a structural problem: move the CTA up or add a sticky version
  • A plateau (depth suddenly levels off) often corresponds to a visual break in the page layout; visitors think the page ends there

The fold line:

"Above the fold" typically corresponds to the first 15–25% of page depth (depending on page length). Use scroll data combined with click heatmaps to understand whether key content above the fold is actually driving engagement.

Device filter matters here: Mobile visitors often scroll more than desktop visitors on long-form pages (smaller viewport = more scrolling to see the same content). Always compare Desktop vs Mobile scroll data separately before making layout decisions.

Mouse Move Heatmap (Business+)

A density map of where visitors move their cursor, which correlates strongly with where they are reading

Research consistently shows that mouse movement tracks eye movement with roughly 80–90% correlation on desktop. Where visitors move their cursor is where they are focused. The mouse move heatmap makes this visible as a density gradient overlay.

How it is collected:

  • The snippet samples cursor position every 100ms while the page is active
  • Coordinates are normalised to 0–1 relative to the full page dimensions so data is resolution-independent
  • Samples are batched and sent as heatmap_move events

Using move data alongside click data:

  • Areas with high move density but low click density: visitors are reading that content but not acting on it. Consider adding a CTA near this area.
  • Areas with high click density but low move density: impulse clicks, often from users who already know what they want (return visitors, direct-nav users).
  • Large areas of zero move density: visitors may not be scrolling there at all, or the content is not holding attention.

Business and Enterprise only. Mouse move tracking is not available on Free or Professional plans. If your plan does not include it, the Moves tab will display a plan upgrade prompt.

Top Elements Table

A ranked list of CSS selectors ordered by total click count, giving you a precise breakdown of what visitors click most

The Top Elements tab shows the most-clicked CSS selectors on a given page, sorted by total clicks across all recorded sessions. This is useful when you want a precise answer rather than a visual approximation.

Selector generation:

When a click is recorded, the snippet generates a stable CSS selector for the clicked element. It follows this priority order:

  1. #id if the element has a unique ID
  2. tag.class (tag name plus the first non-dynamic class)
  3. tag[data-attr] (data attribute, if present)
  4. Fallback path using parent chain (up to 3 levels)

Practical uses:

  • Use the top-clicked element selector directly in A/B experiments as a Visual Editor target
  • Identify elements being rage-clicked (check the Rage Clicks column next to each selector)
  • Find elements with unexpectedly high click rates; these are candidates for experiment testing

Filtering tip: Use the Device filter in combination with the URL filter to compare which elements desktop vs mobile visitors click most. Mobile users often interact with completely different elements.

Session Recordings (Enterprise)

Full DOM-accurate playback of individual user sessions, including all clicks, scrolls, form interactions, and navigation events

Session recordings let you watch a replay of exactly what each visitor saw and did on your site, frame by frame. Unlike heatmaps (which aggregate thousands of visitors), recordings show individual journeys, ideal for diagnosing specific UX problems, understanding edge cases, or validating experiment results.

How recordings work:

  1. When a new session starts, the snippet sends POST /api/v1/sessions/start and receives a session_id
  2. The snippet captures a full DOM snapshot plus all subsequent mutations (layout shifts, dynamic content, React/Vue rerenders)
  3. Events are compressed and streamed as chunks to POST /api/v1/events/session-chunk every few seconds
  4. At the end of the session (page unload or 30-minute idle), the session record is finalised with duration and metadata

What is recorded:

  • All mouse movements, clicks, and scroll positions
  • DOM mutations (text changes, element additions/removals, style changes)
  • Form input events (field focus, blur; values are masked by default for privacy)
  • Page navigation and URL changes (supports SPA routing)
  • Viewport size and device type

Privacy and data masking:

All input field values (type="password", type="email", and standard text fields) are masked to *** in the recording stream before transmission. Sensitive content is never sent to Segmently servers.

The Sessions dashboard:

  • Navigate to Dashboard > Sessions
  • Each row shows: session date/time, entry URL, device type, session duration, rage-click count, and whether the visitor converted
  • Filter by site and date range
  • Session playback is rendered directly in the browser, with no plugin or extension required

Enterprise only. Session recordings require the Enterprise plan. The Sessions menu item and all recording endpoints are gated at both the frontend and backend. If your organisation is on a lower tier, the sessions page will display an upgrade option.

Heatmap API Reference

All heatmap and session recording endpoints for integration with custom reporting tools

All endpoints require a valid JWT token in the Authorization: Bearer <token> header, except POST /sessions/start and POST /events/session-chunk which use an API key.

GET /api/v1/heatmap/clicks

Description: Returns normalised click coordinates for a given page.

Query params: project_id (required), url, device_type, days (default 30)

Response: { "data": { "points": [{ "x": 0.45, "y": 0.23, "count": 12 }], "total": 847 } }

GET /api/v1/heatmap/scroll

Description: Returns scroll depth distribution in 5% buckets.

Query params: project_id (required), url, device_type, days

Response: { "data": { "buckets": [{ "depth": 0, "count": 5231 }, { "depth": 5, "count": 4108 }] } }

GET /api/v1/heatmap/moves

Description: Returns normalised mouse movement coordinates. Business+ plan required.

Query params: project_id (required), url, device_type, days

Response: Same shape as /clicks: an array of { x, y, count } points

GET /api/v1/heatmap/elements

Description: Returns top-clicked CSS selectors ranked by click count.

Query params: project_id (required), url, device_type, days

Response: { "data": { "elements": [{ "selector": ".btn-cta", "count": 412 }] } }

GET /api/v1/heatmap/pages

Description: Returns all pages with recorded heatmap activity for a site.

Query params: project_id (required), days

Response: { "data": { "pages": [{ "url": "/pricing", "click_count": 3412, "scroll_count": 9201, "move_count": 18430, "rage_clicks": 23, "last_seen": "2026-04-01T..." }], "tier": "business" } }

POST /api/v1/sessions/start (API key auth)

Description: Starts a new session recording. Enterprise only.

Body: { "visitor_id": "...", "url": "...", "device_type": "desktop" }

Response: { "session_id": "uuid" }

POST /api/v1/events/session-chunk (API key auth)

Description: Streams a chunk of compressed recording events for an active session.

Body: { "session_id": "...", "chunk_index": 0, "events": [...], "duration_ms": 4500 }

Response: 204 No Content

GET /api/v1/sessions (JWT auth, Enterprise)

Description: Lists all sessions for a site.

Query params: project_id (required), days (default 30)

Response: Array of session objects with id, visitor_id, url, device_type, duration_seconds, rage_clicks, converted, started_at

GET /api/v1/sessions/:id (JWT auth, Enterprise)

Description: Returns the full session metadata and all recording chunks for playback.

Response: Session object plus chunks array ordered by chunk_index

Heatmap Troubleshooting

Common issues and how to fix them

No data showing after installation:

  • Confirm your plan includes heatmaps (Professional+). Free accounts see a lock screen.
  • Check the browser Network tab for POST /events/batch requests. If none appear, the snippet may not be loading. Verify the data-api-key attribute on the script tag.
  • Heatmap data is aggregated in batches. New installs may take a few minutes before data first appears in the dashboard.

Coordinates look off / clicks not lining up with the page:

  • Coordinates are normalised (0–1 range) based on the page dimensions at the time of click. The dashboard canvas scales them back to a 900×540 render area. If your page has dynamic height (infinite scroll, lazy-loaded sections), coordinates from early in a session may not match your current page layout.
  • Always use the Device filter to compare desktop vs mobile data separately, as coordinate spaces differ significantly between viewport sizes.

Session recordings missing chunks:

  • Recordings stream in real time. If a visitor closes the tab mid-session, the final chunk may not be transmitted. Shorter sessions with abrupt exits may have incomplete recordings.
  • Verify that your Content Security Policy (CSP) does not block connect-src https://segmently.us, which is required for chunk uploads.

Mouse move tab is locked:

Mouse Move Heatmaps require a Business or Enterprise plan. If you are on Professional or Free, the tab displays a plan upgrade prompt. Upgrade in Settings > Billing to unlock.

Session Recordings

Watch exactly what real visitors did on your site, frame by frame. Every click, scroll, and navigation captured and replayed in your browser.

What Are Session Recordings?

Full DOM-accurate playback of individual visitor sessions, including all interactions, navigations, and layout changes

Session recordings capture a complete, pixel-accurate replay of each visitor's journey through your site. Unlike analytics dashboards that show aggregated numbers, session recordings let you see exactly what one specific person experienced: where they moved their mouse, what they clicked, how far they scrolled, and what page they left on.

They are the single fastest way to diagnose UX problems. If your conversion rate drops after a redesign, watching five real sessions often reveals the issue in minutes.

When to use session recordings:

  • Visitors are leaving a page without converting and you don't know why
  • A form has an unexpectedly high abandonment rate
  • You've just launched a redesign and want to see how real users react
  • A specific experiment variant underperforms and you want to understand the behavioural difference
  • Support cases where a user reports something "not working"

Sessions vs Heatmaps:

HeatmapsSession Recordings
GranularityAggregate (all visitors)Individual (one visitor)
Best forPatterns across thousands of sessionsDiagnosing specific problems
Shows navigationNoYes — full page-to-page flow
Real-timeNear real-timeAvailable after session ends

What the Snippet Records

The Segmently snippet uses rrweb under the hood to capture a complete, compressed stream of every DOM change during a session

Recording is powered by rrweb, the same library used by companies like LogRocket and FullStory. It captures a full DOM snapshot at session start, then records every subsequent mutation as a compact diff — meaning replays are bit-for-bit identical to what the visitor actually saw, even on React, Vue, or other SPA frameworks.

What is captured:

  • Full DOM snapshot at session start (initial page state)
  • Every DOM mutation: text changes, element additions/removals, class/style changes
  • All mouse movements (sampled to reduce data volume)
  • All clicks, including the CSS selector of the clicked element
  • Scroll position updates throughout the page
  • Viewport resize events (device rotation, window resize)
  • Page navigation and URL changes (SPA routing supported)
  • Form input focus and blur events

What is NOT captured:

  • Form field values (all text inputs are masked to *** before transmission)
  • Password or sensitive field content
  • Cross-origin iframes (blocked by browser security)
  • Canvas elements (captured as blank placeholders)
  • Hover intent or eye-tracking (not available without specialised hardware)

Recording limits (to prevent huge files):

Idle cutoff: If a visitor stops all activity (no clicks, scrolls, or mouse moves) for 5 minutes, recording stops automatically. A new recording starts when they become active again.

Hard cap: Any single session is capped at 20 minutes. Longer visits are split into multiple session records, each with its own player entry.

These limits keep session files small and playback fast, preventing accidental 1,000-minute recordings from open browser tabs.

How events are transmitted:

  1. Snippet sends POST /api/v1/sessions/start when a new session begins, receiving a session_id
  2. Events are compressed and batched, then streamed as chunks every few seconds to POST /api/v1/events/session-chunk
  3. When the session ends (page unload, idle cutoff, or hard cap), the record is finalised with total duration and metadata

The Sessions List

Browse, filter, and search all recorded sessions for your site

Navigate to Analytics › Sessions in the main menu. You'll see a table of all recorded sessions for your selected project and date range.

Each row shows:

  • Entry URL: the first page the visitor landed on
  • Device type: desktop, mobile, or tablet
  • Session duration: total active time recorded (idle periods excluded)
  • Started at: date and time the session began

Filtering:

  • Use the site selector dropdown to switch between your projects
  • Use the date range picker to narrow by time period

Click any row to open the full session player for that recording.

The Session Player

A built-in, browser-native video-like player for replaying recordings with full playback controls

The session player is a full-screen-capable replay interface built directly into the dashboard. No plugin, extension, or external tool is needed.

Player layout:

  • Replay viewport: a scaled view of the visitor's browser at the exact resolution they had. The page renders with the same CSS and DOM the visitor saw.
  • Activity timeline: a scrubber bar below the viewport showing the full recording duration. Purple segments mark periods of active user interaction (mouse moves, clicks, scrolls). Gray gaps are idle periods.
  • Controls bar: transport controls centered below the timeline.

Playback controls (left to right):

  • Rewind 10s: jumps back 10 seconds in the recording
  • Play / Pause: starts or pauses playback
  • Forward 10s: jumps forward 10 seconds
  • Skip Idle toggle: when enabled (purple), automatically jumps over idle gaps larger than 2 seconds. Enabled by default. Click to toggle off if you want to see every second including idle time.
  • Speed selector: 1x (normal), 2x, 4x, or 8x playback speed. Higher speeds let you scan long sessions in seconds.

Activity timeline:

  • The scrubber bar can be clicked or dragged to jump to any point in the recording
  • Hovering shows a timestamp tooltip at the cursor position
  • Purple segments = active interaction. Gray = idle.
  • The time display shows active duration / total active time. The denominator is the sum of all purple segments, not wall-clock time. A visitor who was idle for most of a 15-minute visit might have only 2 minutes of active time.

Skip Idle: Automatic Idle Skipping

The player automatically detects and skips over gaps where the visitor had no activity, so you never sit through empty time

When Skip Idle is on (purple button in the controls bar), the player monitors the recording in real time and jumps forward whenever it reaches an idle gap longer than 2 seconds. You only watch the parts of the session where the visitor was actually doing something.

How idle is detected:

The snippet classifies time as active if any of the following events occurred within a 1-second window: mouse movement, click, scroll. Any second with no events is marked idle. In the timeline, idle spans appear as gray gaps between purple active segments.

How Skip Idle works in the player:

  1. The player pre-computes the start and end time of every active segment when the recording loads
  2. During playback, it continuously checks whether the current playhead position is inside an active segment
  3. If the playhead falls outside all active segments (inside a gray gap), and the next active segment is more than 2 seconds away, it instantly jumps the playhead to that next segment
  4. Playback continues from there without interruption

When to turn Skip Idle off:

  • You want to understand pace: how long the visitor actually paused before making a decision
  • You're watching a session where "idle" time might be reading (no mouse movement but active thought)
  • You're debugging a timing-sensitive issue and need the real elapsed time

Click the Skip Idle button in the controls bar to toggle it. The button turns gray when off, purple when on.

Privacy and Data Masking

Segmently is designed to capture behaviour, not personal data. All sensitive content is masked before it leaves the visitor's browser.

Privacy is built in at the capture layer, not added as an opt-in. The following masking happens automatically:

  • All input field values are replaced with *** in the recording stream. This includes type="text", type="email", type="password", type="tel", and textarea elements.
  • Masking happens client-side, before any data is transmitted to Segmently servers. Unmasked values never leave the visitor's device.
  • Mouse movements and clicks are recorded as coordinates only, not element content.
  • Cross-origin content (payment iframes, embedded widgets) cannot be captured by the browser and is shown as a black rectangle.

GDPR and privacy considerations:

Session recordings capture behavioural data tied to a visitor_id (a random UUID stored in a cookie). They do not capture names, emails, or account data unless you explicitly pass those via window.Segmently.setAttributes(). Review your privacy policy to ensure session recording is disclosed to visitors as required by GDPR, CCPA, or your applicable jurisdiction.

Recommendation: Add a cookie consent banner if you haven't already. Segmently respects the segmently_opt_out cookie: if a visitor sets it to true, the snippet will not record their session.

Troubleshooting Sessions

Common issues and how to fix them

Sessions list is empty, but the snippet is installed

Session recording starts on the next page load after the snippet is installed. If you installed the snippet and immediately checked Sessions, wait for a real visitor to browse at least one page. Use the Live view to confirm events are flowing.

Recording stops after a few minutes even though the visitor was still active

This usually means the visitor's activity was classified as idle (no mouse moves, clicks, or scrolls for more than 5 minutes). Encourage scroll or interaction to keep recording active. You can also check the session's activity timeline: if the entire bar is gray, no interaction events were captured.

The player shows a blank / black viewport

This can happen if the initial DOM snapshot was not captured (snippet loaded too late on the page). Make sure the snippet is in the <head> tag, not deferred below the fold. It can also occur if the page is cross-origin or uses CSP headers that block script evaluation.

Sessions are much shorter than expected

Sessions are capped at 20 minutes and cut off after 5 minutes of idle. Long browsing sessions will appear as multiple shorter recordings in the Sessions list. The hard cap prevents runaway recordings from tabs left open overnight.

Skip Idle is skipping too aggressively

Toggle Skip Idle off using the button in the player controls bar to watch the full recording including idle time.

CSS looks wrong in the player

The player reconstructs the DOM from the sequence of mutations recorded. If your site loads fonts or stylesheets from a CDN with strict CORS headers, those resources may not load in the player context. This is a browser security limitation and does not affect the accuracy of the interaction data.

Live Chat Widget

The Segmently Live Chat Widget allows you to engage with your website visitors in real time, answer questions, provide support, and drive conversions. Fully integrated with Segmently's analytics and behavioral targeting, the chat widget is a powerful tool to increase engagement and revenue.

Quick Overview

The Live Chat Widget is a premium feature available on Business and Enterprise plans. It allows your team to communicate directly with visitors on your site without requiring additional third-party software.

Overview & Capabilities

Learn what the Live Chat Widget can do for your business.

The chat widget embeds directly onto any project where the Segmently snippet is installed. It provides a seamless interface for visitors to connect with your support or sales teams.

  • Real-time messaging with visitors.
  • Customizable presentation to match your brand.
  • Visitor context (URL, device, referral source) passed to agents.
  • Integrated directly into the Segmently dashboard inbox.

Enabling the Widget

How to turn on the chat widget for your projects.

To enable the chat widget for a project:

  1. Navigate to Sites > Project Settings.
  2. Select the Chat Widget tab.
  3. Toggle Enable Chat Widget to ON.
  4. Click Save Changes.

Once enabled, the widget will instantly appear on your site for all visitors.

Permissions & Access

Controlling who can answer chats and manage settings.

Chat permissions are tied to your existing team roles:

  • Owners & Admins: Can change widget settings, manage availability, and respond to all conversations.
  • Members: Can view the inbox, claim conversations, and respond to visitors. Cannot alter widget placement or core settings.

Manage your team's access in the Settings > Team section of the dashboard.

Appearance & Customization

Matching the widget to your brand identity.

You can customize the visual presentation of the widget in the Chat Settings:

  • Primary Color: Set the hex code to match your brand's primary button color.
  • Widget Position: Display on the bottom-right or bottom-left of the screen.
  • Launcher Icon: Choose between a classic chat bubble, support icon, or custom image.

Messaging & Copy

Customizing the text inside the chat widget.

All text strings within the widget can be localized or adjusted to fit your tone:

  • Welcome Message: The initial greeting shown when a visitor opens the chat.
  • Offline Message: Displayed when no team members are available to respond.
  • Input Placeholder: The text shown in the typing area (e.g., "Type your message...").

Note: Emojis and em dashes are not supported in copy fields for accessibility and compatibility reasons.

Behavior & Routing

Controlling when the widget appears and who receives messages.

Advanced behavioral settings include:

  • URL Targeting: Restrict the widget to specific pages, such as checkout or pricing pages, to optimize engagement.
  • Business Hours: Automatically switch the widget to offline mode outside of your defined operating hours.
  • Auto-Prompt: Trigger a proactive message when a user remains on a page for a specific duration or scrolls past a certain depth.

Security & Privacy

How data is handled and protected in the chat widget.

Security is paramount:

  • Encryption: All messages are encrypted in transit and at rest.
  • Data Retention: Conforms to your organization's data retention policy.
  • PII Masking: Credit card numbers, Social Security Numbers, and other sensitive patterns can be automatically redacted before being stored.

Canned Responses

Save and reuse your team's most common replies.

Canned responses let you store pre-written replies that any agent can insert instantly while chatting with a visitor. This saves time and ensures consistent, high-quality responses across your team.

Setting up canned responses:

  • Go to Chat Admin in the sidebar and open the Settings tab.
  • Scroll to the Canned Responses section and click + Add reply.
  • Give the reply a descriptive shortcut name (for example, "Pricing question" or "Trial length") and write the reply body.
  • Click Save reply. The reply is stored at the organization level and is immediately available to all agents.

Using canned responses in a conversation:

  • Open any conversation in the Chat Inbox.
  • Type / in the reply box. A floating menu appears showing all saved replies.
  • Continue typing after the slash to filter by title or body text.
  • Use the arrow keys to navigate the list, then press Tab or Enter to insert the selected reply. You can also click any item directly.
  • Press Escape to dismiss the menu without inserting anything.

Canned responses are available on Business and Enterprise plans and are shared across all agents in the organization. You can edit or delete them at any time from Chat Settings.

Performance Impact

How the widget affects your site speed.

The chat widget is designed to be lightweight:

  • Asynchronous Loading: The widget loads after your main page content, ensuring it does not block rendering.
  • Lazy Connection: The WebSocket connection to the server is only established when the user interacts with the widget or an auto-prompt is triggered.
  • Minimal Footprint: The widget code is heavily minified and bundled with the core Segmently snippet.

Technical Reference

JavaScript API

Programmatic integration from your website code

Core Object:

window.Segmently

Available Methods:

// 1) Track custom events
window.Segmently.track('cta_click', {
  section: 'hero',
  label: 'start_free_trial'
});

// 2) Track Revenue (Dashboard Analytics Integration)
// Passing a numeric "revenue" key automatically aggregates in the dashboard
window.Segmently.track('conversion', {
  revenue: 149.99,
  currency: 'USD',
  transaction_id: 'T-12345'
});

// 3) Get assigned variant for an experiment
const variant = window.Segmently.getVariant('homepage-hero-test');

// 4) Get stable anonymous visitor ID
const visitorId = window.Segmently.getVisitorId();

// 5) Attach custom attributes to the current visitor
window.Segmently.setAttributes({
  plan: 'pro',
  country: 'US'
});

// 6) Get all active experiment-to-variant assignments
const assignments = window.Segmently.getAllAssignments();
// Returns: { 'homepage-hero': 'variant_a', 'pricing-test': 'control' }

// 7) Clear visitor identity and all experiment state
window.Segmently.reset(); // Call on logout

Method Behavior:

  • track(eventName, eventData?) sends custom analytics events. Passing {revenue: numeric} inside the eventData object when the event is a conversion will automatically increment the Total Revenue analytics blocks in the Dashboard.
  • getVariant(experimentSlug) returns the assigned variant key or null
  • getVisitorId() returns the persistent anonymous visitor ID
  • setAttributes(attrs) merges custom key-value pairs onto the visitor profile for targeting and event metadata
  • getAllAssignments() returns a plain object mapping every active experiment slug to the visitor's assigned variant key
  • reset() clears visitor identity, all experiment assignments, and custom attributes then generates a fresh visitor ID. Call this on logout.
  • Methods are available after the snippet initializes on the page

Recommended Pattern:

function safeTrack(eventName, data) {
  if (window.Segmently && typeof window.Segmently.track === 'function') {
    window.Segmently.track(eventName, data)
  }
}

REST API Reference

Programmatic endpoints for assignment and tracking

Public API Base URL:

https://segmently.us/api/v1

Always use segmently.us in client integrations. Do not expose internal infrastructure URLs.

Authentication Header:

X-API-Key: seg_live_xxxxx

Assign Visitor to Variant:

POST /api/v1/experiments/:experimentSlug/assign
Content-Type: application/json
X-API-Key: seg_live_xxxxx

{
  "visitor_id": "visitor_123",
  "targeting_data": {
    "url": "https://example.com/pricing",
    "device": "desktop"
  }
}

Track Event:

POST /api/v1/events/track
Content-Type: application/json
X-API-Key: seg_live_xxxxx

{
  "event_name": "conversion",
  "visitor_id": "visitor_123",
  "session_id": "session_abc",
  "experiment_id": "exp_123",
  "variant_id": "var_123",
  "event_data": { "value": 99.99 },
  "device_type": "desktop"
}

Batch Events:

POST /api/v1/events/batch
Content-Type: application/json
X-API-Key: seg_live_xxxxx

{
  "events": [
    {
      "event_name": "scroll_depth",
      "visitor_id": "visitor_123",
      "event_data": { "percent": 75 }
    },
    {
      "event_name": "cta_click",
      "visitor_id": "visitor_123",
      "event_data": { "location": "hero" }
    }
  ]
}

Management API (Enterprise)

Automate experiment control and receive real-time event notifications from your own backend

Management API Keys

Generate long-lived seg_mgmt_* API keys from Settings → API. Use them to authenticate against the Management REST API without exposing your dashboard login credentials.

  • Keys are stored server-side as SHA-256 hashes. The raw key is shown exactly once at creation. Copy it immediately.
  • Up to 10 active management keys per organization
  • Keys can be revoked at any time from Settings. Revocation takes effect on the next request.
  • Enterprise plan required. Only organization owners can create or revoke keys.

Authentication:

# Pass in Authorization header
Authorization: Bearer seg_mgmt_<your-key>

# Or via X-Management-Key header
X-Management-Key: seg_mgmt_<your-key>

REST Management Endpoints

All management endpoints are under /api/v1/manage/ and require a valid management key.

# List all projects
GET /api/v1/manage/projects

# List experiments (optional filter by project)
GET /api/v1/manage/experiments?project_id=<id>

# Get experiment details (full config, visual changes, goals)
GET /api/v1/manage/experiments/:id

# Update experiment status or traffic percentage
PATCH /api/v1/manage/experiments/:id
Content-Type: application/json
{
  "status": "active",       // draft | active | paused | archived
  "traffic_percentage": 50  // 0–100
}

Outbound Webhook Endpoints

Subscribe to Segmently events and receive real-time HTTP POST notifications at your own HTTPS endpoint. Configure from Settings → API.

  • Up to 20 active webhook endpoints per organization
  • HTTPS-only. Private/internal IP addresses are rejected at creation time.
  • Every delivery includes an X-Segmently-Signature: sha256=<hex> header. Verify it on your server to confirm the payload is authentic.
  • Use the Test button in Settings to send a sample payload and confirm your endpoint is reachable.

Supported event types:

experiment.started     experiment.paused      experiment.archived
experiment.created     experiment.deleted     significance.reached
project.created        project.deleted
member.invited         member.joined          member.removed
team.ownership_transferred
subscription.upgraded  subscription.downgraded  payment.failed

Payload format:

{
  "event": "experiment.started",
  "team_id": "<uuid>",
  "timestamp": "2026-03-12T10:00:00Z",
  "data": { ... }  // event-specific fields
}

Signature verification (Node.js example):

const crypto = require('crypto');

function verifySignature(rawBody, secret, signatureHeader) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret)
          .update(rawBody)
          .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

Snippet Verification & QA Playbook

How clients verify project setup, experiments, and tracking end-to-end

1) Install and verify snippet load

<script src="https://segmently.us/segmently.js"
  data-api-key="seg_live_xxxxx"></script>
  • Place in <head> or before </body>
  • Open browser console and confirm no snippet initialization errors
  • Confirm requests are sent to segmently.us/api/v1

2) Verify project linkage

  • Ensure the API key belongs to the correct project in Dashboard
  • Confirm target URL in project settings matches client site domain
  • Use API key regeneration if a compromised key is suspected

3) Verify experiment eligibility

  • Status must be active/live (not draft)
  • URL targeting, device targeting, and geo targeting must match current visitor context
  • Traffic percentage must include enough visitors for validation

4) Verify visual changes and anti-flicker behavior

  • Use preview links to inspect exact variant rendering
  • Validate activation delay timing (0ms / 100ms / 500ms / custom)
  • Check that bucketed users only see final variant state (no flash of original)

5) Verify analytics and events

  • Confirm page_view and custom events appear in analytics
  • Trigger window.Segmently.track(...) and verify payload capture
  • Cross-check visitors, conversions, and variant distribution in experiment analytics

6) Verify tier-based behavior

  • Free tier should display Powered by Segmently badge on client site
  • Paid tiers should not render free-tier branding

Recommended client QA checklist before launch

  • Snippet loads successfully on all key pages
  • Experiment assignment works on desktop + mobile
  • Variant visuals are stable with no flicker
  • Events and conversions are visible in dashboard analytics
  • API key, targeting rules, and traffic settings are correct

How It Works

Technical architecture and methodology

1. Snippet Loading:

  • 9.4kb compressed JavaScript file
  • Served from Vercel Edge Network globally
  • Loads asynchronously (no page blocking)

2. Visitor Assignment:

  • Deterministic hashing: hash(visitor_id + experiment_id)
  • Consistent assignment across sessions (no cookies needed)
  • Traffic percentage enforced at assignment time
  • URL targeting validated before assignment

3. Event Tracking:

  • Batched requests (reduces server load)
  • Stored in PostgreSQL with timestamps
  • JSONB metadata for extensibility

4. Statistical Analysis:

  • Bayesian approximation for significance
  • 95% confidence threshold for winner determination
  • Real-time updates (no batch processing delays)

Current Features (March 2026)

What's available now in Segmently

  • ✅ User account management with full authentication
  • ✅ Project creation and management
  • ✅ Experiment lifecycle controls (start, pause, resume, archive, reinstate)
  • ✅ Real-time analytics dashboard with statistical significance
  • ✅ Event tracking implementation (page views, conversions, bounces)
  • ✅ Visual editor (snippet-based element selection)
  • ✅ Anti-flicker protection with customizable activation delays
  • ✅ Settings tabs (Profile, Security, Team, Notifications, Billing)
  • ✅ Team management (roles, status, ownership transfer)
  • ✅ Stripe billing integration (subscriptions, cancellation, portal)
  • ✅ Free tier branding (removable by upgrading)
  • ✅ Subscription tier enforcement (projects, experiments, team limits)
  • ✅ API key management and regeneration
  • ✅ Secure authentication with real-time validation
  • ✅ Account status & suspension management
  • ✅ Edge-native CDN delivery (<20ms globally)
  • ✅ Privacy-first tracking (no cookies required)
  • ✅ Device targeting (desktop, mobile, tablet)
  • ✅ URL targeting (exact, contains, starts with, ends with, regex)
  • ✅ Traffic percentage control
  • ✅ Pre-push verification (git hooks, npm run verify)
  • ✅ Management API keys (seg_mgmt_*) for backend automation (Enterprise)
  • ✅ REST Management API: list projects, experiments, and update status programmatically (Enterprise)
  • ✅ Outbound webhook endpoints with HMAC-SHA256 signed delivery, 15 event types (Enterprise)
  • ✅ JavaScript SDK: setAttributes(), getAllAssignments(), reset()

Security & Privacy

How we protect your data and your users

Authentication:

  • JWT tokens with 30-day expiration
  • Database validation on EVERY request (not cached)
  • Checks: user exists, account active, permissions current
  • Auto-logout on 401/403/404 responses
  • Bcrypt password hashing (cost 10+)

API Key Validation:

  • Every event validates account status in real-time
  • Suspended/deleted accounts = instantly disabled API keys
  • Rate limiting per IP address (prevents abuse)
  • Input sanitization (XSS protection with html.EscapeString)

Privacy:

  • GDPR Compliant by design
  • No cookies stored on visitor browsers
  • No cross-site tracking
  • Full data ownership (you control everything)
  • Visitor IDs are anonymous hashes

Database Security:

  • Parameterized queries ($1, $2 placeholders)
  • Never concatenate user input into SQL
  • SQL injection pattern detection
  • PostgreSQL on Neon (encrypted at rest)

Team Management Features

Collaborate with roles, permissions, and full control

Available Features:

  • View all team members with real data (name, email, role, status)
  • Role badges: Owner (blue), Admin (purple), Member (gray)
  • Status badges: Active (green), Suspended (red)
  • Three-dot menu for owner actions (on other members)
  • Transfer Ownership → Make another member the owner
  • Suspend/Activate → Toggle member account access
  • Remove Member → Delete from team permanently
  • Seat count display (e.g., "2/2 seats")
  • Upgrade prompts when at team limit

Team Limits Enforced:

  • Free: 1 member (owner only)
  • Professional: 1 member
  • Business: 2 members
  • Enterprise: Unlimited

API Reference

Integrate Segmently into your application

Track Events:POST /api/v1/events/track
Authentication:X-API-Key: seg_live_xxxxx

Best Practices

Get the most out of your A/B tests

Experiment Design:

  • Test one variable at a time (headline OR button color, not both)
  • Start with high-impact changes (not minor tweaks)
  • Make changes big enough to matter

Sample Size:

  • Wait for at least 100 conversions per variant
  • Never end test before 95% confidence
  • Run for minimum 1 week (capture day-of-week patterns)

Success Metrics:

  • Define primary metric before starting (conversion rate, revenue, etc.)
  • Watch for secondary impacts (bounce rate, time on page)
  • Consider long-term vs short-term effects

Documentation:

  • Record hypothesis: "We believe changing X will increase Y because Z"
  • Note start/end dates and traffic volume
  • Document learnings even if test fails
  • Share results with team

Support & Help

Troubleshooting

Common issues and solutions

Snippet Not Loading:

  • Verify snippet in <head> or before </body>
  • Check API key matches your site
  • Look for console errors in browser DevTools
  • Ensure no ad blockers blocking Segmently

Visitors Not Tracked:

  • Check URL matches experiment targeting rules
  • Verify experiment status is "Live" not "Draft"
  • Check traffic percentage (if 10%, only 10% are tracked)
  • Look for API errors in browser console

Visual Editor Not Working:

  • Snippet must be installed on website
  • Look for "Segmently snippet ready" message
  • Check for CORS or security policy blocking iframe
  • Try refreshing the page in visual editor

API Key Issues:

  • Ensure using API key from correct project
  • Check account status (suspended = disabled keys)
  • Regenerate key if compromised

Getting Help

Contact support and community resources

Support Channels:

Response Times:

  • Free: 48 hours
  • Professional/Business: 24 hours
  • Enterprise: 4 hours (priority queue)

Self-Service:

  • Complete documentation (this page)
  • Installation guides for all platforms
  • FAQ section with common questions
  • Updates page with changelog

Need Additional Help?

Can't find what you're looking for? Our support team is ready to assist you.