Overview
The MentiQ Analytics SDK provides comprehensive user identification capabilities, allowing you to track both anonymous and identified users, merge user profiles, and enrich user data with custom traits.
User Identity Types
The SDK manages three types of user identifiers:
- User ID: Unique identifier for logged-in users
- Anonymous ID: Automatically generated for all users
- Session ID: Unique identifier for each session
Anonymous Tracking
Anonymous tracking is automatic - no configuration needed:
import { Analytics } from 'mentiq-sdk';
const analytics = new Analytics({
apiKey: 'your-api-key',
projectId: 'your-project-id',
});
// Anonymous ID is automatically generated and persisted
const anonymousId = analytics.getAnonymousId();
console.log('Anonymous ID:', anonymousId);
The anonymous ID is:
- Generated on first visit
- Stored in
localStorage as mentiq_anonymous_id
- Persists across sessions and page reloads
- Included automatically with all events
Identifying Users
Basic User Identification
Call identify() when a user logs in or signs up:
analytics.identify('user-123');
Unique identifier for the user (e.g., database ID, UUID)
Identification with User Traits
Enrich user profiles with additional information:
analytics.identify('user-123', {
email: '[email protected]',
name: 'John Doe',
plan: 'premium',
created_at: '2024-01-15',
company: 'Acme Corp',
});
Unique identifier for the user
Object containing user traits. Can include:
email: User email address (automatically detected from auth if not provided)
name: User full name
subscription: Subscription properties (see Subscription Tracking)
- Custom properties: Any additional user attributes
Managing User IDs
Set User ID
Set or update the user ID without sending an identify event:
analytics.setUserId('user-123');
Get User ID
Retrieve the current user ID:
const userId = analytics.getUserId();
if (userId) {
console.log('User is logged in:', userId);
} else {
console.log('User is anonymous');
}
Initialize with User ID
Set user ID during initialization:
const analytics = new Analytics({
apiKey: 'your-api-key',
projectId: 'your-project-id',
userId: 'user-123',
});
User Aliasing
Alias allows you to merge user identities, typically when transitioning from anonymous to identified:
// User was anonymous
const anonymousId = analytics.getAnonymousId();
// User signs up
analytics.identify('user-123', {
email: '[email protected]',
});
// Link the anonymous and identified user
analytics.alias('user-123', anonymousId);
The new user ID (typically the logged-in user ID)
The previous user ID or anonymous ID. If omitted, uses the current user ID.
Automatic Aliasing Flow
// 1. User arrives (anonymous)
const analytics = new Analytics({
apiKey: 'your-api-key',
projectId: 'your-project-id',
});
// 2. User browses (anonymous events tracked)
analytics.track('page_viewed', { page: 'pricing' });
analytics.track('button_clicked', { button: 'start_trial' });
// 3. User signs up
const newUserId = 'user-789';
const previousAnonymousId = analytics.getAnonymousId();
analytics.identify(newUserId, {
email: '[email protected]',
signup_method: 'email',
});
// 4. Link identities
analytics.alias(newUserId, previousAnonymousId);
Resetting User Identity
Reset user identity when logging out:
This:
- Clears the user ID
- Clears event queue
- Generates a new anonymous ID
- Starts a new session
- Preserves stored anonymous tracking
Always call reset() when a user logs out to prevent attribution errors.
Automatic Email Detection
The SDK automatically detects user email from popular authentication providers:
- NextAuth / Auth.js
- Supabase Auth
- Firebase Auth
- Clerk
- Auth0
No additional configuration needed:
// Email is automatically detected and included with events
const analytics = new Analytics({
apiKey: 'your-api-key',
projectId: 'your-project-id',
});
// Later, when user logs in via Supabase/Firebase/etc.
// Email is automatically detected and enriched in events
Detected email is:
- Stored in
localStorage as mentiq_user_email
- Automatically included with all events
- Used for user attribution and segmentation
Manual Email Override
Manually set email to override auto-detection:
Subscription Tracking
Track user subscription status for SaaS metrics:
analytics.identify('user-123', {
email: '[email protected]',
subscription: {
status: 'active',
plan_id: 'plan_premium',
plan_name: 'Premium Plan',
plan_tier: 'pro',
mrr: 2900, // $29.00 in cents
currency: 'usd',
billing_interval: 'month',
provider: 'stripe',
provider_customer_id: 'cus_123',
},
});
Subscription Properties
Subscription status: "active", "trialing", "past_due", "canceled", "paused", "incomplete", "incomplete_expired", or "unpaid"
Plan tier: "free", "starter", "pro", "enterprise", etc.
Monthly Recurring Revenue in cents (e.g., 2900 for $29.00)
Annual Recurring Revenue in cents
Currency code (e.g., "usd", "eur")
Billing cycle: "day", "week", "month", or "year"
Payment provider: "stripe", "paddle", "chargebee", "manual", or custom
Automatic Subscription Detection
The SDK automatically detects subscriptions from:
- Stripe.js
- Paddle.js
- Chargebee.js
// Automatic detection runs on initialization
const analytics = new Analytics({
apiKey: 'your-api-key',
projectId: 'your-project-id',
});
// Subscription data is automatically detected and stored
// Retrieve it with:
const subscription = analytics.getSubscriptionData();
if (subscription) {
console.log('Plan:', subscription.plan_name);
console.log('Status:', subscription.status);
console.log('MRR:', subscription.mrr);
}
PCI Compliance
The SDK automatically ensures PCI compliance:
Never include full card numbers or CVV codes. The SDK automatically removes these fields and truncates card numbers to last 4 digits only.
analytics.identify('user-123', {
subscription: {
status: 'active',
payment_method_type: 'card',
payment_method_last4: '4242', // Only last 4 digits
payment_method_brand: 'visa',
// card_number: NEVER include full card numbers
// cvv: NEVER include CVV
},
});
User Trait Enrichment
All events automatically include user traits:
analytics.identify('user-123', {
email: '[email protected]',
subscription: {
status: 'active',
plan_name: 'Premium',
mrr: 2900,
},
});
// Subsequent events automatically enriched
analytics.track('feature_used', {
feature: 'export_data',
});
// This event includes:
// - email: '[email protected]'
// - subscription_status: 'active'
// - subscription_plan: 'Premium'
// - subscription_mrr: 2900
// - is_paid_user: true
User Persistence
Storage Locations
User data is persisted in browser storage:
// User ID
localStorage.getItem('mentiq_user_id')
// Anonymous ID
localStorage.getItem('mentiq_anonymous_id')
// Email
localStorage.getItem('mentiq_user_email')
// Subscription Data
localStorage.getItem('mentiq_user_subscription')
// Session ID (per-tab)
sessionStorage.getItem('mentiq_session_id')
Cross-Domain Tracking
For cross-domain tracking, manually pass user identifiers:
// On domain A
const userId = analytics.getUserId();
const anonymousId = analytics.getAnonymousId();
// Pass to domain B via URL
window.location.href = `https://domainb.com?uid=${userId}&aid=${anonymousId}`;
// On domain B
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('uid');
const anonymousId = urlParams.get('aid');
if (userId) {
analytics.identify(userId);
}
Best Practices
Call identify() immediately after successful login or signup to ensure all subsequent events are attributed correctly.
Always call reset() on logout to prevent cross-user contamination.
Use database IDs (not emails) as user IDs for stability - emails can change.
Anonymous and identified user data is automatically merged when you call alias(), preserving the complete user journey.
Common Implementation Patterns
Next.js with NextAuth
import { useSession } from 'next-auth/react';
import { useEffect } from 'react';
function MyApp() {
const { data: session } = useSession();
useEffect(() => {
if (session?.user) {
analytics.identify(session.user.id, {
email: session.user.email,
name: session.user.name,
});
} else {
analytics.reset();
}
}, [session]);
return <div>App Content</div>;
}
React with Supabase
import { useEffect } from 'react';
import { supabase } from './supabaseClient';
function App() {
useEffect(() => {
// Listen for auth changes
const { data: authListener } = supabase.auth.onAuthStateChange(
(event, session) => {
if (event === 'SIGNED_IN' && session?.user) {
analytics.identify(session.user.id, {
email: session.user.email,
});
} else if (event === 'SIGNED_OUT') {
analytics.reset();
}
}
);
return () => {
authListener?.subscription.unsubscribe();
};
}, []);
return <div>App Content</div>;
}
SaaS with Stripe Integration
// After successful Stripe checkout
stripe.redirectToCheckout({ sessionId }).then((result) => {
if (result.error) {
// Handle error
} else {
// Update subscription in analytics
analytics.identify(userId, {
subscription: {
status: 'active',
plan_id: selectedPlan.id,
plan_name: selectedPlan.name,
mrr: selectedPlan.price,
currency: 'usd',
billing_interval: 'month',
provider: 'stripe',
},
});
}
});