Context & Automatic Data
Rich context data automatically captured + beautiful user/org display đ¨
WhatIf automatically captures rich context data with every response, and you can enhance it with user and organization information for beautiful dashboard displays.
Automatic Data Collection
Every response automatically includes the following context data - no code required:
đ Timestamp
- ISO timestamp of when the response was submitted
- Used for accurate date filtering and analytics
đ Browser Information
{
"browser": {
"userAgent": "Mozilla/5.0...",
"language": "en-US",
"languages": ["en-US", "en"],
"platform": "MacIntel"
}
}đą Device Information
{
"device": {
"type": "desktop" | "mobile" | "tablet",
"platform": "MacIntel" | "iPhone" | "iPad" | "Win32"
}
}đ Page Information
{
"page": {
"url": "https://app.example.com/checkout",
"title": "Checkout - My App",
"pathname": "/checkout",
"search": "?step=2",
"hash": "#payment"
}
}đ Previous URL
- Automatically captures the referrer or previous page URL
- Helps track user navigation flow
Beautiful User Display
Add user context to display beautiful user cards in your dashboard with avatars, names, and emails.
Basic User Context
whatif.ask('question-id', {
user: {
id: "user_123", // Required for smart filtering
name: "Sarah Chen", // Optional - for dashboard display
email: "sarah@example.com", // Optional - for dashboard display
avatar: "https://example.com/avatar.jpg" // Optional - for dashboard display
},
context: {
page: "checkout", // Custom metadata
feature: "new-payment"
}
});In React
import { useWhatIf } from '@twenty1tools/whatif';
function FeedbackButton() {
const { ask } = useWhatIf();
const user = useCurrentUser(); // Your auth hook
const handleFeedback = () => {
ask('question-id', {
user: {
id: user.id, // Required for smart filtering
name: user.name, // Optional - enhances dashboard display
email: user.email,
avatar: user.avatarUrl
}
});
};
return <button onClick={handleFeedback}>Give Feedback</button>;
}In Vanilla JS
const whatif = new WhatIf('your-project-id');
function showFeedback() {
const user = getCurrentUser(); // Your user object
whatif.ask('question-id', {
user: {
id: user.id, // Required for smart filtering
name: user.name, // Optional - enhances dashboard display
email: user.email,
avatar: user.avatarUrl
},
context: {
page: "dashboard", // Custom metadata
action: "feedback-click"
}
});
}Dashboard Display
When you include user context, responses display beautifully in your dashboard:
âââââââââââââââââââââââââââââââââââ
â đ¤ Sarah Chen â
â sarah@example.com â
âââââââââââââââââââââââââââââââââââThe dashboard automatically:
- â Shows user avatar (or initials if no avatar)
- â Displays name and email
- â Enables user-based filtering
- â Groups responses by user
Beautiful Organization Display
Add organization context to display organization cards with logos and names.
Basic Organization Context
whatif.ask('question-id', {
user: {
id: "user_123",
name: "Sarah Chen"
},
org: {
id: "org_acme_123", // Optional - for organization tracking
name: "Acme Corp", // Required if org provided - for dashboard display
logo: "https://example.com/logo.png" // Optional - for dashboard display
},
context: {
department: "engineering" // Custom metadata
}
});In React
import { useWhatIf } from '@twenty1tools/whatif';
function FeedbackButton() {
const { ask } = useWhatIf();
const { user, organization } = useAuth(); // Your auth hook
const handleFeedback = () => {
ask('question-id', {
user: {
id: user.id, // Required for smart filtering
name: user.name,
email: user.email,
avatar: user.avatarUrl
},
org: {
id: organization.id, // Optional - for organization tracking
name: organization.name,
id: organization.id,
logo: organization.logoUrl
}
}
});
};
return <button onClick={handleFeedback}>Give Feedback</button>;
}In Vanilla JS
const whatif = new WhatIf('your-project-id');
function showFeedback() {
const { user, organization } = getCurrentSession();
whatif.ask('question-id', {
context: {
user: {
name: user.name,
email: user.email,
avatar: user.avatarUrl
},
org: {
name: organization.name,
id: organization.id,
logo: organization.logoUrl
}
}
});
}Dashboard Display
When you include organization context, responses display beautifully:
âââââââââââââââââââââââââââââââââââ
â đ˘ Acme Corp â
â org_acme_123 â
âââââââââââââââââââââââââââââââââââThe dashboard automatically:
- â Shows organization logo (or initials if no logo)
- â Displays organization name and ID
- â Enables organization-based filtering
- â Groups responses by organization
Complete Example
Here's a complete example with all context data:
const whatif = new WhatIf('your-project-id');
function collectFeedback() {
const user = getCurrentUser();
const organization = getCurrentOrganization();
whatif.ask('feature-feedback', {
user: {
id: user.id, // Required for smart filtering
name: user.name, // Optional - for dashboard display
email: user.email, // Optional - for dashboard display
avatar: user.avatarUrl // Optional - for dashboard display
},
org: {
name: organization.name, // Required - for dashboard display
id: organization.id, // Optional - for organization tracking
logo: organization.logoUrl // Optional - for dashboard display
},
context: {
// Additional custom context
feature: 'new-dashboard',
version: '2.0',
plan: user.plan
}
});
}What Gets Captured Automatically
Even if you don't provide any context, WhatIf automatically captures:
{
"timestamp": "2025-11-19T09:12:27.792Z",
"browser": {
"userAgent": "Mozilla/5.0...",
"language": "en-US",
"languages": ["en-US", "en"],
"platform": "MacIntel"
},
"device": {
"type": "desktop",
"platform": "MacIntel"
},
"page": {
"url": "https://app.example.com/checkout",
"title": "Checkout - My App",
"pathname": "/checkout",
"search": "",
"hash": ""
},
"previousUrl": "https://app.example.com/cart"
}Context Merging
Your custom context is merged with automatic context. Your values take precedence:
// You provide:
{
user: { id: "user123", name: "Sarah" },
context: { page: "checkout", custom: "data" }
}
// Final context includes:
{
user: { id: "user123", name: "Sarah" }, // Your user data
context: {
page: "checkout", // Your custom data
custom: "data", // Your custom data
timestamp: "2025-11-19T09:12:27.792Z", // Auto-captured
browser: { ... }, // Auto-captured
device: { ... }, // Auto-captured
page: {
url: "https://...", // Auto-captured
title: "...", // Auto-captured
pathname: "/checkout" // Auto-captured
}
}
}Dashboard Features
When you provide user and org context, your dashboard automatically:
User Column
- Beautiful avatar display (or initials)
- Name and email shown
- Clickable for filtering
- Searchable
Organization Column
- Organization logo (or initials)
- Name and ID displayed
- Clickable for filtering
- Searchable
Page Column
- Page title and URL displayed
- Shows pathname and query params
- Clickable for filtering
Filtering
- Filter by user
- Filter by organization
- Filter by page
- Filter by date (using automatic timestamp)
- Filter by any custom context fields
Best Practices
â Do's
// â
Always include user context when available
ask('question-id', {
user: {
id: user.id, // Required for smart filtering
name: user.name,
email: user.email,
avatar: user.avatarUrl
},
context: {
feature: 'checkout'
}
});
// â
Include organization for B2B apps
ask('question-id', {
user: {
id: user.id,
name: user.name
},
org: {
name: org.name,
id: org.id,
logo: org.logoUrl
},
context: {
department: 'engineering'
}
});
// â
Add relevant custom context
ask('question-id', {
user: {
id: user.id,
name: user.name
},
context: {
feature: 'checkout',
step: 'payment',
orderValue: 99.99
}
});â Don'ts
// â Don't include sensitive data in user object
ask('question-id', {
user: {
id: user.id,
name: user.name,
password: "secret123" // Never! User object should only contain display data
}
});
// â Don't include large objects in context
ask('question-id', {
user: { id: user.id, name: user.name },
context: {
entireDatabase: { ... } // Too large!
}
});Field Requirements
User Object (Top-level)
- id (string, required): User's unique identifier for smart filtering
- name (string, optional): User's display name for dashboard
- email (string, optional): User's email address for dashboard
- avatar (string, optional): URL to user's avatar image for dashboard
Organization Object (Top-level)
- name (string, required): Organization's display name for dashboard
- id (string, optional): Organization's unique identifier for tracking
- logo (string, optional): URL to organization's logo image for dashboard
Context Object (Custom metadata)
- Any additional key-value pairs for your business logic
- No restrictions on types or nesting
Examples
E-commerce Checkout
whatif.ask('checkout-satisfaction', {
user: {
id: user.id,
name: user.name,
email: user.email,
avatar: user.avatarUrl
},
context: {
orderId: order.id,
orderTotal: order.total,
paymentMethod: order.paymentMethod
}
});SaaS Feature Feedback
whatif.ask('feature-feedback', {
user: {
id: user.id,
name: user.name,
email: user.email,
avatar: user.avatarUrl
},
org: {
name: organization.name,
id: organization.id,
logo: organization.logoUrl
},
context: {
feature: 'new-dashboard',
plan: user.subscriptionPlan
}
});Support Ticket Follow-up
whatif.ask('support-satisfaction', {
user: {
id: user.id,
name: user.name,
email: user.email,
avatar: user.avatarUrl
},
context: {
ticketId: ticket.id,
ticketCategory: ticket.category,
resolved: ticket.resolved
}
});Next Steps
- đ Product Use Cases - Industry-specific implementation examples
- đ View Analytics - See how context data helps with insights
- đ¨ Theming Guide - Customize widget appearance
- đ API Reference - Full API documentation