The more metadata you attach to each conversation, the more you can filter, segment, and analyze in the dashboard. Start with user and organization data, then layer on session and custom fields as needed.
Every recordMessages call accepts optional metadata objects alongside your messages. These fields power filtering across the OpenBat dashboard — by plan, industry, MRR range, device type, country, or any custom dimension you define.
Attach user information so you can trace conversations back to specific accounts and filter by plan, revenue, or industry.
user: {
id: string, // Your internal user ID
name: string, // Display name
email: string, // Email address
plan: string, // "free" | "pro" | "enterprise" | etc.
createdAt: Date, // Account creation date
industry: string, // User's industry
mrr: number // Monthly recurring revenue in dollars
}
All fields are optional. Pass whichever ones you have available.
When your users belong to teams or companies, attach organization data for account-level filtering.
organization: {
id: string,
name: string,
plan: string,
mrr: number,
industry: string
}
Session fields help you understand where and how conversations happen.
session: {
id: string,
pageUrl: string, // Page where the conversation started
referrer: string, // Referring URL
device: string, // "desktop" | "mobile" | "tablet"
country: string // ISO country code
}
Custom fields
For anything not covered by the built-in fields, use the custom object.
custom: Record<string, string | number | boolean>
Custom fields must match the metadata schema configured in your chatbot’s Settings → Metadata tab. Unknown fields produce a warning in the response but do not fail the request.
Fully enriched example
Here is a complete recordMessages call with all metadata objects populated:
await client.recordMessages({
conversationId: `conv_${userId}_${sessionId}`,
user: {
id: user.id,
name: user.fullName,
email: user.email,
plan: user.subscriptionPlan,
createdAt: user.createdAt,
industry: user.company?.industry,
mrr: user.monthlyRevenue
},
organization: {
id: user.organization.id,
name: user.organization.name,
plan: user.organization.plan,
mrr: user.organization.monthlyRevenue,
industry: user.organization.industry
},
session: {
id: sessionId,
pageUrl: req.headers['referer'],
device: detectDevice(req.headers['user-agent']),
country: req.headers['cf-ipcountry']
},
custom: {
trial_days_remaining: user.trialDaysLeft,
feature_flags: user.activeFeatures.join(","),
account_tier: user.accountTier
},
messages: conversationHistory
});
With this data attached, you can filter conversations in the dashboard by plan, industry, MRR range, device type, country, or any of your custom fields.
When you call recordMessages from a server-side route handler, pass the incoming request headers so OpenBat can automatically detect the user’s country and device type from Cloudflare headers (cf-ipcountry, user-agent).
await client.recordMessages({
conversationId: metadata.conversationId,
user: metadata.user,
messages: conversationHistory,
headers: Object.fromEntries(req.headers)
});
This removes the need to manually populate session.country and session.device — OpenBat extracts them from the forwarded headers on the server side.