Package Exports
- @shoppi/analytics
Readme
Shoppi Analytics SDK
A lightweight, type-safe analytics SDK for tracking user interactions with e-commerce applications.
Features
- Type-safe event tracking with TypeScript support
- Specialized methods for common e-commerce events
- Configurable batch processing and automatic retries
- Flow context tracking for analyzing user journeys
- Robust user identity management with persistent tracking
- Automatic timestamp and client metadata handling
- Minimal configuration required
- Support for selector-based tracking with HTML data attributes
Table of Contents
- Installation
- Usage Methods
- Quick Start
- Initialization
- User Identification
- Basic Usage
- Data Attributes
- Event Types
- Flow Types
- Advanced Usage
- Configuration Options
- Best Practices
- API Reference
- Cross-Device Tracking
- Changelog
Installation
npm install shoppi-analytics
Usage Methods
The SDK supports three modes of usage:
1. TypeScript
import { Analytics, FlowType } from 'shoppi-analytics';
const analytics = Analytics.init({
apiKey: 'your-api-key',
clientId: 'your-client-id',
debug: true
});
analytics.trackProductDetailView({
objectId: 'product-123',
price: 99.99,
category: 'clothing'
});
2. JavaScript (Node.js/Bundler)
// ESM import
import { Analytics } from 'shoppi-analytics';
// OR CommonJS require
const { Analytics } = require('shoppi-analytics');
const analytics = Analytics.init({
apiKey: 'your-api-key',
clientId: 'your-client-id'
});
analytics.trackProductClick({
objectId: 'product-123',
price: 99.99
});
3. Browser (Script Tag)
<script src="https://cdn.example.com/shoppi-analytics/dist/shoppi-analytics.js"></script>
<script>
// Clean interface - no nested Analytics property needed
const analytics = ShoppiAnalytics.init({
apiKey: 'your-api-key',
clientId: 'your-client-id'
});
// Track events
analytics.trackProductClick({
objectId: 'product-123',
price: 99.99
}, ShoppiAnalytics.FlowType.DIRECT);
</script>
Quick Start
Initialization
import { Analytics, AnalyticsConfig, FlowType } from 'shoppi-analytics';
const config: AnalyticsConfig = {
apiKey: 'your-api-key',
clientId: 'your-client-id',
debug: true, // Optional, enables debug logging
// Optional user tokens - recommended for user journey tracking
userToken: {
anonymousId: 'client-anon-id-123', // Client-provided anonymous user ID
authenticatedId: 'user-456' // Client-provided authenticated user ID
}
};
// Initialize the SDK
const analytics = Analytics.init(config);
// Track events using selectors
analytics.trackProductClick(`[id="${product.id}"]`);
// Using flow-specific methods with selectors
analytics.trackSearchAddToCart(`[data-shoppi-object-id="${product.id}"][data-shoppi-price="${product.price}"]`);
analytics.trackOutfitAddToCart(`[data-shoppi-object-id="${outfitProduct.id}"][data-shoppi-price="${outfitProduct.price}"]`);
analytics.trackSimilarAddToCart(`[data-shoppi-object-id="${similarProduct.id}"][data-shoppi-price="${similarProduct.price}"]`);
// Or using properties
analytics.trackAddToCart({
objectId: 'product-123',
price: 99.99
}, FlowType.DIRECT);
User Identification
The SDK manages three types of user identifiers:
- anonymousId (optional): Client-provided identifier for anonymous users
- authenticatedId (optional): Client-provided identifier for authenticated users
- shoppiId (required, managed by SDK): Persistent identifier generated and stored by the SDK
You can set these during initialization or update them later:
// Set during initialization
const analytics = Analytics.init({
// required config...
userToken: {
anonymousId: 'client-anon-id-123',
authenticatedId: 'user-456'
}
});
// Update later
analytics.setAnonymousId('new-anon-id');
analytics.setAuthenticatedId('new-auth-id');
analytics.setUserToken({
anonymousId: 'another-anon-id',
authenticatedId: 'another-auth-id'
});
Best Practices for User Identification
Initialize with existing IDs when available
// Retrieve IDs from storage or your authentication system const anonymousId = localStorage.getItem('your_anon_id_key'); const authenticatedId = getAuthenticatedUser()?.id; // Initialize with existing IDs const analytics = Analytics.init({ // Other config... userToken: { anonymousId, authenticatedId } });
Generate and store client anonymous ID
// Generate client-side anonymous ID if not already available let anonymousId = localStorage.getItem('your_anon_id_key'); if (!anonymousId) { anonymousId = generateRandomId(); // Your ID generation method localStorage.setItem('your_anon_id_key', anonymousId); } const analytics = Analytics.init({ // Other config... userToken: { anonymousId } });
Update authenticated ID after login
// After user login function onUserLogin(user) { // Update the authenticated ID while preserving anonymous ID analytics.setAuthenticatedId(user.id); }
Keep both IDs after authentication
- Always maintain both the anonymous ID and authenticated ID when a user logs in
- This ensures consistent tracking across anonymous and authenticated sessions
For SPAs and page reloads
- Initialize analytics with the same user tokens on page changes
- For single-page applications, initialize once with persistent tokens
Basic Usage
The SDK provides two approaches to tracking events:
Selector-based Tracking
Use CSS selectors to reference HTML elements with data attributes:
<!-- HTML element with data attributes -->
<div class="product-card"
id="product-123"
data-shoppi-object-id="product-123"
data-shoppi-price="99.99"
data-shoppi-category="clothing"
data-shoppi-title="Summer T-Shirt">
<img src="product.jpg" alt="Product Image">
<h3>Summer T-Shirt</h3>
<p>$99.99</p>
</div>
// Track a product click when the element is clicked
document.getElementById('product-123').addEventListener('click', function() {
analytics.trackProductClick(`[id="product-123"]`);
});
Properties-based Tracking
Directly pass properties as objects:
// Track a product view
analytics.trackProductDetailView({
objectId: 'product-123',
price: 99.99,
category: 'clothing',
title: 'Summer T-Shirt'
});
// Track adding to cart with specified flow
analytics.trackAddToCart({
objectId: 'product-123',
price: 99.99
}, FlowType.DIRECT);
// Using flow-specific methods
analytics.trackSearchAddToCart({
objectId: 'product-123',
price: 99.99
});
analytics.trackOutfitAddToCart({
objectId: 'product-456',
price: 149.99
});
analytics.trackSimilarAddToCart({
objectId: 'product-789',
price: 199.99
});
Data Attributes
The SDK supports automatic event tracking through HTML data attributes. All attributes should be prefixed with data-shoppi-
.
Attribute Format
- All attributes are prefixed with
data-shoppi-
- Property names are converted from kebab-case to camelCase automatically
- Example:
data-shoppi-object-id
becomesobjectId
in the event properties - Values are automatically converted to appropriate types (numbers, booleans)
Required Attributes
Different events require different attributes:
- Most events require
data-shoppi-object-id
- Search events require
data-shoppi-query-id
anddata-shoppi-query
- Conversion events require
data-shoppi-flow
- Purchase events also require
data-shoppi-value
anddata-shoppi-currency
Example Elements
Product Detail:
<div class="product-detail"
id="product-123"
data-shoppi-object-id="product-123"
data-shoppi-price="99.99"
data-shoppi-category="clothing"
data-shoppi-brand="BrandName"
data-shoppi-title="Summer T-Shirt">
<!-- Product content -->
</div>
Search Results:
<div class="search-results"
id="search-results"
data-shoppi-query-id="search-123"
data-shoppi-query="summer t-shirt"
data-shoppi-results-count="24">
<!-- Search results content -->
</div>
Add to Cart Button:
<button id="add-to-cart"
data-shoppi-object-id="product-123"
data-shoppi-price="99.99"
data-shoppi-quantity="1"
data-shoppi-flow="direct">
Add to Cart
</button>
Event Types
The SDK supports different event types for tracking various user interactions:
View Events
Track when users view content like products, search results, or outfits.
// Track product detail view
analytics.trackProductDetailView({
objectId: 'product-123',
price: 99.99,
category: 'clothing'
});
// Track search results view
analytics.trackSearchResultsView({
queryId: 'search-456',
query: 't-shirt',
resultsCount: 24
});
// Track outfit view
analytics.trackOutfitView({
objectId: 'outfit-789'
}, FlowType.OUTFIT);
// Track similar products view
analytics.trackSimilarProductsView({
sourceObjectId: 'product-123'
});
// Track category page view
analytics.trackCategoryPageView({
categoryId: 'men-clothing'
});
Click Events
Track when users click on interactive elements.
// Track product click
analytics.trackProductClick({
objectId: 'product-123',
price: 99.99
});
// Track search result click
analytics.trackSearchResultClick({
objectId: 'product-123',
queryId: 'search-456',
position: 3
});
// Track outfit item click
analytics.trackOutfitItemClick({
objectId: 'product-123',
position: 2
}, FlowType.OUTFIT);
// Track similar product click
analytics.trackSimilarProductClick({
objectId: 'product-456',
sourceObjectId: 'product-123'
});
Search Events
Track search-related actions like queries, filtering, and sorting.
// Track search query
analytics.trackSearchQuery({
queryId: 'search-456',
query: 't-shirt'
});
// Track filter applied
analytics.trackFilterApplied({
queryId: 'search-456',
filters: {
category: 'clothing',
size: 'medium',
color: 'blue'
}
});
// Track sort changed
analytics.trackSortChanged({
queryId: 'search-456',
sort: 'price_asc'
});
Conversion Events
Track commercial actions like adding to cart or purchasing.
// Track add to cart (flow is required for conversion events)
analytics.trackAddToCart({
objectId: 'product-123',
price: 99.99,
quantity: 1
}, FlowType.DIRECT);
// Track purchase
analytics.trackPurchase({
objectId: 'product-123',
value: 99.99,
currency: 'USD',
quantity: 1
}, FlowType.DIRECT);
// Track save for later
analytics.trackSaveForLater({
objectId: 'product-123'
}, FlowType.SEARCH);
Flow Types
Flow types indicate the user journey or context:
// Available flow types:
FlowType.DIRECT // Direct navigation or interaction
FlowType.SEARCH // From search results
FlowType.SIMILAR // From similar product recommendations
FlowType.OUTFIT // From outfit/collection recommendations
FlowType.CATEGORY // From category browsing
Most event methods use an appropriate default flow type, but you can override it. For conversion events, you must specify the flow explicitly to track attribution.
Default Flow Types
The SDK automatically sets appropriate default flow types for each event:
Event Method | Default Flow Type |
---|---|
trackSearchResultsView | FlowType.SEARCH |
trackSearchResultClick | FlowType.SEARCH |
trackSearchQuery | FlowType.SEARCH |
trackFilterApplied | FlowType.SEARCH |
trackSortChanged | FlowType.SEARCH |
trackOutfitView | FlowType.OUTFIT |
trackOutfitItemClick | FlowType.OUTFIT |
trackSimilarProductClick | FlowType.SIMILAR |
trackSimilarProductsView | FlowType.SIMILAR |
trackCategoryPageView | FlowType.CATEGORY |
trackProductDetailView | FlowType.DIRECT |
trackProductClick | FlowType.DIRECT |
Advanced Usage
Manual Event Tracking
For more control or custom events, use the generic trackEvent
method:
import { EventType, EventSubtype, FlowType } from 'shoppi-analytics';
analytics.trackEvent(
EventType.CONVERSION,
EventSubtype.ADD_TO_CART,
{
objectId: 'product-123',
objectType: 'product',
quantity: 2,
price: 99.99
},
FlowType.SEARCH
);
Event Batching and Flushing
Events are batched and sent automatically based on your configuration:
- Events are queued until the batch size is reached (default: 10)
- Events are automatically sent every X milliseconds (default: 5000ms)
- You can manually flush events at any time:
// Send all queued events immediately
analytics.flush();
// For single page applications, flush on route change
router.beforeEach((to, from, next) => {
analytics.flush().then(() => next());
});
// Always flush before page unload
window.addEventListener('beforeunload', function() {
analytics.flush();
});
// Call when your application is closing to ensure all events are sent
analytics.shutdown();
Tracking Dynamically Loaded Content
For content loaded dynamically via AJAX or other methods:
function loadProductsAndTrack(products) {
const container = document.getElementById('product-container');
// Clear container
container.innerHTML = '';
// Add products and track them
products.forEach((product, index) => {
// Create element
const productEl = document.createElement('div');
productEl.className = 'product-item';
productEl.id = `product-${product.id}`;
// Add data attributes
productEl.dataset.shoppiObjectId = product.id;
productEl.dataset.shoppiPosition = index + 1;
productEl.dataset.shoppiPrice = product.price;
productEl.dataset.shoppiCategory = product.category;
// Add content
productEl.innerHTML = `
<h3>${product.name}</h3>
<p>$${product.price}</p>
`;
// Add click handler
productEl.addEventListener('click', () => {
analytics.trackProductClick(`[id="product-${product.id}"]`);
});
// Add to container
container.appendChild(productEl);
});
}
Event Types and Required Fields
Event Type | Event Subtype | Description | Base Required Fields | Additional Required Fields | Flow Type Support |
---|---|---|---|---|---|
SEARCH | QUERY | Track search query execution | eventType, eventSubtype, eventName, flow, queryID, timestamp | query | All |
FILTER_APPLIED | Track when filters are applied | eventType, eventSubtype, eventName, flow, queryID, timestamp | filterName, filterValue | All | |
FILTER_REMOVED | Track when filters are removed | eventType, eventSubtype, eventName, flow, queryID, timestamp | filterName, filterValue | All | |
SORT_CHANGED | Track sort order changes | eventType, eventSubtype, eventName, flow, queryID, timestamp | sortOption | All | |
ZERO_RESULTS | Track searches with no results | eventType, eventSubtype, eventName, flow, queryID, timestamp | query | All | |
CLICK | PRODUCT | Track product clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | - | All |
SEARCH_RESULT | Track search result clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | queryID, position | SEARCH | |
SIMILAR_PRODUCT | Track similar product clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | sourceObjectID, position | SIMILAR | |
OUTFIT_ITEM | Track outfit item clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | outfitID, position | OUTFIT | |
OUTFIT | Track outfit clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | outfitID | OUTFIT | |
PAGINATION | Track pagination clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | - | All | |
FILTER | Track filter clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | - | All | |
SORT | Track sort option clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | - | All | |
SUGGESTION | Track search suggestion clicks | eventType, eventSubtype, eventName, flow, objectID, timestamp | suggestion, queryID | SEARCH | |
VIEW | PRODUCT_DETAIL | Track product detail views | eventType, eventSubtype, eventName, flow, timestamp | objectID | All |
SEARCH_RESULTS | Track search results views | eventType, eventSubtype, eventName, flow, timestamp | queryID, resultsCount | SEARCH | |
SIMILAR_PRODUCTS | Track similar products views | eventType, eventSubtype, eventName, flow, timestamp | sourceObjectID | SIMILAR | |
OUTFIT | Track outfit views | eventType, eventSubtype, eventName, flow, timestamp | outfitID | OUTFIT | |
OUTFIT_COLLECTION | Track outfit collection views | eventType, eventSubtype, eventName, flow, timestamp | outfitID | OUTFIT | |
CATEGORY_PAGE | Track category page views | eventType, eventSubtype, eventName, flow, timestamp | categoryID | CATEGORY | |
CONVERSION | PURCHASE | Track product purchases | eventType, eventSubtype, eventName, flow, objectID, timestamp | value, currency | All |
ADD_TO_CART | Track add to cart actions | eventType, eventSubtype, eventName, flow, objectID, timestamp | quantity | All | |
SAVE_FOR_LATER | Track save for later actions | eventType, eventSubtype, eventName, flow, objectID, timestamp | - | All | |
IMPRESSION | PRODUCT_LIST | Track product list impressions | eventType, eventSubtype, eventName, flow, items, timestamp | - | All |
SIMILAR_PRODUCTS | Track similar products impressions | eventType, eventSubtype, eventName, flow, items, timestamp | sourceObjectID | SIMILAR | |
OUTFIT_LIST | Track outfit list impressions | eventType, eventSubtype, eventName, flow, items, timestamp | outfitID | OUTFIT | |
SEARCH_RESULTS | Track search results impressions | eventType, eventSubtype, eventName, flow, items, timestamp | queryID, resultsCount | SEARCH |
Flow Types and Required Fields
Flow Type | Description | Required Fields | Use Case |
---|---|---|---|
DIRECT | Direct navigation or interaction | - | User directly navigates to a product or takes action without context |
SEARCH | From search results | queryID | User interacts with content from search results |
SIMILAR | From similar product recommendations | sourceObjectID | User interacts with similar product recommendations |
OUTFIT | From outfit/collection recommendations | outfitID | User interacts with outfit or collection content |
CATEGORY | From category browsing | categoryID | User browses and interacts with category pages |
Notes:
- All events include common fields like
timestamp
andflow
- Flow-specific fields are required when using that flow type
- Additional custom properties can be included beyond the required fields
- Some events may require specific combinations of fields based on the context
Configuration Options
- apiKey: Your API key for accessing the analytics server
- clientId: Your client ID for identifying the application
- debug: Enable or disable debug logging
- userToken: Optional user tokens for tracking user journeys
- batchSize: Maximum number of events to send in a single batch (default: 10)
- flushInterval: Interval in milliseconds to send events automatically (default: 5000ms)
Best Practices
- Initialize with existing IDs when available
- Generate and store client anonymous ID
- Update authenticated ID after login
- Keep both IDs after authentication
- For SPAs and page reloads
- Use appropriate flow types for conversion events
- Flush events before page unload
- Use selector-based tracking for dynamically loaded content
API Reference
Core Methods
- init(config): Initialize the analytics SDK
- setUserToken(token): Set user identification tokens
- setAnonymousId(id): Set anonymous user ID
- setAuthenticatedId(id): Set authenticated user ID
- flush(): Flush queued events
- shutdown(): Shutdown the SDK
View Events
- trackProductDetailView: Track product detail view
- trackSearchResultsView: Track search results view
- trackOutfitView: Track outfit view
- trackSimilarProductsView: Track similar products view
- trackCategoryPageView: Track category page view
Click Events
- trackProductClick: Track product click
- trackSearchResultClick: Track search result click
- trackOutfitItemClick: Track outfit item click
- trackSimilarProductClick: Track similar product click
Search Events
- trackSearchQuery: Track search query
- trackFilterApplied: Track filter applied
- trackSortChanged: Track sort changed
Conversion Events
- trackAddToCart: Track add to cart
- trackSearchAddToCart: Track add to cart from search flow
- trackOutfitAddToCart: Track add to cart from outfit flow
- trackSimilarAddToCart: Track add to cart from similar products flow
- trackPurchase: Track purchase
- trackSaveForLater: Track save for later
Generic Event Tracking
- trackEvent: Track custom event
Cross-Device Tracking
The SDK supports cross-device tracking by using persistent identifiers.
Changelog
- v1.0.0: Initial release
- v1.1.0: Added support for cross-device tracking
- v1.2.0: Added support for manual event tracking
- v1.3.0: Added support for event batching and flushing
- v1.4.0: Added support for tracking dynamically loaded content
- v1.5.0: Added support for custom tracking wrappers
- v1.6.0: Added support for event types and required fields
- v1.7.0: Added default flow types for all event methods