Sign inGet started

Chat widget attributes

Chat Widget Attributes

When using the Bird Chat Widget, you can pass contextual data into conversations using two different mechanisms:
  • Contact Attributes — update the Contact Profile in BirdCRM (persistent across sessions)
  • Conversation Attributes — attach metadata to a specific conversation (per-conversation)

Contact Attributes (via Bird Web SDK)

Contact attributes update the CRM profile for the identified contact. These persist across conversations and sessions.
Codevoorbeeld
// First, identify the contact
await Bird.contact.identify({
  strategy: 'SignedIdentityClaims',
  signedIdentity: signedIdentity,
});

// Then update their profile
await Bird.contact.putAttributes({
  displayName: 'Jane Smith',
});
Contact attributes are visible in the Contact Profile UI and can be used in:
  • Journeys: Access via {{run.contact.attributes.<key>}}
  • Flows: Use a "Fetch Contact" step, then access contact fields
  • Audience segmentation: Filter contacts by attribute values

Supported Attributes

AttributeTypeDescription
displayNamestringContact's display name shown in CRM
Custom keysanyAny key-value pair stored as a contact attribute

Conversation Attributes (via Chat Widget API)

Conversation attributes attach metadata to the next conversation created through the chat widget. They are session-specific and do not persist on the contact record.
Codevoorbeeld
window.mbchat.setAttributes({
  currentPage: window.location.pathname,
  userPlan: 'premium',
  cartValue: '149.99',
  referrer: document.referrer,
});
These attributes are:
  • Sent automatically when the visitor creates a new conversation
  • Stored on the conversation record
  • Visible to agents in the conversation details
  • Accessible in Flows via a Get Conversation step (not directly on the trigger)
  • Not persisted on the Contact Profile

When to Use Each

Data TypeUseAPI
User identity (name, email)Contact AttributesBird.contact.putAttributes()
Subscription tier, account infoContact AttributesBird.contact.putAttributes()
Current page, referrer, UTM paramsConversation Attributeswindow.mbchat.setAttributes()
Cart value, product being viewedConversation Attributeswindow.mbchat.setAttributes()

Complete Example

Here is the recommended integration pattern for a logged-in user:
Codevoorbeeld
<script
  src="https://embeddables.p.mbirdcdn.net/sdk/v0/bird-sdk.js"
  data-config-url="YOUR_CONFIG_URL"
></script>

<script>
async function initBirdChat(user) {
  // 1. Get signed identity from your authenticated backend
  //    Your backend verifies the user's session and generates the JWT
  //    using their email/ID from YOUR database — not from client input
  const resp = await fetch('/api/bird-identity', {
    method: 'POST',
    credentials: 'include', // sends session cookies for authentication
  });
  const { signedIdentity } = await resp.json();

  // 2. Identify the contact (links to CRM record)
  await Bird.contact.identify({
    strategy: 'SignedIdentityClaims',
    signedIdentity,
  });

  // 3. Update contact profile (persistent)
  await Bird.contact.putAttributes({
    displayName: user.fullName,
  });

  // 4. Set conversation context (per-conversation)
  window.mbchat.setAttributes({
    currentPage: window.location.pathname,
    plan: user.plan,
  });
}
</script>

Anonymous Visitors

For visitors who haven't logged in, you can still pass conversation context:
Codevoorbeeld
// No signed identity needed — SDK auto-identifies as Visitor
window.mbchat.setAttributes({
  landingPage: document.referrer,
  currentPage: window.location.pathname,
  utm_source: new URLSearchParams(window.location.search).get('utm_source'),
  utm_campaign: new URLSearchParams(window.location.search).get('utm_campaign'),
});
You can optionally set a display name on the anonymous contact:
Codevoorbeeld
await Bird.contact.identify({ strategy: 'Visitor' });
await Bird.contact.putAttributes({ displayName: 'Website Visitor' });
Note: If the visitor later logs in and is identified with Signed Identity, Bird will link them to their real CRM record. The anonymous contact's attributes do not automatically transfer to the verified contact.

Visitor Logs In Mid-Session

If a visitor starts chatting anonymously and then logs in:
Codevoorbeeld
async function onUserLogin(user) {
  // Get signed identity from your authenticated backend
  // The backend verifies the login and looks up identifiers from its own records
  const { signedIdentity } = await fetch('/api/bird-identity', {
    method: 'POST',
    credentials: 'include',
  }).then(r => r.json());

  // Re-identify — links contact to real CRM record
  await Bird.contact.identify({
    strategy: 'SignedIdentityClaims',
    signedIdentity,
  });

  // Update the real contact profile
  await Bird.contact.putAttributes({
    displayName: user.fullName,
  });

  // Update conversation context for the next conversation
  window.mbchat.setAttributes({
    plan: user.plan,
    authenticated: 'true',
  });
}
Important: The conversation that was already in progress keeps its original attributes. New setAttributes() values apply to the next conversation created.

Accessing Attributes in Flows

Both conversation attributes and contact profile data require an explicit step in your Flow to retrieve them.
Attribute SourceFlow Step RequiredThen Access Via
Conversation attributesGet Conversation stepconversation.attributes.<key> (e.g. conversation.attributes.userPlan)
Contact profileFetch Contact stepcontact.displayName, contact.attributes.<key>

Example: Get Conversation step output

After adding a Get Conversation step to your Flow, the conversation attributes are available in the result:
Codevoorbeeld
{
  "attributes": {
    "currentPage": "https://example.com/pricing",
    "userPlan": "premium",
    "userEmail": "demo@example.com",
    "source": "support-page"
  },
  "featuredParticipants": [
    {
      "displayName": "Demo User",
      "type": "contact"
    }
  ]
}
Note: The trigger payload contains the conversationId and contactId, but not the full attribute data. Use a Get Conversation or Fetch Contact step to retrieve the details you need.

Signed Identity

Signed Identity is the recommended way to identify contacts in production. It uses a JWT signed by your backend server, ensuring that only your server can assert a visitor's identity.
Security: Always authenticate the user first. Your backend must verify the user's identity (e.g. validate their session token, check their login credentials) before generating a Signed Identity JWT. The signing key should never be exposed to the client. If your endpoint issues JWTs without authentication, any visitor could impersonate any contact.

Setup

To generate signed identities, you need the Signing Key and Issuer from your Bird dashboard:
  1. Go to Developer > Applications
  2. Select your application
  3. Find the Identity Signing Key section on the Overview tab
  4. Store the signing key securely on your backend (e.g. environment variable or secrets manager) -- never expose it in client-side code

Backend Implementation

Your backend endpoint should:
  1. Authenticate the request -- verify the user is who they claim to be (session token, cookie, OAuth token, etc.)
  2. Generate identifiers from your own records -- do not trust identifiers sent from the client
  3. Sign and return the JWT
Codevoorbeeld
const crypto = require('crypto');

const ISSUER = process.env.BIRD_ISSUER;
const SIGNING_KEY = process.env.BIRD_SIGNING_KEY;

function makeSignedIdentity(identifiers) {
  const header = JSON.stringify({ alg: 'HS256', typ: 'JWT', kid: ISSUER });
  const payload = JSON.stringify({ identifiers });

  const headerB64 = Buffer.from(header).toString('base64url');
  const payloadB64 = Buffer.from(payload).toString('base64url');

  const signature = crypto
    .createHmac('sha256', SIGNING_KEY)
    .update(`${headerB64}.${payloadB64}`)
    .digest('base64url');

  return `${headerB64}.${payloadB64}.${signature}`;
}

// Express example
app.post('/api/bird-identity', async (req, res) => {
  // Step 1: Authenticate the user using YOUR session/auth system
  const user = await getUserFromSession(req);
  if (!user) {
    return res.status(401).json({ error: 'Not authenticated' });
  }

  // Step 2: Build identifiers from your own trusted user record
  // DO NOT use identifiers sent from the client request body
  const signedIdentity = makeSignedIdentity([
    { key: 'emailaddress', value: user.email },
    { key: 'externalid', value: user.id },
  ]);

  // Step 3: Return the signed JWT
  res.json({ signedIdentity });
});

Client-Side Usage

Codevoorbeeld
async function identifyWithBird() {
  // Call YOUR authenticated backend endpoint
  const resp = await fetch('/api/bird-identity', {
    method: 'POST',
    credentials: 'include', // sends session cookies
  });

  if (!resp.ok) throw new Error('Not authenticated');

  const { signedIdentity } = await resp.json();

  // Pass the server-signed JWT to Bird
  await Bird.contact.identify({
    strategy: 'SignedIdentityClaims',
    signedIdentity,
  });
}
For more details, see Signed Identity.

API Reference

Bird.contact.putAttributes(attributes)

Updates the Contact Profile in BirdCRM.
ParameterTypeDescription
attributesRecord<string, any>Key-value pairs to set on the contact
Returns Promise<ContactResponse>.

Bird.contact.identify(claim)

Identifies the current visitor as a contact.
ParameterTypeDescription
claim.strategy'Visitor' | 'SignedIdentityClaims'Identification strategy
claim.signedIdentitystringJWT from your backend (for SignedIdentityClaims)
claim.identifier{ key: string, value: string }Optional identifier (for Visitor)
Returns Promise<{ contactId: string, accessToken: string }>.

Bird.contact.getCurrent()

Returns the current contact's profile data.
Returns Promise<ContactResponse>.

Bird.contact.reset(options?)

Resets the current session and generates a new anonymous ID.

window.mbchat.setAttributes(attributes)

Sets conversation-level attributes on the chat widget.
ParameterTypeDescription
attributesRecord<string, string>Key-value pairs attached to the next conversation
These are sent when a new conversation is created through the widget.