Polling Interval
How often the SDK checks PageSense for configuration updates. Default is 10 seconds.
Method
- .addPollingInterval(intervalInSeconds)
Parameter
Parameter | Type | Description |
intervalInSeconds | Integer | Polling frequency in seconds. |
Example
- const sdkOptions = new PageSenseSDKOptions()
- .addPollingInterval(60);
Things to watch:
Under 10 seconds → higher server load, more network traffic, increased resource usage.
Over 5 minutes → experiment config changes reach users with a noticeable delay.
30–120 seconds works well for most production setups.
Log Level
Sets the minimum severity for SDK logs. Only messages at or above this level are captured.
Method
.addLogLevel(logLevel)
Supported levels
TRACE · DEBUG · INFO · WARN · ERROR · FATAL
Example
- const sdkOptions = new PageSenseSDKOptions()
- .addLogLevel("DEBUG");
DEBUG captures everything from DEBUG upward. Good for development and production debugging.
Custom Logger
The SDK logs to the console by default. If your app uses an existing logging framework, plug it in via a custom logger that implements PageSenseLogger.
Method
- .addCustomLogger(customLogger)
Example
- const sdkOptions = new PageSenseSDKOptions()
- .addCustomLogger(customLogger);
Works with Winston, Bunyan, Pino, or any enterprise logging system.
Sample Implementation (Winston)
- const fs = require('fs');
- const FileSys = require('fs');
- const Path = require('path');
- const Winston = require('winston');
- const { PageSenseLogger } = require('@zohopagesense/pagesense-node-sdk');
- /**
- * FileSystemLogger — writes SDK logs to a file using Winston.
- * @implements PageSenseLogger
- */
- class FileSystemLogger extends PageSenseLogger {
- constructor() {
- super();
- const logDir = Path.join(__dirname, '../../tests/logs');
- if (!FileSys.existsSync(logDir)) {
- FileSys.mkdirSync(logDir, { recursive: true });
- }
- this.logFilePath = Path.join(logDir, 'pagesense_custom_activity_log.log');
- if (!FileSys.existsSync(this.logFilePath)) {
- FileSys.writeFileSync(this.logFilePath, '');
- FileSys.chmodSync(this.logFilePath, 0o666);
- }
- this.logger = Winston.createLogger({
- level: 'debug',
- format: Winston.format.combine(
- Winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
- Winston.format.printf(
- ({ timestamp, level, message, className }) =>
- `[${timestamp}] [${className}] [${level.toUpperCase()}] ${message}`
- )
- ),
- transports: [
- new Winston.transports.File({
- filename: this.logFilePath,
- level: 'debug'
- })
- ]
- });
- }
- writeLog(levelName, message, className) {
- this.logger.log({ level: levelName.toLowerCase(), message, className });
- }
- trace(className, logMessage) { this.writeLog('silly', logMessage, className); }
- debug(className, logMessage) { this.writeLog('debug', logMessage, className); }
- info(className, logMessage) { this.writeLog('info', logMessage, className); }
- warning(className, logMessage) { this.writeLog('warn', logMessage, className); }
- error(className, logMessage) { this.writeLog('error', logMessage, className); }
- fatal(className, logMessage) { this.writeLog('error', logMessage, className); }
- // Winston doesn't have a FATAL level — mapped to error.
- }
- module.exports = FileSystemLogger;
User Storage Service
The User Storage Service (USS) saves variation assignments so users see the same variation across sessions — even if experiment configurations change between visits.
Without USS, the SDK recalculates assignments from scratch each time using MurmurHash. That works fine until you add a variation or adjust traffic splits — at which point some users may shift to a different variation mid-experiment.
Method
- .addCustomStorage(userStorageService)
Example
- const sdkOptions = new PageSenseSDKOptions()
- .addCustomStorage(userStorageService);
Your implementation must follow the UserStorageService interface — two methods: look up an existing assignment, save a new one. Storage options include JSON files, relational databases, Redis, and cloud storage.
Sample Implementation (File-based)
- const fs = require('fs');
- const path = require('path');
- const Winston = require('winston');
- const { UserStorageService } = require('@zohopagesense/pagesense-node-sdk');
- /**
- * FileUserStorageService — stores experiment–variation mappings in a JSON file.
- * @implements UserStorageService
- */
- class FileUserStorageService extends UserStorageService {
- constructor(storageDirectory) {
- super();
- this.storageDir = storageDirectory;
- this.userFile = path.join(storageDirectory, 'user_storage.json');
- this.logFile = path.join(storageDirectory, 'user_storage.log');
- this.initializeStorage();
- this.initializeLogger();
- }
- initializeStorage() {
- if (!fs.existsSync(this.storageDir)) {
- fs.mkdirSync(this.storageDir, { recursive: true });
- }
- if (!fs.existsSync(this.userFile)) {
- fs.writeFileSync(this.userFile, JSON.stringify({}, null, 2));
- }
- }
- initializeLogger() {
- this.logger = Winston.createLogger({
- level: 'info',
- format: Winston.format.combine(Winston.format.timestamp(), Winston.format.json()),
- transports: [new Winston.transports.File({ filename: this.logFile })]
- });
- }
- lookUp(userId) {
- if (!fs.existsSync(this.userFile)) return null;
- const data = this.safeJsonDecode(fs.readFileSync(this.userFile, 'utf8'));
- return data && data[userId] ? JSON.stringify(data[userId]) : null;
- }
- async save(userProfile) {
- const userId = userProfile.getUserId();
- const profileData = this.safeJsonDecode(userProfile.getUserProfileJSONString());
- if (!profileData) return;
- const fileContent = await fs.promises.readFile(this.userFile, 'utf8').catch(() => '{}');
- const existingData = this.safeJsonDecode(fileContent) || {};
- existingData[userId] = profileData;
- await fs.promises.writeFile(this.userFile, JSON.stringify(existingData, null, 2));
- }
- safeJsonDecode(jsonString) {
- try { return jsonString ? JSON.parse(jsonString) : null; }
- catch { return null; }
- }
- }
- module.exports = FileUserStorageService;
What the storage file looks like
- {
- "User123": {
- "userId": "User123",
- "experiments": [
- {
- "experiment_key": "expkey0001",
- "variation_key": "varkey001"
- }
- ]
- }
- }
We’ve
designed this documentation to guide you every step of the way. If you
need further assistance or have any questions, don’t hesitate to contact
us at
support@zohopagesense.com - we’re always here to help!