JavaScript
Ensure you have completed the Prerequisites section before continuing.
Installation
If you're using npm:
npm install @dashx/browser
If you're using yarn:
yarn add @dashx/browser
Configuration
DashX needs to be configured as early as possible in your application:
import DashX from '@dashx/browser'
DashX.configure({
publicKey: '...', // required
targetEnvironment: '...', // required
baseUri: '...', // optional (defaults to https://api.dashx.com/graphql)
realtimeBaseUri: '...', // optional (defaults to wss://realtime.dashx.com)
})
Your Public Key is not sensitive and can be safely included in client-side code. If you use multiple Environments, we recommend using environment variables or build-time configuration to set the targetEnvironment.
Multiple Instances
If you need separate clients (e.g., for different environments or workspaces), use createClient:
import DashX from '@dashx/browser'
const staging = DashX.createClient({
publicKey: '...',
targetEnvironment: 'staging',
})
const production = DashX.createClient({
publicKey: '...',
targetEnvironment: 'production',
})
staging.track('Event A')
production.track('Event B')
createClient returns an independent Client instance. The singleton methods (DashX.track(), etc.) only work with the instance created by DashX.configure().
Usage
All asynchronous methods return Promises and can be used with async/await.
User Management
setIdentity)Mobile native SDKs (iOS / Android): you can set uid without token and still use public features/resources. The second argument is the DashX Identity Token: a JWT from your backend, signed with your workspace private key (see User management). Setting token grants access to your private resources in DashX—treat it as sensitive. Web (@dashx/browser): setIdentity(uid, token) expects both strings; use identify and other public flows when you do not need access to private resources or a JWT.
// Signed-in user + JWT (omit setIdentity or skip the token if you do not need access to private resources)
DashX.setIdentity('user-123', 'your-identity-token')
// Send user attributes
await DashX.identify({
uid: 'user-123',
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com'
})
// Or identify with just a UID
await DashX.identify('user-123')
// Clear identity, generate new anonymous ID, and clean up push state
DashX.reset()
Analytics
DashX.track('Button Clicked', {
label: 'Click here',
placement: 'top'
})
Messaging
Web push notifications require your app to be configured for Firebase Cloud Messaging (FCM). Before proceeding, ensure you have:
- A Firebase project with Cloud Messaging enabled
- Your VAPID key from Firebase Console > Project Settings > Cloud Messaging > Web Push certificates
- A service worker file for handling background notifications (see Background Notifications below)
Push Notifications
import { initializeApp } from 'firebase/app'
import { getMessaging, getToken, deleteToken, onMessage } from 'firebase/messaging'
const firebaseApp = initializeApp({ /* your Firebase config */ })
const fbMessaging = getMessaging(firebaseApp)
// Wrap Firebase's function-based API into the interface DashX expects
const messaging = {
getToken: (options) => getToken(fbMessaging, options),
onMessage: (handler) => onMessage(fbMessaging, handler),
deleteToken: () => deleteToken(fbMessaging),
}
// Subscribe to push notifications
await DashX.subscribe(messaging, { vapidKey: 'your-vapid-key' })
// Unsubscribe from push notifications
await DashX.unsubscribe()
You can optionally pass a serviceWorkerRegistration if you manage your own service worker:
const registration = await navigator.serviceWorker.register('/firebase-messaging-sw.js')
await DashX.subscribe(messaging, {
vapidKey: 'your-vapid-key',
serviceWorkerRegistration: registration,
})
subscribe() automatically requests notification permission if not already granted.
Foreground Notifications
When the app is in the foreground, push notifications are delivered to your callback instead of being shown as system notifications:
const unsubscribe = DashX.onPushNotificationReceived((payload) => {
console.log(payload)
// payload: { id, title, body, image, url }
})
// Later, to stop listening:
unsubscribe()
Background Notifications (Service Worker)
Create a firebase-messaging-sw.js file in your public directory to handle notifications when the app is in the background:
importScripts('https://www.gstatic.com/firebasejs/10.14.1/firebase-app-compat.js')
importScripts('https://www.gstatic.com/firebasejs/10.14.1/firebase-messaging-compat.js')
firebase.initializeApp({
// your Firebase config
})
const messaging = firebase.messaging()
// Import DashX service worker helper
// Copy from node_modules/@dashx/browser/dist/sw-helper.umd.js to your public directory
importScripts('./dashx-sw-helper.umd.js')
const dashx = createDashXServiceWorkerHandler({
publicKey: 'your-public-key',
targetEnvironment: 'production',
})
messaging.onBackgroundMessage((payload) => dashx.onBackgroundMessage(payload, self.registration))
self.addEventListener('notificationclick', (event) => dashx.onNotificationClick(event, self.clients))
self.addEventListener('notificationclose', (event) => dashx.onNotificationClose(event))
The service worker helper automatically:
- Displays a browser notification with the title, body, and image from the DashX payload
- Tracks DELIVERED when the notification arrives
- Tracks CLICKED when the user clicks the notification (and opens the URL if provided)
- Tracks DISMISSED when the user dismisses the notification
If you prefer to handle background messages manually without the helper:
messaging.onBackgroundMessage((payload) => {
const data = JSON.parse(payload.data.dashx)
self.registration.showNotification(data.title, {
body: data.body,
icon: data.image,
data: { url: data.url },
})
})
Notification tracking (DELIVERED, CLICKED, DISMISSED) is handled automatically — by the service worker helper for background notifications, and by onPushNotificationReceived for foreground notifications.
In-App Notifications
For real-time in-app notifications via WebSocket:
// Connect to the real-time WebSocket
DashX.connectWebSocket()
// Fetch existing notifications (populates cache)
await DashX.fetchInAppNotifications()
// Watch for notification list updates in real-time
const unwatch = DashX.watchFetchInAppNotifications((notifications) => {
console.log(notifications) // Array of { id, sentAt, readAt, renderedContent }
})
// Watch unread count
const unwatchCount = DashX.watchFetchInAppNotificationsAggregate((count) => {
console.log('Unread:', count)
})
// Register a callback for incoming notifications
const off = DashX.onNotification((notification) => {
console.log('New notification:', notification)
})
// Clean up
unwatch()
unwatchCount()
off()
DashX.disconnectWebSocket()
User Preferences
// Stored preferences need an identified user: call setIdentity with uid + JWT when private resources require it (see User Management above)
const preferences = await DashX.fetchStoredPreferences()
// Save preferences
await DashX.saveStoredPreferences({ push: true, email: false })
Contact Management
// Fetch user's contact channels
const contacts = await DashX.fetchContacts()
// Save contacts
await DashX.saveContacts([
{ kind: 'EMAIL', value: 'john@example.com' },
{ kind: 'PHONE', value: '+1234567890', tag: 'PRIMARY' },
])
CMS
const record = await DashX.fetchRecord('blog/welcome', {
language: 'en_US',
preview: true,
})
fetchRecord accepts the following optional arguments:
| Name | Type | Example |
|---|---|---|
preview | boolean | true |
language | string | "en_US" |
fields | object[] | |
include | object[] | |
exclude | object[] |
const records = await DashX.searchRecords('blog', {
filter: { status: 'published' },
order: [{ created_at: 'DESC' }],
limit: 10,
language: 'en_US',
preview: true,
})
searchRecords also supports a fluent builder pattern:
const records = await DashX.searchRecords('blog')
.filter({ status: 'published' })
.order({ created_at: 'DESC' })
.limit(10)
.language('en_US')
.preview(true)
.all()
searchRecords accepts the following optional arguments:
| Name | Type | Example |
|---|---|---|
filter | object | { status: 'published' } |
order | object[] | [{ created_at: 'DESC' }] |
limit | number | 10 |
page | number | 1 |
preview | boolean | true |
language | string | "en_US" |
fields | object[] | |
include | object[] | |
exclude | object[] |
Assets
const asset = await DashX.upload({
file: fileInput.files[0], // a File object
resource: 'users',
attribute: 'avatar',
})
console.log(asset.url)
Asset uploads are automatically polled for completion (5 retries, 3 s interval).
Cart
// Add item to cart
const cart = await DashX.addItemToCart({
itemId: 'item-uuid',
pricingId: 'pricing-uuid',
quantity: '1',
reset: false,
})
// Apply a coupon
await DashX.applyCouponToCart({ couponCode: 'SAVE20' })
// Remove a coupon
await DashX.removeCouponFromCart({ couponCode: 'SAVE20' })
// Fetch cart
const cart = await DashX.fetchCart({})
// Transfer anonymous cart to identified user
await DashX.transferCart({})
AI Agent
// Load agent configuration
const agent = await DashX.loadAiAgent({ publicEmbedKey: 'your-embed-key' })
// Invoke agent
const response = await DashX.invokeAiAgent({
publicEmbedKey: 'your-embed-key',
prompt: 'How can I reset my password?',
conversationId: 'optional-conversation-id', // for multi-turn conversations
})