Tappd Web SDK for customer data collection and content delivery
npm install @tappd/web-sdkCustomer Data Platform SDK for web applications. Track user behavior, sessions, page visits, and custom events with automatic session management and anonymous user tracking.
✅ Automatic Session Management - Hybrid approach with browser and time-based sessions
✅ Anonymous User Tracking - Track users before identification, automatically merge data
✅ Auto Page View Tracking - Automatic page visit tracking with SPA support
✅ Manual Event Tracking - Track custom events throughout your application
✅ Auto-Capture - Optional automatic click and form tracking
✅ Comprehensive Device Info - Browser, OS, screen, timezone, language tracking
✅ UTM Parameter Tracking - Automatic UTM parameter extraction
✅ Duration Tracking - Track time spent on pages
You can use the SDK via CDN (recommended for quick integration) or NPM (for build tools).
Add this script tag to your HTML:
``html`
Or load from your local server:
`html`
`bash`
npm install @tappd/web-sdk
Then in your JavaScript:
`javascript
// ES Module
import { TappdSDK } from '@tappd/web-sdk';
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
apiUrl: 'https://api.tappd.io/api/v1/sdk'
});
// CommonJS
const { TappdSDK } = require('@tappd/web-sdk');
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
apiUrl: 'https://api.tappd.io/api/v1/sdk'
});
`
1. Log into your Tappd dashboard
2. Navigate to Settings > Apps
3. Copy the App ID for your web app
`javascript
import TappdSDK from '@tappd/web-sdk';
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
apiUrl: 'https://sdk.gotappd.com/api/v1/sdk', // Optional
autoTrack: true, // Auto-track page views (default: true)
sessionTimeout: 30, // Session timeout in minutes (default: 30)
enableAutoCapture: false, // Auto-capture clicks/forms (default: false)
debug: false // Enable debug logging (default: false)
});
`
`javascript`
// When user logs in or signs up
await tappd.identify('user_123', {
name: 'John Doe',
email: 'john@example.com',
phone: '+1234567890',
external_id: 'ext_123',
// Custom attributes
age: 28,
plan: 'premium',
company: 'Acme Corp'
});
We recommend using standard event names for consistency:
`javascript
// Ecommerce events
await tappd.track('ecommerce.product_viewed', {
productId: 'prod_123',
productName: 'Pro Plan',
price: 99.99
});
await tappd.track('ecommerce.add_to_cart', {
productId: 'prod_123',
quantity: 1,
price: 99.99,
currency: 'USD'
});
await tappd.track('ecommerce.purchase', {
orderId: 'ord_123',
total: 99.99,
currency: 'USD',
items: [...]
});
// Web interaction events
await tappd.track('web.interaction.click', {
element: 'button',
text: 'Get Started',
location: 'hero'
});
await tappd.track('web.form.submitted', {
formId: 'contact-form',
formName: 'Contact Us',
success: true
});
// User events
await tappd.track('user.signup', {
method: 'email',
source: 'landing-page'
});
`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| appId | string | Required | Your App ID from the dashboard |apiUrl
| | string | https://sdk.gotappd.com/api/v1/sdk | Custom API URL |autoTrack
| | boolean | true | Auto-track page views |sessionTimeout
| | number | 30 | Session timeout in minutes |enableAutoCapture
| | boolean | false | Auto-capture clicks/forms |debug
| | boolean | false | Enable debug logging |
#### identify(userId, attributes?)
Identify or update a customer. Automatically merges anonymous data if user was previously anonymous.
`javascript`
await tappd.identify('user_123', {
name: 'John Doe',
email: 'john@example.com',
// Custom attributes
age: 28,
plan: 'premium'
});
Returns: Promise
---
#### track(eventName, properties?)
Track a custom event. We recommend using standard event names (see Standard Events).
`javascript
// Using standard event names
await tappd.track('ecommerce.add_to_cart', {
productId: 'prod_123',
quantity: 1,
price: 99.99,
currency: 'USD'
});
// Or custom event names
await tappd.track('custom_event', {
customProperty: 'value'
});
`
Returns: Promise
---
#### trackPageView(url?, properties?)
Manually track a page view.
`javascript`
await tappd.trackPageView('https://example.com/pricing');
Returns: Promise
---
#### setExternalId(externalId)
Set the external ID for the current user.
`javascript`
await tappd.setExternalId('ext_user_123');
Returns: Promise
---
#### setUserAttributes(attributes)
Update user attributes.
`javascript`
await tappd.setUserAttributes({
plan: 'enterprise',
lastLogin: new Date()
});
Returns: Promise
---
#### setCustomAttributes(attributes)
Set custom user attributes.
`javascript`
await tappd.setCustomAttributes({
preferences: { theme: 'dark', language: 'en' }
});
Returns: Promise
---
#### getSessionId()
Get the current session ID.
`javascript`
const sessionId = tappd.getSessionId();
console.log('Session ID:', sessionId);
Returns: string | null
---
#### getAnonymousId()
Get the anonymous ID (persists across sessions).
`javascript`
const anonymousId = tappd.getAnonymousId();
console.log('Anonymous ID:', anonymousId);
Returns: string
---
#### reset()
Reset the SDK state (clear user data, useful for logout).
`javascript`
tappd.reset();
Returns: void
---
The SDK uses a hybrid session approach:
1. Browser-based: New session per browser tab/window (stored in sessionStorage)
2. Time-based: Session expires after 30 minutes of inactivity (configurable)
1. Session Start: Automatically when SDK initializes
2. Heartbeat: Every 30 seconds to keep session alive
3. Session End: On page unload or after timeout
`javascript
// Get current session ID
const sessionId = tappd.getSessionId();
// Sessions are managed automatically
// No manual start/end needed
`
---
1. First Visit: SDK generates an anonymousId and stores it in localStorageanonymousId
2. Anonymous Tracking: All events, pages, and sessions are tracked with identify()
3. Identification: When is called, all anonymous data is automatically merged
4. Data Persistence: Anonymous ID persists across browser sessions until identification
`javascript
// User visits site (anonymous)
// SDK generates anonymousId and tracks page views, events
// Later, user logs in
await tappd.identify('user_123', {
email: 'john@example.com',
name: 'John Doe'
});
// All previous anonymous data is now associated with user_123
`
---
Page views are automatically tracked when:
- SDK initializes on page load
- User navigates (SPA support via History API)
- Browser back/forward button is used
`javascript`
// Manually track a page view
await tappd.trackPageView('https://example.com/pricing');
The SDK automatically tracks page views in Single Page Applications (SPAs) by:
- Overriding history.pushState() and history.replaceState()popstate
- Listening for events
- Tracking browser back/forward navigation
---
`javascript`
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
enableAutoCapture: true // Enable automatic event capture
});
- Link Clicks: All tags clickedautoTrack: true
- Form Submissions: All form submissions
- Page Views: (Always enabled if )
---
The SDK automatically collects comprehensive device information:
`javascript`
{
userAgent: "Mozilla/5.0...",
browser: { name: "Chrome", version: "120" },
os: { name: "macOS", version: "14.0" },
device: { type: "desktop" },
screenSize: { width: 1920, height: 1080, pixelRatio: 2 },
timezone: "America/New_York",
language: "en-US",
platform: "MacIntel",
connection: "4g"
}
---
UTM parameters are automatically extracted from page URLs:
`javascript`
// If URL is: https://example.com?utm_source=google&utm_medium=cpc&utm_campaign=summer
// SDK automatically extracts:
{
source: "google",
medium: "cpc",
campaign: "summer"
}
---
We've pre-defined standard event names for common use cases. These are automatically available in your workspace:
| Event Name | Description | Properties |
|------------|-------------|------------|
| web.pageView | User viewed a page | page, title, referrer |web.interaction.click
| | User clicked an element | element, text, location |web.form.viewed
| | User viewed a form | formId, formName |web.form.started
| | User started filling a form | formId, formName |web.form.filled
| | User filled out a form | formId, formName, fields |web.form.submitted
| | User submitted a form | formId, formName, success |
| Event Name | Description | Required Properties |
|------------|-------------|---------------------|
| ecommerce.product_viewed | User viewed a product | productId |ecommerce.add_to_cart
| | User added to cart | productId |ecommerce.remove_from_cart
| | User removed from cart | productId |ecommerce.checkout_started
| | User started checkout | - |ecommerce.checkout_step_completed
| | User completed checkout step | step |ecommerce.purchase
| | User completed purchase | orderId, total, currency |
| Event Name | Description | Properties |
|------------|-------------|------------|
| user.signup | User signed up | method, source |user.login
| | User logged in | method |user.logout
| | User logged out | - |
`javascript
// Ecommerce example
await tappd.track('ecommerce.product_viewed', {
productId: 'prod_123',
productName: 'Pro Plan',
category: 'Subscription',
price: 99.99
});
// Web interaction example
await tappd.track('web.interaction.click', {
element: 'button',
text: 'Get Started',
location: 'hero'
});
// User event example
await tappd.track('user.signup', {
method: 'email',
source: 'landing-page'
});
`
Note: You can still use custom event names (e.g., custom.event_name), but using standard names ensures consistency and better analytics.
---
`javascript
// Track product viewed
await tappd.track('ecommerce.product_viewed', {
productId: 'prod_123',
productName: 'iPhone 15',
price: 999,
category: 'Electronics'
});
// Track add to cart
await tappd.track('ecommerce.add_to_cart', {
productId: 'prod_123',
quantity: 1,
price: 999,
currency: 'USD'
});
// Track purchase
await tappd.track('ecommerce.purchase', {
orderId: 'order_456',
total: 999,
currency: 'USD',
items: [{ productId: 'prod_123', name: 'iPhone 15', price: 999, quantity: 1 }]
});
`
`javascript
// User visits site (anonymous)
// SDK automatically tracks page views
// User signs up
await tappd.identify('user_123', {
email: 'john@example.com',
name: 'John Doe'
});
// All previous anonymous data is now linked to user_123
// Track signup event
await tappd.track('user.signup', {
source: 'homepage',
plan: 'free'
});
// User upgrades
await tappd.track('upgrade', {
from: 'free',
to: 'pro',
amount: 99
});
// Update user attributes
await tappd.setUserAttributes({
plan: 'pro',
upgradedAt: new Date()
});
`
`javascript
// Initialize in main app file
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
autoTrack: true // SPA navigation is automatically tracked
});
// In your router
router.onRouteChange = async (to) => {
// Optional: Manually track route change
await tappd.track('route_change', {
from: router.previousRoute,
to: to.path,
title: to.meta.title
});
};
`
---
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
---
Enable debug logging to see SDK activity:
`javascript
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
debug: true // Enable debug logging
});
// Check browser console for SDK logs
// [Tappd SDK] Initialized with App ID: a1b2c3d4...
// [Tappd SDK] Customer identified: user_123
// [Tappd SDK] Event tracked: button_click
`
---
The SDK uses these API endpoints on https://sdk.gotappd.com/api/v1/sdk (automatically configured):
``
POST /identify # Identify user
POST /track # Track event
POST /page # Track page view
POST /session/start # Start session
POST /session/heartbeat # Session heartbeat
GET /in-app-messages # Get pending messages
POST /in-app-messages/:id/delivered # Mark message delivered
POST /in-app-messages/:id/dismiss # Dismiss message
GET /banners # Get eligible banners
POST /banners/:id/display # Track banner display
POST /banners/:id/click # Track banner click
POST /banners/:id/dismiss # Track banner dismiss
POST /bridge/action # Execute bridge action
POST /bridge/capture # Capture form data
GET /web-push/vapid-public-key # Get VAPID key
GET /web-push/subscription-status # Check push status
For detailed endpoint documentation, see API_ENDPOINTS.md
`
---
- All data is sent securely via HTTPS
- Anonymous IDs are stored in browser localStorage
- Session IDs are stored in sessionStorage (cleared when browser closes)
- No sensitive data is stored in the SDK
- Comply with GDPR, CCPA, and other privacy regulations
---
1. Check App ID is correct
2. Enable debug mode: debug: true
3. Check browser console for errors
4. Verify API endpoint is accessible
1. Ensure identify() is called with the same userIdanonymousId
2. Check that is passed during identification
3. Verify anonymous tracking happened before identification
1. Check browser console for errors
2. Verify session initialization completed
3. Look for network errors in Network tab
---
---
The SDK supports displaying in-app messages (banners, popups, and modals) created in your Tappd dashboard. Messages are automatically fetched and displayed when enabled using smart polling that only polls when users are active.
`javascript`
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
enableInAppMessages: true, // Enable in-app message rendering (default: true)
autoDisplayMessages: true, // Automatically display pending messages (default: true)
messagePollingInterval: 300, // Poll for new messages every 300 seconds (5 minutes) when active (default: 300)
inactivityThreshold: 300, // Stop polling after 300 seconds (5 minutes) of inactivity (default: 300)
messageContainerId: 'custom-container' // Optional: Custom DOM container ID
});
The SDK uses an intelligent polling strategy to minimize API calls and improve battery life:
1. Always Fetch on Launch - Messages are fetched immediately when the SDK initializes or page loads
2. Poll When Active - Polls for new messages every 5 minutes (configurable) when user is active
3. Stop When Inactive - Automatically stops polling after 5 minutes (configurable) of user inactivity
4. Resume on Activity - Immediately fetches messages and resumes polling when user becomes active again
5. Local Caching - Messages are cached in localStorage for 5 minutes for offline support and faster display
Activity Detection:
- Tracks user interactions: clicks, scrolls, keyboard input, mouse movement, touch events
- Uses Page Visibility API to detect when page is hidden/visible
- Automatically stops polling when page is hidden or user is inactive
When autoDisplayMessages is enabled, the SDK will:
1. Fetch on launch - Immediately fetch messages when SDK initializes
2. Load from cache - Display cached messages instantly (if available)
3. Poll when active - Update messages every 5 minutes (configurable) when user is active
4. Stop when inactive - Stop polling after 5 minutes (configurable) of inactivity
5. Resume on return - Fetch immediately when user returns
6. Evaluate trigger conditions
7. Display messages that are ready to be shown
8. Track message views and interactions
`javascript
// Fetch pending messages
const messages = await tappd.getInAppMessages();
// Display a specific message
await tappd.displayInAppMessage(message);
// Display all pending messages
await tappd.displayPendingMessages();
// Dismiss a message
await tappd.dismissMessage(messageId);
`
The SDK supports three message types:
1. Banner - Fixed position at top, bottom, or center of screen
2. Popup - Centered modal with overlay (smaller size)
3. Modal - Centered modal with overlay (larger size)
Messages can contain multiple blocks:
- Image - Display images with alignment options
- Text - Text content with styling (font size, weight, color, alignment)
- Button - Clickable buttons with links and custom styling
- HTML - Raw HTML content (sanitized)
The SDK automatically tracks message events:
- message.viewed - When a message is displayedmessage.clicked
- - When a button in the message is clickedmessage.dismissed
- - When a message is dismissed
`javascript
// Initialize SDK with in-app messages
const tappd = new TappdSDK({
appId: 'YOUR_APP_ID',
enableInAppMessages: true,
autoDisplayMessages: true
});
// Identify user (messages will be fetched automatically)
await tappd.identify({
external_id: 'user_123',
email: 'john@example.com',
name: 'John Doe'
});
// Messages are now being fetched and displayed automatically
// You can also manually fetch and display:
const messages = await tappd.getInAppMessages();
await tappd.displayPendingMessages();
``
---
MIT
---
For issues and questions:
- GitHub Issues: https://github.com/gotappd/web-sdk/issues
- Documentation: https://docs.gotappd.com/web-sdk
- Email: dev-support@gotappd.com