Docs/Introduction

Introduction

GetFluxly is a customer data platform built around behavior-triggered email. You capture events from your product through a JavaScript SDK or an HTTP API, those events flow onto a unified customer profile, and automations send lifecycle messages through the email provider you already operate.

This page is the 10-minute version. By the end of it, you'll have the SDK installed, an event flowing into your workspace, a profile identified, and an automation triggered on a real event.

Beta access required. The platform is currently in private beta. Request access →

Quickstart

Three steps. Each one is independently useful: if you stop after step 1, you still have analytics; after step 2, you have profiles; after step 3, you have lifecycle email.

Install

The browser SDK ships as @getfluxly/browser on npm. Use either npm (or pnpm / yarn) for bundled apps, or a CDN script tag for static sites.

$ npm install @getfluxly/browser

Bundled apps should call initGFlux directly. Script tag installs read window.__GFLUX__ and boot on DOMContentLoaded. Auto-capture for pageviews, clicks, form submits, and page-leave starts on its own.

Configuration

Pass config to initGFlux before the SDK attaches listeners. The fields below are the common set; the only required one is apiKey.

import { initGFlux } from "@getfluxly/browser";

const gflux = initGFlux({
  apiKey: "gflux_pub_live_your_key",
  apiHost: "https://api.getfluxly.com",
  autocapture: {
    pageviews: true,
    clicks: true,
    forms: true,
    pageLeave: true
  },
  flushIntervalMs: 3000,
  flushQueueSize: 10,
  maxRetries: 3
});

gflux?.page();
OptionTypeDefaultDescription
apiKeystringrequiredYour project's browser API key. Format: gflux_pub_live_….
apiHoststringapi.getfluxly.comOverride for self-hosted or proxied ingest.
autocaptureobjectall onToggle individual auto-capture features.
flushIntervalMsnumber3000How often the queue is flushed to the API, in ms.
flushQueueSizenumber10Flush early when this many events are queued.
maxRetriesnumber3How many times a failed batch is retried.

identify()

Tie the current browser session to a known user. Call this the moment you have a stable user ID, typically right after sign-in or sign-up.

window.gflux?.identify("usr_847", {
  email: "neo@zion.dev",
  plan:  "free",
  name:  "Jane Doe"
});

What happens behind the scenes: Any events captured under the anonymous ID are stitched onto the identified profile. Subsequent events on this device will go to usr_847 directly. Call reset() on logout or account switch before identifying another user.

track()

Send a custom event. Auto-capture handles pageviews, clicks, and form submits; track is for the events that matter to your lifecycle: sign-ups, activations, upgrades, feature uses.

window.gflux?.track("pricing_viewed", {
  plan:   "team",
  source: "nav"
});

window.gflux?.track("subscription_started", {
  plan:         "team",
  amount_cents: 4900,
  trial:        false
});
Naming convention. Use past_tense_snake_case: pricing_viewed, not view_pricing. This makes segment language read naturally: users who did pricing_viewed ≥ 3 times.

reset()

Clear the user identity. Call this on logout so the next visitor on the same browser starts a fresh anonymous session.

window.gflux?.reset();

destroy()

Tear down the SDK, flush any queued events, and remove all browser listeners. Useful in single-page apps that swap analytics tools at runtime.

window.gflux?.destroy();

Node SDK

Backend apps should use @getfluxly/node for lifecycle events like billing webhooks, sign-ups, job completions, and server-side profile stitching.

import { initGFluxNode } from "@getfluxly/node";

const gflux = initGFluxNode({
  token: process.env.GFLUX_SERVER_TOKEN,
  apiHost: "https://api.getfluxly.com"
});

await gflux.track("subscription_started", {
  userId: "usr_847",
  properties: {
    plan: "team",
    amount_cents: 4900
  }
});

await gflux.identify({
  anonymousId: "anon_abc",
  userId: "usr_847",
  traits: {
    plan: "team"
  }
});

Use a gflux_secret_live_… key here. Never ship that key to browser code. identify stitches earlier anonymous activity to the known user, and alias can link anonymous-like IDs from trusted backend workflows.

HTTP Events API · Authentication

Server-side events use the HTTP Events API with a secret server token. Tokens have the format gflux_secret_live_…. Never put a server token in browser code.

POSThttps://api.getfluxly.com/v1/events
curl -X POST https://api.getfluxly.com/v1/events \
  -H "Authorization: Bearer gflux_secret_live_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "subscription_started",
    "external_id": "usr_847",
    "properties": {
      "plan": "team",
      "amount_cents": 4900
    },
    "occurred_at": "2026-05-06T14:32:11Z"
  }'

POST /v1/events

Send a single event. Use this for low-volume server-side workflows (webhooks, billing events). For higher volume, use /v1/events/batch.

FieldTypeRequiredNotes
eventstringyesEvent name. past_tense_snake_case.
external_idstringone ofIdentified user. Either this or anonymous_id.
anonymous_idstringone ofAnonymous session ID, if pre-identify.
propertiesobjectnoUp to 64 keys. Strings, numbers, and booleans only.
occurred_atISO 8601noDefaults to server-receive time.

POST /v1/events/batch

Send up to 50 events in a single request. Recommended for backfills, server-side workers, and any environment where round-trip latency matters. The browser SDK uses this endpoint internally for its periodic flushes.

POSThttps://api.getfluxly.com/v1/events/batch
curl -X POST https://api.getfluxly.com/v1/events/batch \
  -H "Authorization: Bearer gflux_secret_live_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event": "checkout_started",
        "external_id": "usr_847",
        "properties": { "cart_total_cents": 4900 }
      },
      {
        "event": "order_placed",
        "external_id": "usr_847",
        "properties": { "order_id": "ord_456" }
      }
    ]
  }'

Errors and retries

The API uses standard HTTP status codes. 2xx means accepted; 4xx means stop and fix the request; 5xx means retry with exponential backoff. Ingest is at-least-once, so your backend should tolerate duplicate retries after an unknown network outcome.

StatusMeaningRecommended action
202Accepted, queuedNo action needed.
400Bad requestInspect the response body. Do not retry.
401UnauthorizedCheck your server token.
429Rate limitedHonour the Retry-After header.
5xxServer errorRetry with backoff. Use idempotency keys.

Unified profiles

Every event lands on a profile, which is a single record holding a user's identifiers, traits, and the full event timeline. Profiles update in place. There's no nightly rebuild and no "yesterday's view" of who someone is.

Identity stitching

When you call identify(user_id), the SDK posts an identity link. The platform walks any anonymous IDs seen on that device and merges their event history into the identified profile. The merge is deterministic and reversible. Every link is logged and can be inspected (or undone) on the Identity links page in the Console.

Need help with a specific edge case (cross-device login, identity unification across products, anonymous-to-anonymous merges)? Email hello@getfluxly.com. We respond within a business day during beta.