Documentation

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