Skip to main content

Persona Detection API

The Persona Detection API allows you to detect user personas and intent independently of the ai12z bot. Use this approach when users are interacting with your website outside the bot or when you need persona detection

Persona Detection API block diagram

before the bot is opened.

When to Use This API​

Use the API approach when:

  • 🌐 Pre-bot personalization - Detect persona before user opens the bot
  • πŸ–₯️ Server-side personalization - Personalize content during page rendering
  • πŸ”„ Custom workflows - Integrate persona detection into your own application logic
  • πŸ“Š Analytics systems - Track user intent across your site
  • πŸ—οΈ CMS integration - Magnolia, Drupal, or other CMS-driven personalization
  • πŸ›οΈ E-commerce flows - Personalize product recommendations outside chat

Use the event-driven approach when:

  • πŸ’¬ Users are actively chatting with the ai12z bot
  • ⚑ You want automatic, real-time persona detection based on bot queries
  • πŸ€– The bot handles all persona analysis automatically

πŸ‘‰ For event-driven persona detection, see Intent + Persona Personalizer


How It Works​

  1. User interacts with your website (clicks, searches, navigates)
  2. Your code collects signals (search queries, button clicks, page views)
  3. You call the API with collected queries and user context
  4. API returns persona with confidence score and suggested actions
  5. You personalize the page based on the detected persona

Unlike the event-driven approach where the bot automatically detects persona during conversations, this API gives you full control over when and how persona detection occurs.


API Endpoint​

POST https://api.ai12z.net/bot/intent_persona

Key Difference from Event-Driven Approach:

  • Event-driven: Bot automatically sends queries to persona engine (no manual API calls needed)
  • API approach: You manually collect user signals and call this endpoint when ready

Authentication​

Include your API key in the request body (not in headers):

{
"apiKey": "your-api-key-here"
}

Request Format​

This API uses the same personaCatalog structure as the event-driven approach, but you control when and how to call it.

Complete Request Example​

Scenario: User searches your site for "car loans" without opening the bot. You want to personalize the page.

{
"apiKey": "f3e358c42bd122a85620e4b60489d196dd1786bd7211114c48613810454774df",
"queries": [
"do you offer car loans",
"what are the rates for auto financing"
],
"clicks": ["cta_view_rates", "link_auto_loans"],
"origin": "https://www.example.com/index.html",
"attributes": {
"personaEnable": true,
"personaCatalog": [
{
"id": "auto_buyer",
"label": "Auto Buyer",
"description": "For auto financingβ€”get prequalified, explore vehicle financing options, and browse next steps.",
"panel": "auto",
"next": [
{ "type": "cta", "id": "get_prequalified" },
{ "type": "cta", "id": "view_auto_financing_options" },
{ "type": "heroImage", "id": "vehicle_marketplace_showcase" },
{ "type": "urlChange", "id": "https://example.com/auto-loans" }
]
},
{
"id": "homeowner_mortgage",
"label": "Homeowner",
"description": "For home buying or mortgage needsβ€”get prequalified, estimate payments, and explore the journey.",
"panel": "mortgage",
"next": [
{ "type": "form", "id": "mortgage_prequalification" },
{ "type": "cta", "id": "calculate_mortgage_payment" },
{ "type": "heroImage", "id": "home_buying_journey" }
]
},
{
"id": "investor",
"label": "Investor",
"description": "For investing goalsβ€”open an account, explore portfolio options, or connect with an advisor.",
"panel": "investing",
"next": [
{ "type": "cta", "id": "open_investment_account" },
{ "type": "heroImage", "id": "investment_portfolio_showcase" },
{ "type": "cta", "id": "talk_to_financial_advisor" }
]
}
],
"initialPersonaId": "general",
"activePersonaId": "general",
"profile": {
"customerId": "123",
"segment": "banking",
"age": 35,
"lifestage": "family"
},
"context": {
"pageType": "banking",
"locale": "en-US",
"origin": "https://www.example.com/index.html"
}
}
}

Request Parameters​

ParameterTypeRequiredDescription
apiKeystringYesYour ai12z API key
queriesarrayYesArray of recent user queries (1-5 recommended)
clicksarrayNoArray of CTA/button IDs user clicked
originstringNoCurrent page URL for context
attributesobjectYesConfiguration object (see below)

Attributes Object​

PropertyTypeRequiredDescription
personaEnablebooleanYesMust be true to activate persona detection
personaCatalogarrayYesArray of persona definitions
initialPersonaIdstringNoInitial persona guess (from CDP/CMS)
activePersonaIdstringNoCurrently active persona
profileobjectNoCustomer profile data (CDP)
contextobjectNoPage/session metadata

Response Format​

Success Response​

{
"requestId": "ip_7c2f1a",
"activePersonaId": "auto_buyer",
"confidence": 0.89,
"personaChanged": true,
"panel": "auto",
"next": [
{ "type": "cta", "id": "get_prequalified" },
{ "type": "cta", "id": "view_auto_financing_options" },
{ "type": "heroImage", "id": "vehicle_marketplace_showcase" },
{ "type": "urlChange", "id": "https://example.com/auto-loans" }
],
"thresholdApplied": false
}

Response Fields​

FieldTypeDescription
requestIdstringUnique identifier for this request
activePersonaIdstringDetected persona ID
confidencenumberConfidence score (0.0 to 1.0)
personaChangedbooleanWhether persona changed from activePersonaId in request
panelstringBot panel to display (from persona catalog)
nextarraySuggested actions based on persona
thresholdAppliedbooleanTrue if confidence was below 0.74 threshold

Low Confidence Response​

When confidence is below the threshold (0.74), the API returns the current active persona without changing it:

{
"requestId": "ip_8d3e2b",
"activePersonaId": "general",
"confidence": 0.62,
"personaChanged": false,
"thresholdApplied": true
}

Client-Side Integration​

Use this when you want to detect persona before users interact with the bot, or based on website navigation patterns.

Use Case: Search Box Persona Detection​

Detect persona as users search your website (not the bot):

// Track searches in your site's search box (not bot queries)
const searchBox = document.querySelector("#site-search")
let searchQueries = []

searchBox.addEventListener("submit", async (e) => {
e.preventDefault()
const query = e.target.querySelector("input").value

searchQueries.push(query)
if (searchQueries.length > 5) searchQueries.shift()

// Execute the search
performSearch(query)

// Detect persona after 2+ searches
if (searchQueries.length >= 2) {
await detectPersona(searchQueries)
}
})

Basic fetch API Implementation​

async function detectPersona(queries, attributes) {
try {
const response = await fetch("https://api.ai12z.net/bot/intent_persona", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
apiKey: "your-api-key",
queries: queries,
origin: window.location.href,
attributes: attributes,
}),
})

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}

const result = await response.json()
console.log("Detected persona:", result)

// Handle the result
handlePersonaDetection(result)

return result
} catch (error) {
console.error("Persona detection failed:", error)
return null
}
}

function handlePersonaDetection(result) {
if (!result.personaChanged) {
console.log("Persona unchanged")
return
}

console.log(`Persona changed to: ${result.activePersonaId}`)
console.log(`Confidence: ${result.confidence}`)
console.log(`Panel: ${result.panel}`)

// Handle suggested actions
result.next?.forEach((action) => {
switch (action.type) {
case "urlChange":
// Navigate to new page
window.location.href = action.id
break
case "cta":
// Show CTA button
showCTA(action.id)
break
case "form":
// Display form
showForm(action.id)
break
case "heroImage":
// Swap hero image
updateHeroImage(action.id)
break
}
})
}

Complete Working Example: Site Search Integration​

This example shows persona detection based on site search (not bot chat):

<!doctype html>
<html>
<head>
<title>Banking Website with Search-Based Persona Detection</title>
</head>
<body>
<h1>Banking Services</h1>

<!-- Site search box (not bot) -->
<form id="site-search">
<input type="text" name="q" placeholder="Search our site..." required />
<button type="submit">Search</button>
</form>

<div id="persona-banner" style="display:none;">
<p>
Based on your interests, we think you might be looking for
<span id="persona-type"></span>
</p>
</div>

<div id="search-results"></div>

<script>
const API_KEY = "your-api-key"
const API_URL = "https://api.ai12z.net/bot/intent_persona"

let searchQueries = []
let detectedPersona = null

const personaCatalog = [
{
id: "auto_buyer",
label: "Auto Buyer",
description: "For auto financing options and vehicle loans.",
panel: "auto",
next: [
{ type: "urlChange", id: "/auto-loans" },
{ type: "cta", id: "get_prequalified" },
],
},
{
id: "homeowner_mortgage",
label: "Homeowner",
description: "For home buying and mortgage needs.",
panel: "mortgage",
next: [
{ type: "urlChange", id: "/mortgages" },
{ type: "form", id: "mortgage_calculator" },
],
},
]

// Handle site search submissions
document
.getElementById("site-search")
.addEventListener("submit", async (e) => {
e.preventDefault()

const query = e.target.q.value.trim()
if (!query) return

// Add to query history
searchQueries.push(query)
if (searchQueries.length > 5) searchQueries.shift()

// Show search results (your existing search logic)
displaySearchResults(query)

// Detect persona after 2+ searches
if (searchQueries.length >= 2) {
await detectPersona()
}
})

async function detectPersona() {
try {
const response = await fetch(API_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
apiKey: API_KEY,
queries: searchQueries,
origin: window.location.href,
attributes: {
personaEnable: true,
personaCatalog: personaCatalog,
initialPersonaId: "general",
activePersonaId: detectedPersona || "general",
profile: { customerId: "123" },
context: { pageType: "search" },
},
}),
})

if (!response.ok) return

const result = await response.json()
handlePersonaResult(result)
} catch (error) {
console.error("Persona detection failed:", error)
}
}

function handlePersonaResult(result) {
if (!result.personaChanged) return

detectedPersona = result.activePersonaId

// Show persona banner
document.getElementById("persona-banner").style.display = "block"
document.getElementById("persona-type").textContent =
result.activePersonaId.replace("_", " ")

// Handle actions
result.next?.forEach((action) => {
if (action.type === "urlChange") {
// Optionally redirect to persona-specific page
console.log("Suggested redirect:", action.id)
// Uncomment to auto-redirect:
// setTimeout(() => window.location.href = action.id, 2000);
}
})

// Track for analytics
trackPersona(result.activePersonaId, result.confidence)
}

function displaySearchResults(query) {
// Your existing search results display logic
document.getElementById("search-results").innerHTML =
`<p>Searching for: ${query}</p>`
}

function trackPersona(personaId, confidence) {
console.log(`Persona: ${personaId}, Confidence: ${confidence}`)
// Add your analytics tracking here
}
</script>
</body>
</html>

Key Points:

  • βœ… Detects persona from site search, not bot chat
  • βœ… Collects 2+ queries before calling API
  • βœ… Optionally redirects to persona-specific pages
  • βœ… Works before user ever opens the bot

Server-Side Integration​

Use server-side detection for pre-rendering personalized content or SSR frameworks.

Node.js Example​

const fetch = require("node-fetch")

async function detectPersona(queries, userProfile) {
const response = await fetch("https://api.ai12z.net/bot/intent_persona", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
apiKey: process.env.AI12Z_API_KEY,
queries: queries,
attributes: {
personaEnable: true,
personaCatalog: getPersonaCatalog(),
profile: userProfile,
context: {
pageType: "banking",
locale: "en-US",
},
},
}),
})

return await response.json()
}

// Use in route handler
app.post("/api/personalize", async (req, res) => {
const { queries, userId } = req.body
const userProfile = await getUserProfile(userId)

const persona = await detectPersona(queries, userProfile)

// Store in session/database
await saveUserPersona(userId, persona.activePersonaId)

res.json({
persona: persona.activePersonaId,
recommendations: getRecommendations(persona),
})
})

Python Example​

import requests
import os

def detect_persona(queries, user_profile):
url = "https://api.ai12z.net/bot/intent_persona"

payload = {
"apiKey": os.getenv("AI12Z_API_KEY"),
"queries": queries,
"attributes": {
"personaEnable": True,
"personaCatalog": get_persona_catalog(),
"profile": user_profile,
"context": {
"pageType": "banking",
"locale": "en-US"
}
}
}

response = requests.post(url, json=payload)
response.raise_for_status()

return response.json()

# Usage example
result = detect_persona(
queries=["do you offer car loans", "what are auto loan rates"],
user_profile={"customerId": "123", "segment": "banking"}
)

print(f"Detected persona: {result['activePersonaId']}")
print(f"Confidence: {result['confidence']}")

Best Practices​

1. Query Collection​

  • Collect 2-5 queries before calling the API for better accuracy
  • Include recent queries only (last 5 minutes recommended)
  • Clean and normalize queries before sending

2. Rate Limiting​

  • Implement cooldown periods (10-15 seconds minimum between calls)
  • Don't call on every keystroke - wait for complete queries
  • Cache results to avoid redundant calls
let lastCallTime = 0
const COOLDOWN = 12000 // 12 seconds

async function detectPersonaWithCooldown(queries, attributes) {
const now = Date.now()
if (now - lastCallTime < COOLDOWN) {
console.log("Cooldown active, skipping call")
return null
}

lastCallTime = now
return await detectPersona(queries, attributes)
}

3. Error Handling​

  • Always implement try-catch for network errors
  • Fallback to default persona on errors
  • Log errors for monitoring
async function safeDetectPersona(queries, attributes) {
try {
const result = await detectPersona(queries, attributes)
return result
} catch (error) {
console.error("Persona detection failed:", error)
// Fallback to default
return {
activePersonaId: attributes.initialPersonaId || "general",
confidence: 0,
personaChanged: false,
}
}
}

4. Privacy & Security​

  • Never send PII (Personally Identifiable Information) in queries
  • Use customer IDs instead of names/emails in profile data
  • Consider encrypting sensitive profile data
  • Comply with GDPR/CCPA requirements

5. Performance Optimization​

  • Call API server-side when possible for faster responses
  • Cache persona results in session storage
  • Use CDN for API endpoints (production)
  • Implement request debouncing

Common Integration Patterns​

Pattern 1: Progressive Enhancement​

Start with a default experience, then enhance based on detected persona:

// Initial page load - default content
showDefaultContent()

// After user interaction - detect and personalize
userQueries.length >= 2 && detectPersona().then(applyPersonalization)

Pattern 2: Real-Time Adaptation​

Continuously adapt as user explores:

let personaScore = {}

async function adaptivePersona(query) {
queryHistory.push(query)

if (queryHistory.length >= 2 && queryHistory.length % 2 === 0) {
const result = await detectPersona()

// Track persona consistency
personaScore[result.activePersonaId] =
(personaScore[result.activePersonaId] || 0) + result.confidence

// Only change if consistently detected
if (personaScore[result.activePersonaId] > 1.5) {
applyPersonalization(result)
}
}
}

Pattern 3: Server-Side Prerendering​

Detect persona server-side and pre-render personalized content:

// Express.js example
app.get("/landing/:persona?", async (req, res) => {
let persona = req.params.persona || "general"

// If no persona in URL, try to detect from query params
if (!req.params.persona && req.query.q) {
const result = await detectPersona([req.query.q], getUserProfile(req))
persona = result.activePersonaId
}

const content = await getPersonalizedContent(persona)
res.render("landing", { persona, content })
})

Troubleshooting​

Issue: Low Confidence Scores​

Symptoms: API always returns confidence below 0.74

Solutions:

  • Ensure personaCatalog includes clear, distinct descriptions
  • Collect more queries (3-5 recommended)
  • Verify queries are substantive (not just "hi", "hello")
  • Check that personas cover the expected user intents

Issue: Wrong Persona Detected​

Symptoms: API detects incorrect persona consistently

Solutions:

  • Review persona descriptions for overlap/ambiguity
  • Add more distinct keywords to descriptions
  • Include context data (page type, user segment)
  • Pass richer profile data from CDP

Issue: API Timeout/Errors​

Symptoms: Requests fail or timeout

Solutions:

  • Check API key validity
  • Verify network connectivity
  • Implement retry logic with exponential backoff
  • Reduce payload size (trim long queries)

Comparison: API vs Event-Driven Approach​

FeatureAPI Approach (this page)Event-Driven (persona.md)
When to useUser interacts with website (not bot)User chats with ai12z bot
TriggerManual API call when readyAutomatic on bot messages
Use casesSearch, navigation, pre-bot personalizationReal-time chat analysis
ImplementationYou call /intent_persona endpointListen to messageReceived event
ControlFull control over timingAutomatic by bot
Query sourceSite search, clicks, navigationBot conversation queries
Best forPre-rendering, SSR, CMS personalizationIn-chat personalization

Example scenarios:

  • Use API: User searches "auto loans" in your site search box β†’ personalize page before they open bot
  • Use Event-driven: User opens bot and asks "do you offer car loans?" β†’ bot automatically detects persona

Both approaches use the same personaCatalog and return the same response structureβ€”the only difference is when and how detection occurs.



Note: The Persona Detection API requires ai12z platform version 2.0 or higher and an active subscription with persona detection enabled. Choose the API approach when you need persona detection before or outside of bot interactions.