Generate realistic user behavior data for any website
A web automation service that creates authentic analytics data by simulating real human interactions. Also, it injects Mixpanel!
NPC Mixpanel generates realistic user sessions with:
- Natural mouse movements and scrolling patterns
- Context-aware interactions based on page content
- Persona-driven behaviors that reflect different user types
- Human-like timing and decision patterns
The result: test data that actually reflects how autocaptured data in Mixpanel would look, making it perfect for demos, testing, and validation.
- Intelligent Behavior: Persona-based users with realistic interaction patterns
- Real-Time Monitoring: Live WebSocket updates with detailed logging
- Anti-Detection: Stealth techniques for authentic browser sessions
- Cloud-Ready: Deploy to Google Cloud Run with automatic scaling
https://meeple.mixpanel.org (you will need to be logged in via Okta)
- Clone and Install
git clone <your-repo-url>
cd npc-mixpanel
npm install- Environment Setup
# Create .env file
echo "NODE_ENV=dev" > .env
echo "MIXPANEL_TOKEN=your_mixpanel_token" >> .env
echo "SERVICE_NAME=npc-mixpanel" >> .env- Run Locally
npm run local- Open the Interface
Navigate to
http://localhost:8080and start your first simulation!
# Deploy to Google Cloud Run
npm run deployThe web interface provides an intuitive way to configure and monitor your simulations:
- Target URL: The website you want to test
- Number of Users: 1-25 simulated users per session
- Behavior Settings: Headless mode, Mixpanel injection, historical timestamps
- Real-Time Terminal: Live updates with color-coded status messages
- Session Results: Detailed summaries of user interactions
import main from './headless.js';
// Basic simulation
const results = await main({
url: 'https://your-website.com',
users: 10,
concurrency: 3,
headless: true,
inject: true
});
// Advanced configuration
const results = await main({
url: 'https://your-website.com',
users: 15,
concurrency: 5,
headless: false, // Watch the automation
inject: true, // Inject Mixpanel tracking
past: true, // Use historical timestamps
token: 'your_token', // Custom Mixpanel token
maxActions: 20 // Limit actions per user
});| Parameter | Type | Default | Description |
|---|---|---|---|
url |
string | Demo site | Target website URL |
users |
number | 10 | Number of users to simulate (1-25) |
concurrency |
number | 5 | Concurrent users (1-10) |
headless |
boolean | true | Run browsers in headless mode |
inject |
boolean | true | Inject Mixpanel tracking |
past |
boolean | false | Use historical timestamps |
token |
string | - | Custom Mixpanel project token |
maxActions |
number | null | Maximum actions per user |
For legitimate testing only:
- âś… Test your own websites and applications
- âś… Generate realistic analytics data for development
- âś… Validate user experience flows
Not for:
- đźš« Load testing or overwhelming servers
- đźš« Sites you don't own without permission
- đźš« Circumventing rate limits or security measures
npm test # Run full test suite
npm run test:headless # Test automation functionsISC License - Feel free to use this for your testing and development needs.
The npc-mixpanel automation system supports deterministic sequence execution for creating reproducible user journeys and funnels. This document provides comprehensive guidance on using the sequences feature.
Send a POST request to /simulate with a sequences parameter:
curl -X POST http://localhost:3000/simulate \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-website.com",
"users": 5,
"sequences": {
"checkout-flow": {
"description": "Complete purchase with coupon",
"temperature": 7,
"actions": [
{"action": "click", "selector": "#product"},
{"action": "click", "selector": "#addToCart"},
{"action": "type", "selector": "#coupon", "text": "SAVE20"},
{"action": "click", "selector": "#checkout"}
]
}
}
}'description(optional): Human-readable descriptiontemperature(0-10): Controls sequence adherencechaos-range(optional):[min, max]multiplier for variabilityactions(required): Array of actions to perform
The temperature setting controls how strictly meeples follow the sequence:
- 10: Strict adherence - follows sequence exactly
- 7-9: High adherence - mostly follows sequence with minor deviations
- 4-6: Balanced - mix of sequence and random actions
- 1-3: Low adherence - mostly random with occasional sequence actions
- 0: Random - ignores sequence completely
Adds run-to-run variability by multiplying temperature by a random value:
{
"temperature": 5,
"chaos-range": [0.5, 1.5]
}Effective temperature will be between 2.5 and 7.5 for each run.
Clicks on an element identified by CSS selector:
{ "action": "click", "selector": "#elementId" }Examples:
{"action": "click", "selector": "button.primary"}
{"action": "click", "selector": "[data-testid='submit']"}
{"action": "click", "selector": ".product-card:first-child"}Types text into an input field:
{ "action": "type", "selector": "#inputField", "text": "Hello World" }Examples:
{"action": "type", "selector": "#email", "text": "[email protected]"}
{"action": "type", "selector": "input[name='search']", "text": "product name"}
{"action": "type", "selector": "#message", "text": "This is a test message"}Selects an option from a dropdown:
{ "action": "select", "selector": "#dropdown", "value": "option1" }Examples:
{"action": "select", "selector": "#country", "value": "US"}
{"action": "select", "selector": "select[name='shipping']", "value": "express"}
{"action": "select", "selector": "#quantity", "value": "2"}Sequences include realistic human behaviors:
- Natural delays: 500ms-2000ms between actions
- Mouse movements: Natural cursor paths with bezier curves
- Click precision: Slight randomness in click positions
- Scrolling: Automatic scrolling to bring elements into view
- Micro-movements: Small cursor adjustments and tremor effects
The system gracefully handles common issues:
- Element not found: Continues to next action after timeout
- Invalid selectors: Logs error and proceeds
- Page navigation: Adapts to URL changes during sequence
- Timeout handling: 5-second timeout per element lookup
- Consecutive failures: Stops sequence after 3 consecutive failures
{
"sequences": {
"abandoned-cart": {
"description": "Add to cart but abandon checkout",
"temperature": 6,
"chaos-range": [1, 3],
"actions": [
{ "action": "click", "selector": ".product-item" },
{ "action": "click", "selector": "#add-to-cart" },
{ "action": "click", "selector": "#cart-icon" },
{ "action": "click", "selector": "#remove-item" }
]
},
"successful-purchase": {
"description": "Complete full purchase flow",
"temperature": 8,
"actions": [
{ "action": "click", "selector": ".product-item" },
{ "action": "click", "selector": "#add-to-cart" },
{ "action": "click", "selector": "#checkout" },
{ "action": "type", "selector": "#email", "text": "[email protected]" },
{ "action": "type", "selector": "#card", "text": "4111111111111111" },
{ "action": "click", "selector": "#complete-order" }
]
}
}
}{
"sequences": {
"invalid-email-flow": {
"description": "Test email validation",
"temperature": 9,
"actions": [
{ "action": "type", "selector": "#email", "text": "invalid-email" },
{ "action": "click", "selector": "#submit" },
{ "action": "type", "selector": "#email", "text": "[email protected]" },
{ "action": "click", "selector": "#submit" }
]
},
"required-fields": {
"description": "Test required field validation",
"temperature": 8,
"actions": [
{ "action": "click", "selector": "#submit" },
{ "action": "type", "selector": "#name", "text": "John Doe" },
{ "action": "click", "selector": "#submit" },
{ "action": "type", "selector": "#email", "text": "[email protected]" },
{ "action": "click", "selector": "#submit" }
]
}
}
}{
"sequences": {
"variant-a-flow": {
"description": "Test variant A of signup flow",
"temperature": 7,
"actions": [
{ "action": "click", "selector": "#signup-variant-a" },
{ "action": "type", "selector": "#email", "text": "[email protected]" },
{ "action": "type", "selector": "#password", "text": "password123" },
{ "action": "click", "selector": "#create-account" }
]
},
"variant-b-flow": {
"description": "Test variant B of signup flow",
"temperature": 7,
"actions": [
{ "action": "click", "selector": "#signup-variant-b" },
{ "action": "type", "selector": "#username", "text": "testuser" },
{ "action": "type", "selector": "#email", "text": "[email protected]" },
{ "action": "type", "selector": "#password", "text": "password123" },
{ "action": "click", "selector": "#register" }
]
}
}
}Successful execution returns detailed results:
{
"results": [
{
"actions": [
{
"action": "click",
"selector": "#product",
"success": true,
"duration": 245,
"timestamp": 1647891234567
},
{
"action": "type",
"selector": "#email",
"text": "[email protected]",
"success": true,
"duration": 180,
"timestamp": 1647891234812
}
],
"duration": 12,
"persona": "researcher",
"sequence": "checkout-flow",
"success": true
}
]
}action: Type of action performedselector: CSS selector usedtext: Text typed (for type actions)value: Value selected (for select actions)success: Whether action succeedederror: Error message if failedduration: Time taken in millisecondstimestamp: When action was executed
Invalid sequences return detailed error messages:
{
"error": "Invalid sequences specification",
"details": [
"Sequence \"test\": Temperature must be a number between 0 and 10",
"Sequence \"test\": Action 1 has unsupported action type: invalid",
"Sequence \"test\": Action 2 (type) must have a text field"
]
}Sequences work seamlessly with hot zone detection:
- When sequence actions fail, system falls back to hot zone targeting
- Hot zones provide intelligent element alternatives
- Visual prominence scoring helps select fallback targets
Selected personas influence behavior when temperature allows deviation:
researcher: Longer hover times, more thorough interactionspowerUser: Faster execution, fewer random actionsimpulse: Quick decisions, more random clicking
All sequence actions are tracked in Mixpanel:
- Sequence name and description in event properties
- Action-level tracking with timing data
- Success/failure rates for funnel analysis
WebSocket streaming provides live sequence execution updates:
- Each meeple gets dedicated terminal tab
- Real-time action progress and results
- Error logging and retry attempts
- Use stable selectors: Prefer
data-testidoridattributes - Avoid positional selectors: Don't rely on
:nth-child()unless necessary - Test selectors: Verify selectors work across different page states
- Start high (8-9): Begin with strict sequence following
- Add variability: Introduce chaos-range for realistic variation
- Lower for exploration: Use 4-6 for mixed behavior patterns
- Keep actions atomic: Each action should be simple and focused
- Handle failures gracefully: Design sequences to continue after failures
- Test edge cases: Include invalid inputs and error scenarios
- Limit sequence length: Keep under 10-15 actions for reliability
- Use reasonable delays: Don't make sequences too fast or slow
- Monitor success rates: Adjust selectors if actions frequently fail
Elements not found:
- Check selector syntax and specificity
- Verify elements exist when action executes
- Consider page load timing issues
Sequence not followed:
- Increase temperature value
- Reduce chaos-range
- Check for validation errors
Actions timing out:
- Increase element wait timeout
- Check for page navigation during sequence
- Verify elements are interactable
Enable detailed logging by checking browser console for:
- Element detection results
- Action execution timing
- Error messages and stack traces
Full TypeScript definitions are available in index.d.ts:
import { SequenceSpec, MeepleParams } from './index';
const sequence: SequenceSpec = {
description: 'Test sequence',
temperature: 7,
actions: [{ action: 'click', selector: '#button' }]
};
const params: MeepleParams = {
url: 'https://example.com',
users: 5,
sequences: { test: sequence }
};