@embeddables/analytics
v0.2.0
Published
End-user event tracking SDK for Embeddables funnels and portals.
Keywords
Readme
@embeddables/analytics
TypeScript SDK for sending analytics events from Embeddables applications. It
uses @embeddables/core for
project and user identity.
Install
npm install @embeddables/analytics @embeddables/coreReact applications must also install React 18 or newer.
Client
import { initEmbeddables } from '@embeddables/core'
import { initAnalytics } from '@embeddables/analytics'
const embeddables = initEmbeddables({
projectId: '00000000-0000-4000-8000-000000000001',
publishableKey: 'pk_live_your-key',
forms: [],
experiments: [],
})
const analytics = initAnalytics({ core: embeddables })
await analytics.trackEvent({ event_name: 'page:viewed', page_key: 'intro' })
await analytics.trackEvent({ event_name: 'payment:completed', payment_value: 49 })
await analytics.trackEvent({
event_name: 'payment:failed',
payment_value: 49,
payment_service: 'stripe',
payment_price_id: 'price_123',
payment_promo_code: 'SAVE10',
payment_error_code: 'card_declined',
payment_error_message: 'Your card was declined.',
})The Analytics client uses the current identity from the Core instance, including user changes made after initialization.
In browsers, page:viewed events include available UTM, device, country_code,
and timezone context captured at init time, plus page_url read from
location.href at event time. Explicit values on an event take precedence
over auto-detected ones.
region_name, region_code, and city have no reliable detection method in
the browser, so the SDK never sends them automatically — pass them explicitly
on the event if your app has better location data (for example, from a
shipping address). When omitted, the backend may still fill them in from the
request; if no value is available, they are stored as null. region_name is
the full subdivision name (for example, California) and region_code is its
short code (for example, CA).
country_code follows the same pattern: an ISO 3166-1 alpha-2 code (for
example, US). The backend additionally derives a read-only country_name
(for example, United States) — it cannot be set by the SDK.
The server SDK does not expose page:viewed and therefore does not capture
any of this location context.
Options
| Option | Default | Purpose |
| ---------------- | ----------------------- | ------------------------------------ |
| core | required | Initialized @embeddables/core instance |
| publishableKey | from core | Override the publishable key |
initAnalytics throws if no valid pk_(sandbox|live)_* key is available from
the option or from core.getPublishableKey().
React
Register Analytics through EmbeddablesProvider's modules prop, then use product
hooks from the React subpath.
Example:
import { EmbeddablesProvider } from '@embeddables/core/react'
import {
useTrackClickEvent,
useTrackCustomEvent,
useTrackEvent,
} from '@embeddables/analytics/react'
import { config } from './embeddables/_dist/config.ts'
import { modules } from './embeddables/_dist/modules.ts'
function App({ children }) {
return (
<EmbeddablesProvider
config={config}
publishableKey={import.meta.env.VITE_EMBEDDABLES_PUBLISHABLE_KEY}
modules={modules}
>
{children}
</EmbeddablesProvider>
)
}
function Checkout() {
const { trackEvent, isPending, isError, error } = useTrackEvent()
const { trackClickEvent } = useTrackClickEvent()
const { trackCustomEvent } = useTrackCustomEvent()
const goToCheckout = () => {
// navigate after click is tracked
}
return (
<>
<button
onClick={trackClickEvent({ key: 'buy', callback: goToCheckout })}
disabled={isPending}
>
Buy
</button>
<button
disabled={isPending}
onClick={() => {
void trackEvent({ event_name: 'page:viewed', page_key: 'checkout' })
}}
>
Track page view
</button>
<button
disabled={isPending}
onClick={() => {
void trackCustomEvent({ properties: { key: 'promo_shown' } })
}}
>
Track custom event
</button>
{isError && error instanceof Error ? <p>{error.message}</p> : null}
</>
)
}Example (manual module). Analytics needs no analytics prop — it inherits the
provider's publishableKey:
import { analytics } from '@embeddables/analytics/react'
<EmbeddablesProvider config={config} publishableKey="pk_live_…" modules={[analytics()]}>
{children}
</EmbeddablesProvider>Pass analytics={{ publishableKey }} only to send Analytics somewhere other than
the rest of the SDKs:
<EmbeddablesProvider
config={config}
publishableKey="pk_live_…"
modules={[analytics()]}
analytics={{ publishableKey: 'pk_live_analytics_only_…' }}
>
{children}
</EmbeddablesProvider>- The key resolves as
analytics.publishableKey→publishableKeyon the provider →config.publishableKey. The first one set wins, so most apps set it once on the provider and never pass ananalyticsprop at all. - Analytics is shared with the other SDKs automatically: with
analytics()enabled, Forms and Experiments emit their events without any extra wiring. useTrackEvent(),useTrackClickEvent(), anduseTrackCustomEvent()each return{ track*, isPending, isError, error }.isPendingreflects an in-flight track call, not Analytics initialization. Before Core is ready, track calls resolve as no-ops without throwing.trackClickEvent({ key, callback })returns anonClickhandler that sendsbutton:clicked, then runscallbackonly after a successful track.
For project and user identity, use @embeddables/core/react (useAppUserId,
useEmbeddablesProjectId).
React hooks do not initialize Analytics during server rendering. Use the server entry point directly when tracking from server code.
Server
import { initEmbeddablesServer } from '@embeddables/core/server'
import { initAnalyticsServer } from '@embeddables/analytics/server'
const server = initEmbeddablesServer({
projectId: '00000000-0000-4000-8000-000000000001',
publishableKey: 'pk_live_your-key',
forms: [],
experiments: [],
cookies: { get: (key) => request.cookies.get(key) ?? null },
})
const analytics = initAnalyticsServer({ server })
await analytics.trackEvent({
event_name: 'custom_event:triggered',
properties: { key: 'signup' },
})Server usage accepts the same publishableKey option. It does not capture UTM,
device, or any location context (country, region, city, timezone). trackEvent
is limited to
custom_event:triggered, experiment:assigned, field:updated, data:updated,
payment:completed, and payment:failed (same payment field shapes as the browser client).
Events
Each event_name accepts only its corresponding typed fields. Supported names
include page:viewed, button:clicked,
field:updated, data:updated, form:submitted, payment:completed, payment:failed,
custom_event:triggered, and experiment:assigned.
Timestamps are assigned automatically.
