Skip to main content

Conversation Metadata

Operational metrics that provide context about conversational interactions, included in every bid request.

Overview

Conversation metadata provides AI/ML-powered analytics for conversational interactions. This metadata combines operational metrics and AI-powered insights, included in OpenRTB bid requests via the BidRequest.ext.aura field.

Data Flow

Metadata Categories

Metric CategoryPurpose
Conversation trackingSession management, sequence tracking
Message characteristicsLength, timing, input method
Intent analysisCampaign targeting
Sentiment analysisTone matching
Funnel stageBid optimization
Audience signalsInterest/behavior targeting

Conversation Metrics

These operational metrics are included in every bid request:

FieldTypeRequiredDescriptionExample
messageSequenceNumberintegerYesPosition in conversation, 1-indexed3
messageLengthintegerYesCharacter count of user message45
isQuickReplybooleanYesWhether message was a quick reply vs typedfalse
userThinkTimeMsintegerNoTime in ms between last assistant message and user message2500
sessionDurationMsintegerYesTotal elapsed time in ms since session start45000

messageSequenceNumber

Position of the current message in the conversation sequence.

Type: integer
Required: Yes
Range: 1 to N (1-indexed)

Example:

{
"messageSequenceNumber": 3
}

Use Cases:

  • Track conversation depth
  • Identify early vs late-stage conversations
  • Optimize bid strategies based on engagement level

messageLength

Character count of the user's message.

Type: integer
Required: Yes
Range: 0 to N

Example:

{
"messageLength": 45
}

Use Cases:

  • Gauge user engagement level
  • Identify detailed inquiries vs quick questions
  • Adjust creative length to match user input style

isQuickReply

Indicates whether the message was a quick reply (button/suggestion) or typed by the user.

Type: boolean
Required: Yes

Example:

{
"isQuickReply": false
}

Use Cases:

  • Distinguish between guided and organic interactions
  • Identify user engagement patterns
  • Optimize for different interaction styles

userThinkTimeMs

Time in milliseconds between the last assistant message and the user's response.

Type: integer
Required: No
Range: 0 to N

Example:

{
"userThinkTimeMs": 2500
}

Use Cases:

  • Measure user consideration time
  • Identify thoughtful vs impulsive responses
  • Optimize timing for follow-up messages

Note: May not be available for the first message in a conversation.

sessionDurationMs

Total elapsed time in milliseconds since the conversation session started.

Type: integer
Required: Yes
Range: 0 to N

Example:

{
"sessionDurationMs": 45000
}

Use Cases:

  • Track overall session engagement
  • Identify long vs short sessions
  • Optimize bid strategies for session depth

Request Structure

Conversation metadata is included in BidRequest.ext.aura:

{
"id": "bid-request-123",
"imp": [...],
"site": {...},
"user": {...},
"ext": {
"aura": {
"messageSequenceNumber": 5,
"messageLength": 32,
"isQuickReply": false,
"userThinkTimeMs": 3200,
"sessionDurationMs": 67000
}
}
}

Complete Example

{
"id": "bid-req-20250104-001",
"imp": [
{
"id": "imp-1",
"native": {
"request": "{\"native\":{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":80}}]}}"
}
}
],
"site": {
"id": "site-123",
"domain": "aiplatform.com"
},
"ext": {
"aura": {
"messageSequenceNumber": 3,
"messageLength": 45,
"isQuickReply": false,
"userThinkTimeMs": 2500,
"sessionDurationMs": 45000,
"intent": {
"value": "purchase_inquiry",
"confidence": 0.85,
"topics": ["family travel", "outdoor activities"],
"signals": ["asked_about_options"]
},
"sentiment": {
"value": "positive",
"score": 0.8
}
}
}
}

Publisher Implementation

Calculating Metrics

class ConversationMetrics {
constructor() {
this.sessionStartTime = Date.now()
this.messageCount = 0
this.lastAssistantMessageTime = null
}

calculateMetrics(userMessage, isQuickReply) {
this.messageCount++

const now = Date.now()
const metrics = {
messageSequenceNumber: this.messageCount,
messageLength: userMessage.length,
isQuickReply: isQuickReply,
sessionDurationMs: now - this.sessionStartTime,
}

// Add think time if we have a previous assistant message
if (this.lastAssistantMessageTime) {
metrics.userThinkTimeMs = now - this.lastAssistantMessageTime
}

return metrics
}

recordAssistantMessage() {
this.lastAssistantMessageTime = Date.now()
}
}

Usage Example

const conversation = new ConversationMetrics()

// User sends first message
const metrics1 = conversation.calculateMetrics('Hello, I need help', false)
// { messageSequenceNumber: 1, messageLength: 20, isQuickReply: false, sessionDurationMs: 100 }

// Assistant responds
conversation.recordAssistantMessage()

// User sends second message after 2.5 seconds
const metrics2 = conversation.calculateMetrics('Tell me more', false)
// { messageSequenceNumber: 2, messageLength: 13, isQuickReply: false, userThinkTimeMs: 2500, sessionDurationMs: 2600 }

Best Practices

1. Track Session Start Time

Always track when the session starts:

const sessionStartTime = Date.now()

2. Handle Quick Replies Correctly

Distinguish between typed and quick reply messages:

function isQuickReply(message) {
return message.source === 'button' || message.source === 'suggestion'
}

3. Calculate Think Time Accurately

Only include think time when there's a previous assistant message:

if (lastAssistantMessageTime) {
metrics.userThinkTimeMs = Date.now() - lastAssistantMessageTime
}

4. Reset on New Session

Reset metrics when starting a new conversation:

function startNewSession() {
conversation = new ConversationMetrics()
}

Use Cases

Early vs Late Stage Targeting

function getBidModifier(metrics) {
if (metrics.messageSequenceNumber <= 2) {
return 1.0 // Early stage - awareness
} else if (metrics.messageSequenceNumber <= 5) {
return 1.2 // Mid stage - consideration
} else {
return 1.5 // Late stage - intent
}
}

Engagement Level Detection

function getEngagementLevel(metrics) {
const avgMessageLength = 30
const avgThinkTime = 3000

if (
metrics.messageLength > avgMessageLength * 1.5 &&
metrics.userThinkTimeMs > avgThinkTime
) {
return 'high' // Detailed, thoughtful responses
} else if (metrics.isQuickReply) {
return 'low' // Quick, guided responses
} else {
return 'medium'
}
}

Session Depth Optimization

function shouldShowAd(metrics) {
// Don't show ads in very short sessions
if (metrics.sessionDurationMs < 10000) {
return false
}

// Show ads after sufficient engagement
if (metrics.messageSequenceNumber >= 3) {
return true
}

return false
}

Next Steps