This file provides guidance for AI coding agents working with the mParticle Web SDK codebase.
mParticle is a Customer Data Platform that collects, validates, and forwards event data to analytics and marketing integrations. The SDK is responsible for:
- Event Collection: Capturing user interactions, commerce events, and custom events
- Identity Management: Managing user identity across sessions and platforms
- Event Forwarding: Routing events to configured integrations (kits/forwarders)
- Data Validation: Enforcing data quality through data plans
- Consent Management: Handling user consent preferences (GDPR, CCPA)
- Session Management: Tracking user sessions and engagement
- Batch Upload: Efficiently uploading events to mParticle servers
- MPID (mParticle ID): Unique identifier for a user across sessions and devices
- Kit/Forwarder: Third-party integration (e.g., Google Analytics, Braze) that receives events from the SDK
- Data Plan: Validation schema that defines expected events and their attributes
- Workspace: A customer's mParticle environment (identified by API key)
- Batch: Collection of events grouped together for efficient server upload
- Identity Request: API call to identify, login, logout, or modify a user's identity
- Session: Period of user activity with automatic timeout (typically 30 minutes)
- Consent State: User's privacy preferences (GDPR, CCPA) that control data collection and forwarding
- User Attributes: Key-value pairs describing user properties (e.g., email, age, preferences)
- Custom Events: Application-specific events defined by the developer
- Commerce Events: Predefined events for e-commerce tracking (purchases, product views, etc.)
- Event Type: Category of event (Navigation, Location, Transaction, UserContent, UserPreference, Social, Other)
- Read First, Modify Later: Always read relevant files before proposing changes. Use the Read tool to understand existing code, patterns, and conventions.
- Understand the Architecture: Review the instance-based architecture and module structure before adding features. Check
ARCHITECTURE.mdif available for architectural diagrams and design patterns. - Review Contributing Guidelines: Check
CONTRIBUTING.mdfor repository-specific contribution guidelines, workflow, and standards. - Check Existing Tests: Look at test files for usage examples and to understand expected behavior.
- Review Constants: Check the constants file(s) for standard values, messages, and configuration options.
- Security First: Prevent injection vulnerabilities (XSS, command injection, etc.)
- Avoid Over-Engineering: Only make changes that are directly requested or clearly necessary
- No Premature Abstractions: Don't create helpers or utilities for one-time operations
- Keep It Simple: Three similar lines of code is better than a premature abstraction
- No Unnecessary Features: Don't add error handling for scenarios that can't happen
- Trust Internal Code: Only validate at system boundaries (user input, external APIs)
PII (Personally Identifiable Information) is data that can identify a specific person, for example: email, name or phone number, and similar attributes. Logging raw payloads can expose PII in production.
- Use
obfuscateDevData(data, isDevelopmentMode)fromutilsto log payloads - shows raw data in development mode, obfuscates in production. - Use
obfuscateData(data)fromutilswhen you need to obfuscate a specific field.
- Run the full test suite before committing
- Add tests for new features or bug fixes
- Test both success and error cases
- Use existing test patterns as examples
- Ensure tests pass in all supported environments
This repository uses Conventional Commits for semantic versioning:
<type>[optional scope]: <description>
[optional body]
[optional footer]
Commit Types:
feat→ Triggers minor version bump (new feature)fix→ Triggers patch version bump (bug fix)docs→ Documentation changestest→ Adding or updating testsrefactor→ Code refactoring without behavior changesperf→ Performance improvementsstyle→ Code style changes (formatting, etc.)chore→ Maintenance tasksci→ CI/CD changesbuild→ Build system changesrevert→ Reverting previous commits
Breaking Changes:
feat: new API for identity management
BREAKING CHANGE: Identity.login() now requires a callback parameter
Examples:
feat: add consent state filtering for forwarders
fix: prevent duplicate events in batch upload
docs: update API reference for eCommerce methods
test: add cross-browser tests for identity API
- Create PRs against the
masterbranch - Ensure all CI checks pass
- Include test coverage for changes
- Reference any related issues
- Follow the commit message format throughout the branch
All SDKs should provide these core modules:
- Identity: User identification, login, logout, modify
- Events: Event logging with custom attributes
- eCommerce: Commerce event tracking (purchases, product views, etc.)
- Consent: User consent state management
- Session: Session lifecycle management
- Configuration: SDK configuration and feature flags
Event Logged → Validation → Consent Check → Kit Forwarding → Batch Upload
↓ ↓ ↓ ↓
Data Plan Consent State Active Kits API Client
Initial Config (provided by developer)
↓
SDK Config (normalized and validated)
↓
Server Config (merged from mParticle servers)
↓
Feature Flags & Kit Configs (runtime)
- Languages: TypeScript and JavaScript
- Build Tool: Rollup with multiple output formats:
- IIFE (Immediately Invoked Function Expression) for browser
<script>tags - CommonJS for npm/Node.js environments
- ES Modules for modern bundlers with tree-shaking support
- Stub for capturing API calls before SDK loads
- IIFE (Immediately Invoked Function Expression) for browser
- Testing: Karma (browser integration), Jest (TypeScript modules), BrowserStack (cross-browser)
- Code Quality: ESLint, Prettier, GTS (Google TypeScript Style)
- Package Manager: npm
/ # Repo root
jest.config.js # Jest config for TypeScript unit tests
/src/ # Source code
├── mparticle-instance-manager.ts # Global manager, creates and retrieves named SDK instances
├── mp-instance.ts # Core SDK instance, initialization flow, public APIs, and private modules
├── apiClient.ts # HTTP client for making requests to mParticle Events API
├── batchUploader.ts # Batches events and uploads them to server with retry logic
├── identityApiClient.ts # Handles identity API calls (identify, login, logout, modify)
├── configAPIClient.ts # Fetches SDK configuration and kit settings from server
├── identity.js # User identity operations, MPID management, and identity callbacks
├── identity-utils.ts # Identity request validation and preprocessing helpers
├── events.js # Event logging, validation, and processing before forwarding
├── ecommerce.js # Commerce event creation (purchases, product views, promotions)
├── forwarders.js # Manages third-party kits, event forwarding, and filtering rules
├── kitBlocking.ts # Blocks events from kits based on data plan violations
├── integrationCapture.ts # Captures integration-specific events and metadata
├── consent.ts # GDPR/CCPA consent state management and filtering
├── cookieConsentManager.ts # Cookie-specific consent management and compliance
├── sessionManager.ts # Session creation, timeout tracking, and session ID generation
├── roktManager.ts # Bridge to Rokt services (selectPlacements, placement rendering)
├── store.ts # In-memory runtime state (config, flags, session data)
├── persistence.js # LocalStorage and cookie read/write operations
├── cookieSyncManager.ts # Synchronizes user data across domains via cookies
├── validators.ts # Input validation for events, attributes, and identities
├── constants.ts # SDK constants, error messages, and configuration defaults
├── types.ts # TypeScript type definitions and enums
├── utils.ts # Helper functions (parsing, formatting, feature detection)
├── helpers.js # General utility functions for data manipulation
├── logger.ts # Logging utility for errors, warnings, and debug messages
└── *.interfaces.ts # TypeScript interface definitions for public APIs
/test/ # Test suite
├── karma.config.js # Karma test runner config
├── src/tests-*.ts # Test files
└── jest/*.spec.ts # Jest unit tests
/dist/ # Built output
├── mparticle.js # IIFE bundle (browser <script> tag)
├── mparticle.common.js # CommonJS bundle (npm)
└── mparticle.esm.js # ES Modules bundle
/scripts/ # Build and release automation
/.github/workflows/ # CI/CD pipelines
TypeScript Configuration:
- Target: ES5
- Lib: ES5, ES6, DOM
- Module Resolution: Node
- Strict type checking: strictNullChecks=false, noImplicitAny=false
Naming Conventions:
// Interfaces (prefix with 'I' or 'SDK')
interface IFeatureName { }
interface SDKFeatureName { }
// Enums
enum EventType { }
enum MessageType { }
// Constants
const UPPER_SNAKE_CASE = 'value';
// Methods
function publicMethod() { }
function _privateMethod() { }
function getProperty() { }
function setProperty() { }Code Style (Prettier):
- Tab width: 4 spaces
- Quotes: Single quotes (
') - Trailing commas: ES5 style
- Line length: 80 characters (suggested)
ESLint Rules:
- Prettier enforcement enabled
- No unused variables
- Avoid console.log in production code; prefer Logger (not currently enforced by ESLint)
Linting & Code Quality Commands:
# Linting
npm run lint # ESLint check (both .js and .ts files)
npm run prettier # Prettier check (.js files only)
# Bundle Analysis
npm run bundle # Uglify + gzip for size reporting
npm run uglify # Minify bundle
npm run gzip # Gzip bundleLinting by File Type:
- JavaScript (.js): ESLint + Prettier
- TypeScript (.ts): ESLint + GTS (Google TypeScript Style)
Pre-commit Hooks:
- ESLint runs automatically before commits
- Commit will fail if linting errors exist
The Web SDK uses an instance manager pattern to support multiple SDK instances:
mParticle.init(apiKey, config, instanceName?)
mParticle.getInstance(instanceName?)Key Concepts:
- Default Instance: Used when no instance name is specified (typically named
default_instance) - Multiple Instances: Support for multiple workspaces or isolated data streams
- Instance Isolation: Each instance has its own configuration, user identity, and state
Use Cases for Multiple Instances:
- Multiple mParticle workspaces in a single application
- Isolated analytics streams (e.g., separate tracking for different features)
- Testing scenarios requiring separate SDK states
The Web SDK uses a global instance manager that creates individual SDK instances:
// Global manager
mParticle {
init(apiKey, config, instanceName?)
getInstance(instanceName?)
_instances: { [name: string]: IMParticleWebSDKInstance }
}
// Individual instance
IMParticleWebSDKInstance {
// Public API
logEvent(), logPurchase(), setUserAttribute()
Identity, eCommerce, Consent
// Private modules (accessed via mpInstance._ModuleName)
_APIClient // HTTP communication
_Identity // Identity management
_Events // Event logging
_Ecommerce // Commerce events
_Consent // Consent management
_Persistence // Storage (LocalStorage/Cookies)
_Store // Runtime state
_SessionManager // Session lifecycle
_Forwarders // Kit management
_Logger // Logging utility
}When working on specific features, refer to these files:
| Feature | Main Files |
|---|---|
| Entry Point | mparticle-instance-manager.ts |
| Core Instance | mp-instance.ts |
| Identity | identity.js, identity-utils.ts, identity.interfaces.ts |
| Events | events.js, events.interfaces.ts |
| eCommerce | ecommerce.js, ecommerce.interfaces.ts |
| Forwarders | forwarders.js, forwarders.interfaces.ts, kitBlocking.ts |
| Consent | consent.ts |
| Session | sessionManager.ts |
| Storage | persistence.js, store.ts |
| HTTP | apiClient.ts, identityApiClient.ts, configAPIClient.ts |
| Validation | validators.ts |
| Constants | constants.ts |
| Types | types.ts |
Build Commands:
# Development
npm run watch # Watch IIFE and rebuild
npm run watch:all # Watch all formats
npm run watch:tests # Watch and rebuild tests
npm run build:dev # Dev build with sourcemap
# Production Builds
npm run build # Build all formats
npm run build:iife # Browser bundle (dist/mparticle.js)
npm run build:npm # CommonJS (dist/mparticle.common.js)
npm run build:esm # ES Modules (dist/mparticle.esm.js)
npm run build:stub # Stub file (pre-init API)
# Specialized
npm run build:snippet # Minified snippets
npm run build:ts # TypeScript compilation onlyRollup Configuration:
- Entry:
src/mparticle-instance-manager.ts - Plugins: Babel, TypeScript, Node Resolve, CommonJS, Uglify
Environment Variables:
ENVIRONMENT:devorproductionBUILD: Target build format (e.g.,iife,cjs)BUILDALL: Build all formats
Test Commands:
npm run test # Full suite (Karma + Jest)
npm run test:debug # Interactive Chrome debug mode
npm run test:jest # Jest unit tests only (TypeScript)
npm run test:jest:watch # Jest watch mode
npm run test:browserstack # BrowserStack cross-browser tests
npm run test:integrations # All integrations (CJS, ESM, RequireJS)Karma (Browser Integration Tests):
- Purpose: Full SDK integration tests in real browser environment
- Files:
test/src/tests-*.tsortests-*.js(legacy) - Browsers: ChromeHeadless, Firefox
- Key Patterns:
- Reset state with
mParticle._resetForTests(MPConfig)inbeforeEach - Mock HTTP with fetch-mock/esm/client
- Use
waitForCondition()helper fromtest/src/config/utils.tsfor async operations - Chai assertions:
expect(...).to.equal(),expect(...).to.be.ok,expect(...).to.have.keys() - Sinon for spies/stubs
- Reset state with
Jest (TypeScript Unit Tests):
- Purpose: Fast isolated unit tests for TypeScript modules
- Files:
test/jest/*.spec.ts - Environment: jsdom (simulates browser)
- Key Patterns:
- Mock timers with
jest.useFakeTimers()andjest.advanceTimersByTime() - Mock global.fetch with
jest.fn().mockResolvedValue() - Create mock mpInstance objects as needed
- Jest matchers:
toBe(),toEqual(),toBeDefined(),toHaveBeenCalled()
- Mock timers with
The Web SDK uses a tiered storage approach:
- Primary: LocalStorage (
window.localStorage) - Fallback: Cookies (
document.cookie) - Key Pattern:
mp_[workspace]_[mpid]
Stored Data:
- User MPID (mParticle ID)
- User attributes
- Identity information
- Session data
- Consent state
- Cookie sync information
Access Pattern:
// Via instance
mpInstance._Persistence.setLocalStorage(key, value);
const value = mpInstance._Persistence.getLocalStorage(key);
// Store for runtime state
mpInstance._Store.devToken = 'xyz';Endpoints:
- Events:
/v1/[workspace]/events - Identity:
/v1/[workspace]/identify,/login,/logout,/modify - Config:
/v1/[workspace]/config
Request Flow:
Event/Identity Call → Validation → mpInstance._APIClient.send() → Batch → HTTP POST
↓
Callback Invoked ← Response Processed ← Server Response ← ← ← ← ← ← ← ← ←
HTTP Client:
- Uses
fetchAPI (polyfilled if needed) - Automatic retry logic for failed requests
- Batch upload with configurable intervals
- Request timeout handling
Forwarder Flow:
Event Logged → Kit Filters Applied → Forwarded to Active Kits → Kit Processes Event
↓
Consent Check, User Attribute Filters,
Anonymous User Rules, Kit Blocking
Kit Configuration:
- Fetched from mParticle servers on init
- Applied at runtime based on server config
- Can be dynamically enabled/disabled
- Each kit has its own filtering rules
Key Files:
forwarders.js: Main forwarder logicforwarders.interfaces.ts: Forwarder typeskitBlocking.ts: Data plan violation handlingintegrationCapture.ts: Integration event capture
Session Lifecycle:
SDK Init → Session Start → Activity → Timeout Check → Session End
↓ ↓ ↓
Session ID Created Session Extended New Session Created
Session Configuration:
- Default timeout: 30 minutes
- Configurable via
config.sessionTimeout - Tracked in
sessionManager.ts - Session ID included in all events
Logger Usage:
// Via instance
mpInstance.Logger.error('Error message');
mpInstance.Logger.warning('Warning message');
mpInstance.Logger.verbose('Debug message');Log Levels:
error: Critical errorswarning: Important warningsverbose: Debug information (only in development)
Best Practices:
- Use Logger instead of
console.log - Include context in error messages
- Reference constants for standard messages:
Constants.Messages.ErrorMessages
Core modules receive mpInstance as a parameter, allowing them to access other modules (e.g., mpInstance._Store, mpInstance.Logger). This provides testability, clear dependencies, no circular dependencies, and instance isolation.
- Instance vs Manager:
mParticleis the manager,mpInstanceis the SDK instance - Private Methods: Methods prefixed with
_are private/internal - Async Identity: Identity calls are async, use callbacks
- Storage Limits: LocalStorage has size limits (~5-10MB), cookies have 4KB limit
- Forwarder Timing: Kits may not be initialized immediately
- Filtering Rules: Events may be blocked by data plan rules or consent state
- Batch Events: Events are batched before upload (default: 100 events or 30 seconds)
- Minimize Storage: Only store essential data in LocalStorage/Cookies
- Async Operations: Use callbacks for async operations (don't block)
- Bundle Size: Monitor bundle size with
npm run bundle - Tree Shaking: ESM build supports tree shaking for smaller bundles
- Lazy Loading: Kits are loaded on-demand when configured
- Enable Verbose Logging: Set
config.logLevel = 'verbose'in init - Use Debug Mode: Run
npm run test:debugfor interactive debugging - Check Network: Inspect Network tab for API calls
- Inspect Storage: Check Application tab for LocalStorage/Cookies
- Use Source Maps: Dev builds include source maps
/verify: Run lint, build, and Jest tests to validate your changes before committing. Use this after making code changes to ensure nothing is broken. See.claude/skills/verify/skill.md.
- Documentation: https://docs.mparticle.com/developers/sdk/web/
- GitHub: https://github.com/mParticle/mparticle-web-sdk