search-collector-js
v1.1.1
Published
JavaScript library for search collection that works in both browser and Node.js environments
Maintainers
Readme
search-collector-js
Features
- Singleton API - Simple, plug-and-play interface
- Fully Injectable - All components can be replaced with custom implementations
- TypeScript - Full type safety and IDE support
- UMD Build - Works in browser and Node.js
- Batching - Automatic event batching with configurable intervals
- Search Trail Tracking - Query-centric tracking model
Installation
npm install search-collector-jsQuick Start
Basic Usage
import {
configure,
initialize,
trackSearch,
trackProductClick,
} from 'search-collector-js';
// Configure with defaults
configure({
endpoint: 'https://your-endpoint-url',
channel: 'de',
});
// Initialize (sends browser event)
initialize();
// Track events
trackSearch({keywords: 'jacket', count: 42});
trackProductClick({productId: 'prod-123', position: 1, keywords: 'jacket'});Browser (UMD)
<script src="node_modules/search-collector-js/dist/search-collector-js.js"></script>
<script>
SearchCollector.configure({
endpoint: 'https://your-endpoint-url',
channel: 'de',
});
SearchCollector.initialize();
SearchCollector.trackSearch({keywords: 'shoes', count: 100});
</script>Architecture
The library is built on a modular architecture with injectable dependencies:
SearchCollectorCore
├── Transport → Handles event transmission
├── SessionStore → Manages session IDs (48h sliding window)
├── TrailStore → Tracks search trails (current/previous query)
├── EventQueue → Batches events (respects 10KB/10 events limits)
├── ContextProvider → Provides URL, referrer, user agent, etc.
└── TimestampProvider → Provides timestampsCustom Implementations
All components can be replaced with custom implementations:
import {
configure,
SimpleBatchQueue,
InMemoryTrailStore,
ManualContextProvider,
SingleSessionStore,
} from 'search-collector-js';
const customSession = new SingleSessionStore();
const customTrailStore = new InMemoryTrailStore();
const customContext = new ManualContextProvider(
'https://example.com',
'https://google.com',
'Custom User Agent',
false,
'de-DE'
);
configure({
endpoint: 'https://your-endpoint-url',
channel: 'de',
overrides: {
sessionStore: customSession,
trailStore: customTrailStore,
contextProvider: customContext,
eventQueue: new SimpleBatchQueue(20),
},
});Available Implementations
Transport
ShSqsTransport- AWS SQS transport for searchHub
SessionStore
CookieSessionStore- Browser cookies (default in browser runtime)LocalStorageSessionStore- Browser localStorageSingleSessionStore- Memory-based session store (default in non-browser runtime)
TrailStore
BrowserTrailStore- localStorage/sessionStorage-backed (default in browser runtime)InMemoryTrailStore- memory-backed (default in non-browser runtime)
EventQueue
SimpleBatchQueue- Batches events with 10KB/10 events limits (in-memory)LocalStorageEventQueue- Persists events in localStorage, survives page reloads
ContextProvider
BrowserContextProvider- Auto-detects browser context (default)ManualContextProvider- Manual context for Node.js
TimestampProvider
SystemTimestampProvider- UsesDate.now()
Event Persistence
The LocalStorageEventQueue provides automatic event persistence in the browser. Events are stored in localStorage
and survive page reloads, browser crashes, or network issues.
Using LocalStorageEventQueue
import {
configure,
LocalStorageEventQueue,
} from 'search-collector-js';
const eventQueue = new LocalStorageEventQueue(undefined, 10);
configure({
endpoint: 'https://my-queue-url',
channel: 'de',
overrides: {eventQueue},
});Benefits
- Reliability: Events are not lost if the page is closed before sending
- Offline Support: Events accumulate in localStorage when offline
- Automatic Recovery: On next page load, queued events are automatically sent
- Storage Key: Events are stored under
search-collector-queue(orsearch-collector-queue-<id>)
How It Works
- Events are immediately written to localStorage on
enqueue() - Events are batched and sent during
flush()(manual or auto) - After successful transmission, events are removed from localStorage
- If sending fails, events remain in localStorage for retry
- On page load, any existing events are loaded and queued for sending
Event Tracking API
Session Events
initialize() // Sends browser event with user agent, touch, languageSearch Events
trackInstantSearch({keywords: string})
trackFiredSearch({keywords: string})
trackSuggestClick({keywords: string, prefix: string, position: number})
trackSuggestProductClick({keywords: string, prefix: string, position: number, productId: string})
trackSearch({keywords: string, count: number, action? : SearchAction})
trackRedirect({keywords: string, resultCount: number})Product Events
trackImpression({products: Array < {id: string; position: number} >})
trackProductClick({productId: string, position: number, keywords: string})
trackAssociatedProductClick({productId: string, position: number, keywords: string})Conversion Events
trackBasket({productId: string, price: number})
trackCheckout({products: Array < {id: string; price: number; quantity: number} >})Utility Functions
flush() // Force-send queued events
registerTrail({key: string, query: string | Query, trailType? : TrailType})
copyTrail({fromProductId: string, toProductId: string}) // Copy trail to variant
reset() // Reset singleton instanceConfiguration Options
interface SearchCollectorConfig {
endpoint: string; // Required: Transport endpoint
channel: string; // Required: Channel identifier (e.g., 'de', 'en')
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
logger?: Logger;
queueSettings?: {
batchInterval?: number; // Optional: Auto-flush interval in ms (default: 5000)
maxBatchSize?: number; // Optional: Max events per batch (default: 10)
};
// Injectable dependencies
overrides?: {
transport?: Transport;
sessionStore?: SessionStore;
trailStore?: TrailStore;
eventQueue?: EventQueue;
contextProvider?: ContextProvider;
timestampProvider?: TimestampProvider;
};
}Creating Custom Implementations
Custom Transport
import {Transport, SearchCollectorEvent} from 'search-collector-js';
class MyCustomTransport implements Transport {
async send(events: SearchCollectorEvent[]): Promise<void> {
// Implement your custom transport logic
await fetch('https://my-api.com/events', {
method: 'POST',
body: JSON.stringify(events)
});
}
}Custom SessionStore
import {SessionStore} from 'search-collector-js';
class MyCustomSessionStore implements SessionStore {
getOrCreateSessionId(): string {
// Return or create session ID
}
touch(): void {
// Update last activity timestamp
}
}Development
Install dependencies
npm installBuild
npm run buildRun example
npm run exampleLint
npm run lintLicense
MIT
