Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@amplitude/session-replay-browser

Package Overview
Dependencies
Maintainers
21
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@amplitude/session-replay-browser - npm Package Compare versions

Comparing version 1.13.0 to 1.14.0-srtargeting.0

lib/cjs/targeting/targeting-idb-store.d.ts

25

lib/cjs/config/joined-config.js

@@ -62,3 +62,3 @@ var _this = this;

return tslib_1.__awaiter(this, void 0, void 0, function () {
var config, remoteConfig, samplingConfig_1, privacyConfig, _d, err_1, knownError, samplingConfig, remotePrivacyConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap, _e, _f, _g, selector, selectorType;
var config, remoteConfig, samplingConfig_1, privacyConfig, targetingConfig_1, _d, err_1, knownError, samplingConfig, remotePrivacyConfig, targetingConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap, _e, _f, _g, selector, selectorType;
var e_1, _h;

@@ -76,3 +76,3 @@ return tslib_1.__generator(this, function (_j) {

case 1:
_j.trys.push([1, 5, , 6]);
_j.trys.push([1, 6, , 7]);
if (!this.remoteConfigFetch) {

@@ -88,6 +88,9 @@ config.captureEnabled = false;

privacyConfig = _j.sent();
return [4 /*yield*/, this.remoteConfigFetch.getRemoteConfig('sessionReplay', 'sr_targeting_config', sessionId)];
case 4:
targetingConfig_1 = _j.sent();
// This is intentionally forced to only be set through the remote config.
_d = config;
return [4 /*yield*/, this.remoteConfigFetch.getRemoteConfig('sessionReplay', 'sr_interaction_config', sessionId)];
case 4:
case 5:
// This is intentionally forced to only be set through the remote config.

@@ -103,5 +106,8 @@ _d.interactionConfig = _j.sent();

}
if (targetingConfig_1) {
remoteConfig.sr_targeting_config = targetingConfig_1;
}
}
return [3 /*break*/, 6];
case 5:
return [3 /*break*/, 7];
case 6:
err_1 = _j.sent();

@@ -111,8 +117,8 @@ knownError = err_1;

config.captureEnabled = false;
return [3 /*break*/, 6];
case 6:
return [3 /*break*/, 7];
case 7:
if (!remoteConfig) {
return [2 /*return*/, config];
}
samplingConfig = remoteConfig.sr_sampling_config, remotePrivacyConfig = remoteConfig.sr_privacy_config;
samplingConfig = remoteConfig.sr_sampling_config, remotePrivacyConfig = remoteConfig.sr_privacy_config, targetingConfig = remoteConfig.sr_targeting_config;
if (samplingConfig && Object.keys(samplingConfig).length > 0) {

@@ -229,2 +235,5 @@ if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {

}
if (targetingConfig && Object.keys(targetingConfig).length > 0) {
config.targetingConfig = targetingConfig;
}
this.localConfig.loggerProvider.debug(JSON.stringify({ name: 'session replay joined config', config: (0, helpers_1.getDebugConfig)(config) }, null, 2));

@@ -231,0 +240,0 @@ return [2 /*return*/, config];

import { Config, LogLevel, Logger } from '@amplitude/analytics-types';
import { TargetingFlag } from '@amplitude/targeting';
export interface SamplingConfig {

@@ -10,2 +11,3 @@ sample_rate: number;

}
export type TargetingConfig = TargetingFlag;
export type SessionReplayRemoteConfig = {

@@ -15,2 +17,3 @@ sr_sampling_config?: SamplingConfig;

sr_interaction_config?: InteractionConfig;
sr_targeting_config?: TargetingConfig;
};

@@ -41,2 +44,5 @@ export interface SessionReplayRemoteConfigAPIResponse {

version?: SessionReplayVersion;
userProperties?: {
[key: string]: any;
};
}

@@ -46,2 +52,3 @@ export interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {

interactionConfig?: InteractionConfig;
targetingConfig?: TargetingConfig;
}

@@ -48,0 +55,0 @@ export interface SessionReplayRemoteConfigFetch {

@@ -23,2 +23,6 @@ import { ServerZone } from '@amplitude/analytics-types';

export declare const KB_SIZE = 1024;
export declare enum CustomRRwebEvent {
GET_SR_PROPS = "get-sr-props",
DEBUG_INFO = "debug-info"
}
//# sourceMappingURL=constants.d.ts.map
Object.defineProperty(exports, "__esModule", { value: true });
exports.KB_SIZE = exports.MAX_IDB_STORAGE_LENGTH = exports.MAX_INTERVAL = exports.MIN_INTERVAL = exports.INTERACTION_MAX_INTERVAL = exports.INTERACTION_MIN_INTERVAL = exports.MAX_EVENT_LIST_SIZE_IN_BYTES = exports.STORAGE_PREFIX = exports.SESSION_REPLAY_STAGING_URL = exports.SESSION_REPLAY_EU_URL = exports.SESSION_REPLAY_SERVER_URL = exports.UNMASK_TEXT_CLASS = exports.MASK_TEXT_CLASS = exports.BLOCK_CLASS = exports.SESSION_REPLAY_DEBUG_PROPERTY = exports.DEFAULT_SERVER_ZONE = exports.DEFAULT_SAMPLE_RATE = exports.DEFAULT_SESSION_END_EVENT = exports.DEFAULT_SESSION_START_EVENT = exports.DEFAULT_SESSION_REPLAY_PROPERTY = exports.DEFAULT_EVENT_PROPERTY_PREFIX = void 0;
exports.CustomRRwebEvent = exports.KB_SIZE = exports.MAX_IDB_STORAGE_LENGTH = exports.MAX_INTERVAL = exports.MIN_INTERVAL = exports.INTERACTION_MAX_INTERVAL = exports.INTERACTION_MIN_INTERVAL = exports.MAX_EVENT_LIST_SIZE_IN_BYTES = exports.STORAGE_PREFIX = exports.SESSION_REPLAY_STAGING_URL = exports.SESSION_REPLAY_EU_URL = exports.SESSION_REPLAY_SERVER_URL = exports.UNMASK_TEXT_CLASS = exports.MASK_TEXT_CLASS = exports.BLOCK_CLASS = exports.SESSION_REPLAY_DEBUG_PROPERTY = exports.DEFAULT_SERVER_ZONE = exports.DEFAULT_SAMPLE_RATE = exports.DEFAULT_SESSION_END_EVENT = exports.DEFAULT_SESSION_START_EVENT = exports.DEFAULT_SESSION_REPLAY_PROPERTY = exports.DEFAULT_EVENT_PROPERTY_PREFIX = void 0;
var analytics_core_1 = require("@amplitude/analytics-core");

@@ -26,2 +26,7 @@ var analytics_types_1 = require("@amplitude/analytics-types");

exports.KB_SIZE = 1024;
var CustomRRwebEvent;
(function (CustomRRwebEvent) {
CustomRRwebEvent["GET_SR_PROPS"] = "get-sr-props";
CustomRRwebEvent["DEBUG_INFO"] = "debug-info";
})(CustomRRwebEvent = exports.CustomRRwebEvent || (exports.CustomRRwebEvent = {}));
//# sourceMappingURL=constants.js.map

@@ -14,2 +14,3 @@ import { PrivacyConfig, SessionReplayJoinedConfig } from './config/types';

interactionConfig?: import("./config/types").InteractionConfig | undefined;
targetingConfig?: import("@amplitude/experiment-core").EvaluationFlag | undefined;
apiKey: string;

@@ -25,2 +26,5 @@ loggerProvider: import("@amplitude/analytics-types").Logger;

version?: import("./config/types").SessionReplayVersion | undefined;
userProperties?: {
[key: string]: any;
} | undefined;
flushIntervalMillis: number;

@@ -27,0 +31,0 @@ flushQueueSize: number;

@@ -121,6 +121,7 @@ var _this = this;

var getStorageSize = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var globalScope, _a, usage, quota, usageDetails, totalStorageSize, percentOfQuota;
var globalScope, _a, usage, quota, usageDetails, totalStorageSize, percentOfQuota, e_1;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 3, , 4]);
globalScope = (0, analytics_client_common_1.getGlobalScope)();

@@ -134,3 +135,7 @@ if (!globalScope) return [3 /*break*/, 2];

return [2 /*return*/, { totalStorageSize: totalStorageSize, percentOfQuota: percentOfQuota, usageDetails: JSON.stringify(usageDetails) }];
case 2: return [2 /*return*/, { totalStorageSize: 0, percentOfQuota: 0, usageDetails: '' }];
case 2: return [3 /*break*/, 4];
case 3:
e_1 = _b.sent();
return [3 /*break*/, 4];
case 4: return [2 /*return*/, { totalStorageSize: 0, percentOfQuota: 0, usageDetails: '' }];
}

@@ -137,0 +142,0 @@ });

@@ -1,2 +0,6 @@

export declare const init: (apiKey: string, options: import("./typings/session-replay").SessionReplayOptions) => import("@amplitude/analytics-types").AmplitudeReturn<void>, setSessionId: (sessionId: number, deviceId?: string | undefined) => import("@amplitude/analytics-types").AmplitudeReturn<void>, getSessionId: () => number | undefined, getSessionReplayProperties: () => {
export declare const init: (apiKey: string, options: import("./typings/session-replay").SessionReplayOptions) => import("@amplitude/analytics-types").AmplitudeReturn<void>, setSessionId: (sessionId: number, deviceId?: string | undefined, options?: {
userProperties?: {
[key: string]: any;
} | undefined;
} | undefined) => import("@amplitude/analytics-types").AmplitudeReturn<void>, getSessionId: () => number | undefined, evaluateTargetingAndCapture: (targetingParams?: Pick<import("@amplitude/targeting").TargetingParameters, "event" | "userProperties"> | undefined) => Promise<void>, getSessionReplayProperties: () => {
[key: string]: string | boolean | null;

@@ -3,0 +7,0 @@ }, flush: (useRetry: boolean) => Promise<void>, shutdown: () => void;

Object.defineProperty(exports, "__esModule", { value: true });
exports.shutdown = exports.flush = exports.getSessionReplayProperties = exports.getSessionId = exports.setSessionId = exports.init = void 0;
exports.shutdown = exports.flush = exports.getSessionReplayProperties = exports.evaluateTargetingAndCapture = exports.getSessionId = exports.setSessionId = exports.init = void 0;
var tslib_1 = require("tslib");
var session_replay_factory_1 = tslib_1.__importDefault(require("./session-replay-factory"));
exports.init = session_replay_factory_1.default.init, exports.setSessionId = session_replay_factory_1.default.setSessionId, exports.getSessionId = session_replay_factory_1.default.getSessionId, exports.getSessionReplayProperties = session_replay_factory_1.default.getSessionReplayProperties, exports.flush = session_replay_factory_1.default.flush, exports.shutdown = session_replay_factory_1.default.shutdown;
exports.init = session_replay_factory_1.default.init, exports.setSessionId = session_replay_factory_1.default.setSessionId, exports.getSessionId = session_replay_factory_1.default.getSessionId, exports.evaluateTargetingAndCapture = session_replay_factory_1.default.evaluateTargetingAndCapture, exports.getSessionReplayProperties = session_replay_factory_1.default.getSessionReplayProperties, exports.flush = session_replay_factory_1.default.flush, exports.shutdown = session_replay_factory_1.default.shutdown;
//# sourceMappingURL=index.js.map

@@ -19,4 +19,5 @@ Object.defineProperty(exports, "__esModule", { value: true });

init: (0, analytics_core_1.debugWrapper)(sessionReplay.init.bind(sessionReplay), 'init', (0, exports.getLogConfig)(sessionReplay)),
evaluateTargetingAndCapture: (0, analytics_core_1.debugWrapper)(sessionReplay.evaluateTargetingAndCapture.bind(sessionReplay), 'evaluateTargetingAndRecord', (0, exports.getLogConfig)(sessionReplay)),
setSessionId: (0, analytics_core_1.debugWrapper)(sessionReplay.setSessionId.bind(sessionReplay), 'setSessionId', (0, exports.getLogConfig)(sessionReplay)),
getSessionId: (0, analytics_core_1.debugWrapper)(sessionReplay.getSessionId.bind(sessionReplay), 'getSessionId', (0, exports.getLogConfig)(sessionReplay)),
getSessionId: sessionReplay.getSessionId.bind(sessionReplay),
getSessionReplayProperties: (0, analytics_core_1.debugWrapper)(sessionReplay.getSessionReplayProperties.bind(sessionReplay), 'getSessionReplayProperties', (0, exports.getLogConfig)(sessionReplay)),

@@ -23,0 +24,0 @@ flush: (0, analytics_core_1.debugWrapper)(sessionReplay.flush.bind(sessionReplay), 'flush', (0, exports.getLogConfig)(sessionReplay)),

import { Logger as ILogger } from '@amplitude/analytics-types';
import { record } from '@amplitude/rrweb';
import { TargetingParameters } from '@amplitude/targeting';
import { SessionReplayJoinedConfig, SessionReplayJoinedConfigGenerator } from './config/types';
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, DebugInfo, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
import { CustomRRwebEvent } from './constants';
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
type PageLeaveFn = (e: PageTransitionEvent | Event) => void;

@@ -14,2 +16,4 @@ export declare class SessionReplay implements AmplitudeSessionReplay {

recordCancelCallback: ReturnType<typeof record> | null;
eventCount: number;
sessionTargetingMatch: boolean;
pageLeaveFns: PageLeaveFn[];

@@ -21,4 +25,12 @@ private scrollHook?;

protected _init(apiKey: string, options: SessionReplayOptions): Promise<void>;
setSessionId(sessionId: number, deviceId?: string): import("@amplitude/analytics-types").AmplitudeReturn<void>;
asyncSetSessionId(sessionId: number, deviceId?: string): Promise<void>;
setSessionId(sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}): import("@amplitude/analytics-types").AmplitudeReturn<void>;
asyncSetSessionId(sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}): Promise<void>;
getSessionReplayDebugPropertyValue(): string;

@@ -36,14 +48,12 @@ getSessionReplayProperties(): {

private pageLeaveListener;
evaluateTargetingAndCapture: (targetingParams?: Pick<TargetingParameters, 'event' | 'userProperties'>) => Promise<void>;
sendEvents(sessionId?: number): void;
initialize(shouldSendStoredEvents?: boolean): void;
shouldOptOut(): boolean | undefined;
getShouldRecord(): boolean;
getShouldCapture(): boolean;
getBlockSelectors(): string | string[] | undefined;
getMaskTextSelectors(): string | undefined;
recordEvents(): void;
/**
* Used to send a debug RRWeb event. Typing is included for ease of debugging later on, but probably not
* used at compile/run time.
*/
getDebugInfo: () => Promise<DebugInfo | undefined>;
captureEvents(): void;
addCustomRRWebEvent: (eventName: CustomRRwebEvent, eventData?: {
[key: string]: any;
}, addStorageInfo?: boolean) => Promise<void>;
stopRecordingEvents: () => void;

@@ -50,0 +60,0 @@ getDeviceId(): string | undefined;

@@ -6,2 +6,3 @@ Object.defineProperty(exports, "__esModule", { value: true });

var analytics_core_1 = require("@amplitude/analytics-core");
var analytics_types_1 = require("@amplitude/analytics-types");
var rrweb_1 = require("@amplitude/rrweb");

@@ -16,2 +17,3 @@ var joined_config_1 = require("./config/joined-config");

var identifiers_1 = require("./identifiers");
var targeting_manager_1 = require("./targeting/targeting-manager");
var version_1 = require("./version");

@@ -23,2 +25,4 @@ var SessionReplay = /** @class */ (function () {

this.recordCancelCallback = null;
this.eventCount = 0;
this.sessionTargetingMatch = false;
// Visible for testing

@@ -53,3 +57,4 @@ this.pageLeaveFns = [];

// switches tabs, we take a full snapshot
_this.recordEvents();
_this.stopRecordingEvents();
_this.captureEvents();
};

@@ -66,24 +71,89 @@ /**

};
/**
* Used to send a debug RRWeb event. Typing is included for ease of debugging later on, but probably not
* used at compile/run time.
*/
this.getDebugInfo = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var storageSizeData;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
this.evaluateTargetingAndCapture = function (targetingParams) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var eventForTargeting, _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!this.config) {
if (!this.identifiers || !this.identifiers.sessionId || !this.config) {
if (this.identifiers && !this.identifiers.sessionId) {
this.loggerProvider.log('Session ID has not been set yet, cannot evaluate targeting for Session Replay.');
}
else {
this.loggerProvider.warn('Session replay init has not been called, cannot evaluate targeting.');
}
return [2 /*return*/];
}
return [4 /*yield*/, (0, helpers_1.getStorageSize)()];
if (!(this.config.targetingConfig && !this.sessionTargetingMatch)) return [3 /*break*/, 2];
eventForTargeting = targetingParams === null || targetingParams === void 0 ? void 0 : targetingParams.event;
if (eventForTargeting &&
Object.values(analytics_types_1.SpecialEventType).includes(eventForTargeting.event_type)) {
eventForTargeting = undefined;
}
// We're setting this on this class because fetching the value from idb
// is async, we need to access this value synchronously (for record
// and for getSessionReplayProperties - both synchronous fns)
_a = this;
return [4 /*yield*/, (0, targeting_manager_1.evaluateTargetingAndStore)({
sessionId: this.identifiers.sessionId,
targetingConfig: this.config.targetingConfig,
loggerProvider: this.loggerProvider,
apiKey: this.config.apiKey,
targetingParams: { userProperties: targetingParams === null || targetingParams === void 0 ? void 0 : targetingParams.userProperties, event: eventForTargeting },
})];
case 1:
storageSizeData = _a.sent();
return [2 /*return*/, tslib_1.__assign(tslib_1.__assign({}, storageSizeData), { config: (0, helpers_1.getDebugConfig)(this.config), version: version_1.VERSION })];
// We're setting this on this class because fetching the value from idb
// is async, we need to access this value synchronously (for record
// and for getSessionReplayProperties - both synchronous fns)
_a.sessionTargetingMatch = _b.sent();
_b.label = 2;
case 2:
this.captureEvents();
return [2 /*return*/];
}
});
}); };
this.addCustomRRWebEvent = function (eventName, eventData, addStorageInfo) {
if (eventData === void 0) { eventData = {}; }
if (addStorageInfo === void 0) { addStorageInfo = true; }
return tslib_1.__awaiter(_this, void 0, void 0, function () {
var debugInfo, storageSizeData, e_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 3, , 4]);
debugInfo = undefined;
if (!this.config) return [3 /*break*/, 2];
debugInfo = {
config: (0, helpers_1.getDebugConfig)(this.config),
version: version_1.VERSION,
};
if (!addStorageInfo) return [3 /*break*/, 2];
return [4 /*yield*/, (0, helpers_1.getStorageSize)()];
case 1:
storageSizeData = _a.sent();
debugInfo = tslib_1.__assign(tslib_1.__assign({}, storageSizeData), debugInfo);
_a.label = 2;
case 2:
// Check first to ensure we are recording
if (this.recordCancelCallback) {
rrweb_1.record.addCustomEvent(eventName, tslib_1.__assign(tslib_1.__assign({}, eventData), debugInfo));
}
else {
this.loggerProvider.debug("Not able to add custom replay capture event ".concat(eventName, " due to no ongoing recording."));
}
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
this.loggerProvider.debug('Error while adding custom replay capture event: ', e_1);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
};
this.stopRecordingEvents = function () {
try {
_this.loggerProvider.log('Session Replay capture stopping.');
if (_this.recordCancelCallback) {
_this.loggerProvider.log('Session Replay capture stopping.');
}
_this.recordCancelCallback && _this.recordCancelCallback();

@@ -153,5 +223,12 @@ _this.recordCancelCallback = null;

this.eventsManager = new (multi_manager_1.MultiEventManager.bind.apply(multi_manager_1.MultiEventManager, tslib_1.__spreadArray([void 0], tslib_1.__read(managers), false)))();
this.identifiers.deviceId &&
void this.eventsManager.sendStoredEvents({
deviceId: this.identifiers.deviceId,
});
this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
this.teardownEventListeners(false);
this.initialize(true);
this.stopRecordingEvents();
return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options.userProperties })];
case 6:
_f.sent();
return [2 /*return*/];

@@ -162,6 +239,6 @@ }

};
SessionReplay.prototype.setSessionId = function (sessionId, deviceId) {
return (0, analytics_core_1.returnWrapper)(this.asyncSetSessionId(sessionId, deviceId));
SessionReplay.prototype.setSessionId = function (sessionId, deviceId, options) {
return (0, analytics_core_1.returnWrapper)(this.asyncSetSessionId(sessionId, deviceId, options));
};
SessionReplay.prototype.asyncSetSessionId = function (sessionId, deviceId) {
SessionReplay.prototype.asyncSetSessionId = function (sessionId, deviceId, options) {
return tslib_1.__awaiter(this, void 0, void 0, function () {

@@ -172,2 +249,4 @@ var previousSessionId, deviceIdForReplayId, _a;

case 0:
this.stopRecordingEvents();
this.sessionTargetingMatch = false;
previousSessionId = this.identifiers && this.identifiers.sessionId;

@@ -188,4 +267,5 @@ if (previousSessionId) {

_b.label = 2;
case 2:
this.recordEvents();
case 2: return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options === null || options === void 0 ? void 0 : options.userProperties })];
case 3:
_b.sent();
return [2 /*return*/];

@@ -211,5 +291,6 @@ }

}
var shouldRecord = this.getShouldRecord();
var shouldRecord = this.getShouldCapture();
var eventProperties = {};
if (shouldRecord) {
var eventProperties = (_a = {},
eventProperties = (_a = {},
_a[constants_1.DEFAULT_SESSION_REPLAY_PROPERTY] = this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,

@@ -220,5 +301,12 @@ _a);

}
return eventProperties;
}
return {};
void this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.GET_SR_PROPS, {
shouldRecord: shouldRecord,
eventProperties: eventProperties,
}, this.eventCount === 10);
if (this.eventCount === 10) {
this.eventCount = 0;
}
this.eventCount++;
return eventProperties;
};

@@ -234,17 +322,2 @@ SessionReplay.prototype.sendEvents = function (sessionId) {

};
SessionReplay.prototype.initialize = function (shouldSendStoredEvents) {
var _a;
if (shouldSendStoredEvents === void 0) { shouldSendStoredEvents = false; }
if (!((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId)) {
this.loggerProvider.log("Session is not being recorded due to lack of session id.");
return;
}
var deviceId = this.getDeviceId();
if (!deviceId) {
this.loggerProvider.log("Session is not being recorded due to lack of device id.");
return;
}
this.eventsManager && shouldSendStoredEvents && this.eventsManager.sendStoredEvents({ deviceId: deviceId });
this.recordEvents();
};
SessionReplay.prototype.shouldOptOut = function () {

@@ -259,5 +332,5 @@ var _a, _b;

};
SessionReplay.prototype.getShouldRecord = function () {
SessionReplay.prototype.getShouldCapture = function () {
if (!this.identifiers || !this.config || !this.identifiers.sessionId) {
this.loggerProvider.warn("Session is not being recorded due to lack of config, please call sessionReplay.init.");
this.loggerProvider.warn("Session is not being captured due to lack of config, please call sessionReplay.init.");
return false;

@@ -270,10 +343,23 @@ }

if (this.shouldOptOut()) {
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to optOut config."));
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of replay capture due to optOut config."));
return false;
}
var isInSample = (0, helpers_1.isSessionInSample)(this.identifiers.sessionId, this.config.sampleRate);
if (!isInSample) {
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to sample rate."));
// If targetingConfig exists, we'll use the sessionTargetingMatch to determine whether to record
// Otherwise, we'll evaluate the session against the overall sample rate
if (this.config.targetingConfig) {
if (!this.sessionTargetingMatch) {
this.loggerProvider.log("Not capturing replays for session ".concat(this.identifiers.sessionId, " due to not matching targeting conditions."));
return false;
}
this.loggerProvider.log("Capturing replays for session ".concat(this.identifiers.sessionId, " due to matching targeting conditions."));
}
return isInSample;
else {
var isInSample = (0, helpers_1.isSessionInSample)(this.identifiers.sessionId, this.config.sampleRate);
if (!isInSample) {
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of replay capture due to sample rate."));
return false;
}
this.loggerProvider.log("Capturing replays for session ".concat(this.identifiers.sessionId, " due to inclusion in sample rate."));
}
return true;
};

@@ -302,11 +388,13 @@ SessionReplay.prototype.getBlockSelectors = function () {

};
SessionReplay.prototype.recordEvents = function () {
SessionReplay.prototype.captureEvents = function () {
var _this = this;
var _a;
var shouldRecord = this.getShouldRecord();
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
if (this.recordCancelCallback) {
this.loggerProvider.debug('captureEvents method fired - Session Replay capture already in progress.');
return;
}
var shouldRecord = this.getShouldCapture();
var sessionId = this.identifiers && this.identifiers.sessionId;
if (!shouldRecord || !sessionId || !this.config) {
return;
}
this.stopRecordingEvents();
var privacyConfig = this.config.privacyConfig;

@@ -317,3 +405,3 @@ this.loggerProvider.log('Session Replay capture beginning.');

if (_this.shouldOptOut()) {
_this.loggerProvider.log("Opting session ".concat(sessionId, " out of recording due to optOut config."));
_this.loggerProvider.log("Opting session ".concat(sessionId, " out of replay capture due to optOut config."));
_this.stopRecordingEvents();

@@ -367,9 +455,3 @@ _this.sendEvents();

});
this.getDebugInfo()
.then(function (debugInfo) {
debugInfo && rrweb_1.record.addCustomEvent('debug-info', debugInfo);
})
.catch(function () {
// swallow error
});
void this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.DEBUG_INFO);
};

@@ -376,0 +458,0 @@ SessionReplay.prototype.getDeviceId = function () {

import { AmplitudeReturn, ServerZone } from '@amplitude/analytics-types';
import { SessionReplayJoinedConfig, SessionReplayLocalConfig, SessionReplayVersion } from '../config/types';
import { TargetingParameters } from '@amplitude/targeting';
export type StorageData = {

@@ -8,3 +9,3 @@ totalStorageSize: number;

};
export interface DebugInfo extends StorageData {
export interface DebugInfo extends Partial<StorageData> {
config: SessionReplayJoinedConfig;

@@ -63,3 +64,7 @@ version: string;

init: (apiKey: string, options: SessionReplayOptions) => AmplitudeReturn<void>;
setSessionId: (sessionId: number, deviceId?: string) => AmplitudeReturn<void>;
setSessionId: (sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}) => AmplitudeReturn<void>;
getSessionId: () => number | undefined;

@@ -69,2 +74,3 @@ getSessionReplayProperties: () => {

};
evaluateTargetingAndCapture: (targetingParams?: Pick<TargetingParameters, 'event' | 'userProperties'>) => Promise<void>;
flush: (useRetry: boolean) => Promise<void>;

@@ -71,0 +77,0 @@ shutdown: () => void;

@@ -1,2 +0,2 @@

export declare const VERSION = "1.13.0";
export declare const VERSION = "1.14.0-srtargeting.0";
//# sourceMappingURL=version.d.ts.map
Object.defineProperty(exports, "__esModule", { value: true });
exports.VERSION = void 0;
// Autogenerated by `yarn version-file`. DO NOT EDIT
exports.VERSION = '1.13.0';
exports.VERSION = '1.14.0-srtargeting.0';
//# sourceMappingURL=version.js.map

@@ -58,3 +58,3 @@ import { __assign, __awaiter, __generator, __read, __values } from "tslib";

return __awaiter(this, void 0, void 0, function () {
var config, remoteConfig, samplingConfig_1, privacyConfig, _d, err_1, knownError, samplingConfig, remotePrivacyConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap, _e, _f, _g, selector, selectorType;
var config, remoteConfig, samplingConfig_1, privacyConfig, targetingConfig_1, _d, err_1, knownError, samplingConfig, remotePrivacyConfig, targetingConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap, _e, _f, _g, selector, selectorType;
var e_1, _h;

@@ -72,3 +72,3 @@ return __generator(this, function (_j) {

case 1:
_j.trys.push([1, 5, , 6]);
_j.trys.push([1, 6, , 7]);
if (!this.remoteConfigFetch) {

@@ -84,6 +84,9 @@ config.captureEnabled = false;

privacyConfig = _j.sent();
return [4 /*yield*/, this.remoteConfigFetch.getRemoteConfig('sessionReplay', 'sr_targeting_config', sessionId)];
case 4:
targetingConfig_1 = _j.sent();
// This is intentionally forced to only be set through the remote config.
_d = config;
return [4 /*yield*/, this.remoteConfigFetch.getRemoteConfig('sessionReplay', 'sr_interaction_config', sessionId)];
case 4:
case 5:
// This is intentionally forced to only be set through the remote config.

@@ -99,5 +102,8 @@ _d.interactionConfig = _j.sent();

}
if (targetingConfig_1) {
remoteConfig.sr_targeting_config = targetingConfig_1;
}
}
return [3 /*break*/, 6];
case 5:
return [3 /*break*/, 7];
case 6:
err_1 = _j.sent();

@@ -107,8 +113,8 @@ knownError = err_1;

config.captureEnabled = false;
return [3 /*break*/, 6];
case 6:
return [3 /*break*/, 7];
case 7:
if (!remoteConfig) {
return [2 /*return*/, config];
}
samplingConfig = remoteConfig.sr_sampling_config, remotePrivacyConfig = remoteConfig.sr_privacy_config;
samplingConfig = remoteConfig.sr_sampling_config, remotePrivacyConfig = remoteConfig.sr_privacy_config, targetingConfig = remoteConfig.sr_targeting_config;
if (samplingConfig && Object.keys(samplingConfig).length > 0) {

@@ -225,2 +231,5 @@ if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {

}
if (targetingConfig && Object.keys(targetingConfig).length > 0) {
config.targetingConfig = targetingConfig;
}
this.localConfig.loggerProvider.debug(JSON.stringify({ name: 'session replay joined config', config: getDebugConfig(config) }, null, 2));

@@ -227,0 +236,0 @@ return [2 /*return*/, config];

import { Config, LogLevel, Logger } from '@amplitude/analytics-types';
import { TargetingFlag } from '@amplitude/targeting';
export interface SamplingConfig {

@@ -10,2 +11,3 @@ sample_rate: number;

}
export type TargetingConfig = TargetingFlag;
export type SessionReplayRemoteConfig = {

@@ -15,2 +17,3 @@ sr_sampling_config?: SamplingConfig;

sr_interaction_config?: InteractionConfig;
sr_targeting_config?: TargetingConfig;
};

@@ -41,2 +44,5 @@ export interface SessionReplayRemoteConfigAPIResponse {

version?: SessionReplayVersion;
userProperties?: {
[key: string]: any;
};
}

@@ -46,2 +52,3 @@ export interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {

interactionConfig?: InteractionConfig;
targetingConfig?: TargetingConfig;
}

@@ -48,0 +55,0 @@ export interface SessionReplayRemoteConfigFetch {

@@ -23,2 +23,6 @@ import { ServerZone } from '@amplitude/analytics-types';

export declare const KB_SIZE = 1024;
export declare enum CustomRRwebEvent {
GET_SR_PROPS = "get-sr-props",
DEBUG_INFO = "debug-info"
}
//# sourceMappingURL=constants.d.ts.map

@@ -24,2 +24,7 @@ import { AMPLITUDE_PREFIX } from '@amplitude/analytics-core';

export var KB_SIZE = 1024;
export var CustomRRwebEvent;
(function (CustomRRwebEvent) {
CustomRRwebEvent["GET_SR_PROPS"] = "get-sr-props";
CustomRRwebEvent["DEBUG_INFO"] = "debug-info";
})(CustomRRwebEvent || (CustomRRwebEvent = {}));
//# sourceMappingURL=constants.js.map

@@ -14,2 +14,3 @@ import { PrivacyConfig, SessionReplayJoinedConfig } from './config/types';

interactionConfig?: import("./config/types").InteractionConfig | undefined;
targetingConfig?: import("@amplitude/experiment-core").EvaluationFlag | undefined;
apiKey: string;

@@ -25,2 +26,5 @@ loggerProvider: import("@amplitude/analytics-types").Logger;

version?: import("./config/types").SessionReplayVersion | undefined;
userProperties?: {
[key: string]: any;
} | undefined;
flushIntervalMillis: number;

@@ -27,0 +31,0 @@ flushQueueSize: number;

@@ -112,6 +112,7 @@ import { __assign, __awaiter, __generator } from "tslib";

export var getStorageSize = function () { return __awaiter(void 0, void 0, void 0, function () {
var globalScope, _a, usage, quota, usageDetails, totalStorageSize, percentOfQuota;
var globalScope, _a, usage, quota, usageDetails, totalStorageSize, percentOfQuota, e_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 3, , 4]);
globalScope = getGlobalScope();

@@ -125,3 +126,7 @@ if (!globalScope) return [3 /*break*/, 2];

return [2 /*return*/, { totalStorageSize: totalStorageSize, percentOfQuota: percentOfQuota, usageDetails: JSON.stringify(usageDetails) }];
case 2: return [2 /*return*/, { totalStorageSize: 0, percentOfQuota: 0, usageDetails: '' }];
case 2: return [3 /*break*/, 4];
case 3:
e_1 = _b.sent();
return [3 /*break*/, 4];
case 4: return [2 /*return*/, { totalStorageSize: 0, percentOfQuota: 0, usageDetails: '' }];
}

@@ -128,0 +133,0 @@ });

@@ -1,2 +0,6 @@

export declare const init: (apiKey: string, options: import("./typings/session-replay").SessionReplayOptions) => import("@amplitude/analytics-types").AmplitudeReturn<void>, setSessionId: (sessionId: number, deviceId?: string | undefined) => import("@amplitude/analytics-types").AmplitudeReturn<void>, getSessionId: () => number | undefined, getSessionReplayProperties: () => {
export declare const init: (apiKey: string, options: import("./typings/session-replay").SessionReplayOptions) => import("@amplitude/analytics-types").AmplitudeReturn<void>, setSessionId: (sessionId: number, deviceId?: string | undefined, options?: {
userProperties?: {
[key: string]: any;
} | undefined;
} | undefined) => import("@amplitude/analytics-types").AmplitudeReturn<void>, getSessionId: () => number | undefined, evaluateTargetingAndCapture: (targetingParams?: Pick<import("@amplitude/targeting").TargetingParameters, "event" | "userProperties"> | undefined) => Promise<void>, getSessionReplayProperties: () => {
[key: string]: string | boolean | null;

@@ -3,0 +7,0 @@ }, flush: (useRetry: boolean) => Promise<void>, shutdown: () => void;

import sessionReplay from './session-replay-factory';
export var init = sessionReplay.init, setSessionId = sessionReplay.setSessionId, getSessionId = sessionReplay.getSessionId, getSessionReplayProperties = sessionReplay.getSessionReplayProperties, flush = sessionReplay.flush, shutdown = sessionReplay.shutdown;
export var init = sessionReplay.init, setSessionId = sessionReplay.setSessionId, getSessionId = sessionReplay.getSessionId, evaluateTargetingAndCapture = sessionReplay.evaluateTargetingAndCapture, getSessionReplayProperties = sessionReplay.getSessionReplayProperties, flush = sessionReplay.flush, shutdown = sessionReplay.shutdown;
//# sourceMappingURL=index.js.map

@@ -16,4 +16,5 @@ import { debugWrapper } from '@amplitude/analytics-core';

init: debugWrapper(sessionReplay.init.bind(sessionReplay), 'init', getLogConfig(sessionReplay)),
evaluateTargetingAndCapture: debugWrapper(sessionReplay.evaluateTargetingAndCapture.bind(sessionReplay), 'evaluateTargetingAndRecord', getLogConfig(sessionReplay)),
setSessionId: debugWrapper(sessionReplay.setSessionId.bind(sessionReplay), 'setSessionId', getLogConfig(sessionReplay)),
getSessionId: debugWrapper(sessionReplay.getSessionId.bind(sessionReplay), 'getSessionId', getLogConfig(sessionReplay)),
getSessionId: sessionReplay.getSessionId.bind(sessionReplay),
getSessionReplayProperties: debugWrapper(sessionReplay.getSessionReplayProperties.bind(sessionReplay), 'getSessionReplayProperties', getLogConfig(sessionReplay)),

@@ -20,0 +21,0 @@ flush: debugWrapper(sessionReplay.flush.bind(sessionReplay), 'flush', getLogConfig(sessionReplay)),

import { Logger as ILogger } from '@amplitude/analytics-types';
import { record } from '@amplitude/rrweb';
import { TargetingParameters } from '@amplitude/targeting';
import { SessionReplayJoinedConfig, SessionReplayJoinedConfigGenerator } from './config/types';
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, DebugInfo, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
import { CustomRRwebEvent } from './constants';
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
type PageLeaveFn = (e: PageTransitionEvent | Event) => void;

@@ -14,2 +16,4 @@ export declare class SessionReplay implements AmplitudeSessionReplay {

recordCancelCallback: ReturnType<typeof record> | null;
eventCount: number;
sessionTargetingMatch: boolean;
pageLeaveFns: PageLeaveFn[];

@@ -21,4 +25,12 @@ private scrollHook?;

protected _init(apiKey: string, options: SessionReplayOptions): Promise<void>;
setSessionId(sessionId: number, deviceId?: string): import("@amplitude/analytics-types").AmplitudeReturn<void>;
asyncSetSessionId(sessionId: number, deviceId?: string): Promise<void>;
setSessionId(sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}): import("@amplitude/analytics-types").AmplitudeReturn<void>;
asyncSetSessionId(sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}): Promise<void>;
getSessionReplayDebugPropertyValue(): string;

@@ -36,14 +48,12 @@ getSessionReplayProperties(): {

private pageLeaveListener;
evaluateTargetingAndCapture: (targetingParams?: Pick<TargetingParameters, 'event' | 'userProperties'>) => Promise<void>;
sendEvents(sessionId?: number): void;
initialize(shouldSendStoredEvents?: boolean): void;
shouldOptOut(): boolean | undefined;
getShouldRecord(): boolean;
getShouldCapture(): boolean;
getBlockSelectors(): string | string[] | undefined;
getMaskTextSelectors(): string | undefined;
recordEvents(): void;
/**
* Used to send a debug RRWeb event. Typing is included for ease of debugging later on, but probably not
* used at compile/run time.
*/
getDebugInfo: () => Promise<DebugInfo | undefined>;
captureEvents(): void;
addCustomRRWebEvent: (eventName: CustomRRwebEvent, eventData?: {
[key: string]: any;
}, addStorageInfo?: boolean) => Promise<void>;
stopRecordingEvents: () => void;

@@ -50,0 +60,0 @@ getDeviceId(): string | undefined;

import { __assign, __awaiter, __generator, __read, __spreadArray } from "tslib";
import { getAnalyticsConnector, getGlobalScope } from '@amplitude/analytics-client-common';
import { Logger, returnWrapper } from '@amplitude/analytics-core';
import { SpecialEventType } from '@amplitude/analytics-types';
import { pack, record } from '@amplitude/rrweb';
import { createSessionReplayJoinedConfigGenerator } from './config/joined-config';
import { BLOCK_CLASS, DEFAULT_SESSION_REPLAY_PROPERTY, INTERACTION_MAX_INTERVAL, INTERACTION_MIN_INTERVAL, MASK_TEXT_CLASS, SESSION_REPLAY_DEBUG_PROPERTY, } from './constants';
import { BLOCK_CLASS, CustomRRwebEvent, DEFAULT_SESSION_REPLAY_PROPERTY, INTERACTION_MAX_INTERVAL, INTERACTION_MIN_INTERVAL, MASK_TEXT_CLASS, SESSION_REPLAY_DEBUG_PROPERTY, } from './constants';
import { createEventsManager } from './events/events-manager';

@@ -13,2 +14,3 @@ import { MultiEventManager } from './events/multi-manager';

import { SessionIdentifiers } from './identifiers';
import { evaluateTargetingAndStore } from './targeting/targeting-manager';
import { VERSION } from './version';

@@ -20,2 +22,4 @@ var SessionReplay = /** @class */ (function () {

this.recordCancelCallback = null;
this.eventCount = 0;
this.sessionTargetingMatch = false;
// Visible for testing

@@ -50,3 +54,4 @@ this.pageLeaveFns = [];

// switches tabs, we take a full snapshot
_this.recordEvents();
_this.stopRecordingEvents();
_this.captureEvents();
};

@@ -63,24 +68,89 @@ /**

};
/**
* Used to send a debug RRWeb event. Typing is included for ease of debugging later on, but probably not
* used at compile/run time.
*/
this.getDebugInfo = function () { return __awaiter(_this, void 0, void 0, function () {
var storageSizeData;
return __generator(this, function (_a) {
switch (_a.label) {
this.evaluateTargetingAndCapture = function (targetingParams) { return __awaiter(_this, void 0, void 0, function () {
var eventForTargeting, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!this.config) {
if (!this.identifiers || !this.identifiers.sessionId || !this.config) {
if (this.identifiers && !this.identifiers.sessionId) {
this.loggerProvider.log('Session ID has not been set yet, cannot evaluate targeting for Session Replay.');
}
else {
this.loggerProvider.warn('Session replay init has not been called, cannot evaluate targeting.');
}
return [2 /*return*/];
}
return [4 /*yield*/, getStorageSize()];
if (!(this.config.targetingConfig && !this.sessionTargetingMatch)) return [3 /*break*/, 2];
eventForTargeting = targetingParams === null || targetingParams === void 0 ? void 0 : targetingParams.event;
if (eventForTargeting &&
Object.values(SpecialEventType).includes(eventForTargeting.event_type)) {
eventForTargeting = undefined;
}
// We're setting this on this class because fetching the value from idb
// is async, we need to access this value synchronously (for record
// and for getSessionReplayProperties - both synchronous fns)
_a = this;
return [4 /*yield*/, evaluateTargetingAndStore({
sessionId: this.identifiers.sessionId,
targetingConfig: this.config.targetingConfig,
loggerProvider: this.loggerProvider,
apiKey: this.config.apiKey,
targetingParams: { userProperties: targetingParams === null || targetingParams === void 0 ? void 0 : targetingParams.userProperties, event: eventForTargeting },
})];
case 1:
storageSizeData = _a.sent();
return [2 /*return*/, __assign(__assign({}, storageSizeData), { config: getDebugConfig(this.config), version: VERSION })];
// We're setting this on this class because fetching the value from idb
// is async, we need to access this value synchronously (for record
// and for getSessionReplayProperties - both synchronous fns)
_a.sessionTargetingMatch = _b.sent();
_b.label = 2;
case 2:
this.captureEvents();
return [2 /*return*/];
}
});
}); };
this.addCustomRRWebEvent = function (eventName, eventData, addStorageInfo) {
if (eventData === void 0) { eventData = {}; }
if (addStorageInfo === void 0) { addStorageInfo = true; }
return __awaiter(_this, void 0, void 0, function () {
var debugInfo, storageSizeData, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 3, , 4]);
debugInfo = undefined;
if (!this.config) return [3 /*break*/, 2];
debugInfo = {
config: getDebugConfig(this.config),
version: VERSION,
};
if (!addStorageInfo) return [3 /*break*/, 2];
return [4 /*yield*/, getStorageSize()];
case 1:
storageSizeData = _a.sent();
debugInfo = __assign(__assign({}, storageSizeData), debugInfo);
_a.label = 2;
case 2:
// Check first to ensure we are recording
if (this.recordCancelCallback) {
record.addCustomEvent(eventName, __assign(__assign({}, eventData), debugInfo));
}
else {
this.loggerProvider.debug("Not able to add custom replay capture event ".concat(eventName, " due to no ongoing recording."));
}
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
this.loggerProvider.debug('Error while adding custom replay capture event: ', e_1);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
};
this.stopRecordingEvents = function () {
try {
_this.loggerProvider.log('Session Replay capture stopping.');
if (_this.recordCancelCallback) {
_this.loggerProvider.log('Session Replay capture stopping.');
}
_this.recordCancelCallback && _this.recordCancelCallback();

@@ -150,5 +220,12 @@ _this.recordCancelCallback = null;

this.eventsManager = new (MultiEventManager.bind.apply(MultiEventManager, __spreadArray([void 0], __read(managers), false)))();
this.identifiers.deviceId &&
void this.eventsManager.sendStoredEvents({
deviceId: this.identifiers.deviceId,
});
this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
this.teardownEventListeners(false);
this.initialize(true);
this.stopRecordingEvents();
return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options.userProperties })];
case 6:
_f.sent();
return [2 /*return*/];

@@ -159,6 +236,6 @@ }

};
SessionReplay.prototype.setSessionId = function (sessionId, deviceId) {
return returnWrapper(this.asyncSetSessionId(sessionId, deviceId));
SessionReplay.prototype.setSessionId = function (sessionId, deviceId, options) {
return returnWrapper(this.asyncSetSessionId(sessionId, deviceId, options));
};
SessionReplay.prototype.asyncSetSessionId = function (sessionId, deviceId) {
SessionReplay.prototype.asyncSetSessionId = function (sessionId, deviceId, options) {
return __awaiter(this, void 0, void 0, function () {

@@ -169,2 +246,4 @@ var previousSessionId, deviceIdForReplayId, _a;

case 0:
this.stopRecordingEvents();
this.sessionTargetingMatch = false;
previousSessionId = this.identifiers && this.identifiers.sessionId;

@@ -185,4 +264,5 @@ if (previousSessionId) {

_b.label = 2;
case 2:
this.recordEvents();
case 2: return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options === null || options === void 0 ? void 0 : options.userProperties })];
case 3:
_b.sent();
return [2 /*return*/];

@@ -208,5 +288,6 @@ }

}
var shouldRecord = this.getShouldRecord();
var shouldRecord = this.getShouldCapture();
var eventProperties = {};
if (shouldRecord) {
var eventProperties = (_a = {},
eventProperties = (_a = {},
_a[DEFAULT_SESSION_REPLAY_PROPERTY] = this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,

@@ -217,5 +298,12 @@ _a);

}
return eventProperties;
}
return {};
void this.addCustomRRWebEvent(CustomRRwebEvent.GET_SR_PROPS, {
shouldRecord: shouldRecord,
eventProperties: eventProperties,
}, this.eventCount === 10);
if (this.eventCount === 10) {
this.eventCount = 0;
}
this.eventCount++;
return eventProperties;
};

@@ -231,17 +319,2 @@ SessionReplay.prototype.sendEvents = function (sessionId) {

};
SessionReplay.prototype.initialize = function (shouldSendStoredEvents) {
var _a;
if (shouldSendStoredEvents === void 0) { shouldSendStoredEvents = false; }
if (!((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId)) {
this.loggerProvider.log("Session is not being recorded due to lack of session id.");
return;
}
var deviceId = this.getDeviceId();
if (!deviceId) {
this.loggerProvider.log("Session is not being recorded due to lack of device id.");
return;
}
this.eventsManager && shouldSendStoredEvents && this.eventsManager.sendStoredEvents({ deviceId: deviceId });
this.recordEvents();
};
SessionReplay.prototype.shouldOptOut = function () {

@@ -256,5 +329,5 @@ var _a, _b;

};
SessionReplay.prototype.getShouldRecord = function () {
SessionReplay.prototype.getShouldCapture = function () {
if (!this.identifiers || !this.config || !this.identifiers.sessionId) {
this.loggerProvider.warn("Session is not being recorded due to lack of config, please call sessionReplay.init.");
this.loggerProvider.warn("Session is not being captured due to lack of config, please call sessionReplay.init.");
return false;

@@ -267,10 +340,23 @@ }

if (this.shouldOptOut()) {
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to optOut config."));
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of replay capture due to optOut config."));
return false;
}
var isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);
if (!isInSample) {
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to sample rate."));
// If targetingConfig exists, we'll use the sessionTargetingMatch to determine whether to record
// Otherwise, we'll evaluate the session against the overall sample rate
if (this.config.targetingConfig) {
if (!this.sessionTargetingMatch) {
this.loggerProvider.log("Not capturing replays for session ".concat(this.identifiers.sessionId, " due to not matching targeting conditions."));
return false;
}
this.loggerProvider.log("Capturing replays for session ".concat(this.identifiers.sessionId, " due to matching targeting conditions."));
}
return isInSample;
else {
var isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);
if (!isInSample) {
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of replay capture due to sample rate."));
return false;
}
this.loggerProvider.log("Capturing replays for session ".concat(this.identifiers.sessionId, " due to inclusion in sample rate."));
}
return true;
};

@@ -299,11 +385,13 @@ SessionReplay.prototype.getBlockSelectors = function () {

};
SessionReplay.prototype.recordEvents = function () {
SessionReplay.prototype.captureEvents = function () {
var _this = this;
var _a;
var shouldRecord = this.getShouldRecord();
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
if (this.recordCancelCallback) {
this.loggerProvider.debug('captureEvents method fired - Session Replay capture already in progress.');
return;
}
var shouldRecord = this.getShouldCapture();
var sessionId = this.identifiers && this.identifiers.sessionId;
if (!shouldRecord || !sessionId || !this.config) {
return;
}
this.stopRecordingEvents();
var privacyConfig = this.config.privacyConfig;

@@ -314,3 +402,3 @@ this.loggerProvider.log('Session Replay capture beginning.');

if (_this.shouldOptOut()) {
_this.loggerProvider.log("Opting session ".concat(sessionId, " out of recording due to optOut config."));
_this.loggerProvider.log("Opting session ".concat(sessionId, " out of replay capture due to optOut config."));
_this.stopRecordingEvents();

@@ -364,9 +452,3 @@ _this.sendEvents();

});
this.getDebugInfo()
.then(function (debugInfo) {
debugInfo && record.addCustomEvent('debug-info', debugInfo);
})
.catch(function () {
// swallow error
});
void this.addCustomRRWebEvent(CustomRRwebEvent.DEBUG_INFO);
};

@@ -373,0 +455,0 @@ SessionReplay.prototype.getDeviceId = function () {

import { AmplitudeReturn, ServerZone } from '@amplitude/analytics-types';
import { SessionReplayJoinedConfig, SessionReplayLocalConfig, SessionReplayVersion } from '../config/types';
import { TargetingParameters } from '@amplitude/targeting';
export type StorageData = {

@@ -8,3 +9,3 @@ totalStorageSize: number;

};
export interface DebugInfo extends StorageData {
export interface DebugInfo extends Partial<StorageData> {
config: SessionReplayJoinedConfig;

@@ -63,3 +64,7 @@ version: string;

init: (apiKey: string, options: SessionReplayOptions) => AmplitudeReturn<void>;
setSessionId: (sessionId: number, deviceId?: string) => AmplitudeReturn<void>;
setSessionId: (sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}) => AmplitudeReturn<void>;
getSessionId: () => number | undefined;

@@ -69,2 +74,3 @@ getSessionReplayProperties: () => {

};
evaluateTargetingAndCapture: (targetingParams?: Pick<TargetingParameters, 'event' | 'userProperties'>) => Promise<void>;
flush: (useRetry: boolean) => Promise<void>;

@@ -71,0 +77,0 @@ shutdown: () => void;

@@ -1,2 +0,2 @@

export declare const VERSION = "1.13.0";
export declare const VERSION = "1.14.0-srtargeting.0";
//# sourceMappingURL=version.d.ts.map
// Autogenerated by `yarn version-file`. DO NOT EDIT
export var VERSION = '1.13.0';
export var VERSION = '1.14.0-srtargeting.0';
//# sourceMappingURL=version.js.map
import { Config, LogLevel, Logger } from '@amplitude/analytics-types';
import { TargetingFlag } from '@amplitude/targeting';
export interface SamplingConfig {

@@ -10,2 +11,3 @@ sample_rate: number;

}
export type TargetingConfig = TargetingFlag;
export type SessionReplayRemoteConfig = {

@@ -15,2 +17,3 @@ sr_sampling_config?: SamplingConfig;

sr_interaction_config?: InteractionConfig;
sr_targeting_config?: TargetingConfig;
};

@@ -41,2 +44,5 @@ export interface SessionReplayRemoteConfigAPIResponse {

version?: SessionReplayVersion;
userProperties?: {
[key: string]: any;
};
}

@@ -46,2 +52,3 @@ export interface SessionReplayJoinedConfig extends SessionReplayLocalConfig {

interactionConfig?: InteractionConfig;
targetingConfig?: TargetingConfig;
}

@@ -48,0 +55,0 @@ export interface SessionReplayRemoteConfigFetch {

@@ -23,2 +23,6 @@ import { ServerZone } from '@amplitude/analytics-types';

export declare const KB_SIZE = 1024;
export declare enum CustomRRwebEvent {
GET_SR_PROPS = "get-sr-props",
DEBUG_INFO = "debug-info"
}
//# sourceMappingURL=constants.d.ts.map

@@ -14,2 +14,3 @@ import { PrivacyConfig, SessionReplayJoinedConfig } from './config/types';

interactionConfig?: import("./config/types").InteractionConfig | undefined;
targetingConfig?: import("@amplitude/experiment-core").EvaluationFlag | undefined;
apiKey: string;

@@ -25,2 +26,5 @@ loggerProvider: import("@amplitude/analytics-types").Logger;

version?: import("./config/types").SessionReplayVersion | undefined;
userProperties?: {
[key: string]: any;
} | undefined;
flushIntervalMillis: number;

@@ -27,0 +31,0 @@ flushQueueSize: number;

@@ -1,2 +0,6 @@

export declare const init: (apiKey: string, options: import("./typings/session-replay").SessionReplayOptions) => import("@amplitude/analytics-types").AmplitudeReturn<void>, setSessionId: (sessionId: number, deviceId?: string | undefined) => import("@amplitude/analytics-types").AmplitudeReturn<void>, getSessionId: () => number | undefined, getSessionReplayProperties: () => {
export declare const init: (apiKey: string, options: import("./typings/session-replay").SessionReplayOptions) => import("@amplitude/analytics-types").AmplitudeReturn<void>, setSessionId: (sessionId: number, deviceId?: string | undefined, options?: {
userProperties?: {
[key: string]: any;
} | undefined;
} | undefined) => import("@amplitude/analytics-types").AmplitudeReturn<void>, getSessionId: () => number | undefined, evaluateTargetingAndCapture: (targetingParams?: Pick<import("@amplitude/targeting").TargetingParameters, "userProperties" | "event"> | undefined) => Promise<void>, getSessionReplayProperties: () => {
[key: string]: string | boolean | null;

@@ -3,0 +7,0 @@ }, flush: (useRetry: boolean) => Promise<void>, shutdown: () => void;

import { Logger as ILogger } from '@amplitude/analytics-types';
import { record } from '@amplitude/rrweb';
import { TargetingParameters } from '@amplitude/targeting';
import { SessionReplayJoinedConfig, SessionReplayJoinedConfigGenerator } from './config/types';
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, DebugInfo, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
import { CustomRRwebEvent } from './constants';
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionIdentifiers as ISessionIdentifiers, SessionReplayOptions } from './typings/session-replay';
type PageLeaveFn = (e: PageTransitionEvent | Event) => void;

@@ -14,2 +16,4 @@ export declare class SessionReplay implements AmplitudeSessionReplay {

recordCancelCallback: ReturnType<typeof record> | null;
eventCount: number;
sessionTargetingMatch: boolean;
pageLeaveFns: PageLeaveFn[];

@@ -21,4 +25,12 @@ private scrollHook?;

protected _init(apiKey: string, options: SessionReplayOptions): Promise<void>;
setSessionId(sessionId: number, deviceId?: string): import("@amplitude/analytics-types").AmplitudeReturn<void>;
asyncSetSessionId(sessionId: number, deviceId?: string): Promise<void>;
setSessionId(sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}): import("@amplitude/analytics-types").AmplitudeReturn<void>;
asyncSetSessionId(sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}): Promise<void>;
getSessionReplayDebugPropertyValue(): string;

@@ -36,14 +48,12 @@ getSessionReplayProperties(): {

private pageLeaveListener;
evaluateTargetingAndCapture: (targetingParams?: Pick<TargetingParameters, 'event' | 'userProperties'>) => Promise<void>;
sendEvents(sessionId?: number): void;
initialize(shouldSendStoredEvents?: boolean): void;
shouldOptOut(): boolean | undefined;
getShouldRecord(): boolean;
getShouldCapture(): boolean;
getBlockSelectors(): string | string[] | undefined;
getMaskTextSelectors(): string | undefined;
recordEvents(): void;
/**
* Used to send a debug RRWeb event. Typing is included for ease of debugging later on, but probably not
* used at compile/run time.
*/
getDebugInfo: () => Promise<DebugInfo | undefined>;
captureEvents(): void;
addCustomRRWebEvent: (eventName: CustomRRwebEvent, eventData?: {
[key: string]: any;
}, addStorageInfo?: boolean) => Promise<void>;
stopRecordingEvents: () => void;

@@ -50,0 +60,0 @@ getDeviceId(): string | undefined;

import { AmplitudeReturn, ServerZone } from '@amplitude/analytics-types';
import { SessionReplayJoinedConfig, SessionReplayLocalConfig, SessionReplayVersion } from '../config/types';
import { TargetingParameters } from '@amplitude/targeting';
export type StorageData = {

@@ -8,3 +9,3 @@ totalStorageSize: number;

};
export interface DebugInfo extends StorageData {
export interface DebugInfo extends Partial<StorageData> {
config: SessionReplayJoinedConfig;

@@ -63,3 +64,7 @@ version: string;

init: (apiKey: string, options: SessionReplayOptions) => AmplitudeReturn<void>;
setSessionId: (sessionId: number, deviceId?: string) => AmplitudeReturn<void>;
setSessionId: (sessionId: number, deviceId?: string, options?: {
userProperties?: {
[key: string]: any;
};
}) => AmplitudeReturn<void>;
getSessionId: () => number | undefined;

@@ -69,2 +74,3 @@ getSessionReplayProperties: () => {

};
evaluateTargetingAndCapture: (targetingParams?: Pick<TargetingParameters, 'event' | 'userProperties'>) => Promise<void>;
flush: (useRetry: boolean) => Promise<void>;

@@ -71,0 +77,0 @@ shutdown: () => void;

@@ -1,2 +0,2 @@

export declare const VERSION = "1.13.0";
export declare const VERSION = "1.14.0-srtargeting.0";
//# sourceMappingURL=version.d.ts.map
{
"name": "@amplitude/session-replay-browser",
"version": "1.13.0",
"version": "1.14.0-srtargeting.0",
"description": "",

@@ -46,2 +46,3 @@ "author": "Amplitude Inc",

"@amplitude/rrweb": "2.0.0-alpha.19",
"@amplitude/targeting": "0.2.0",
"idb": "^8.0.0",

@@ -67,3 +68,3 @@ "tslib": "^2.4.1"

],
"gitHead": "4514fbd5e5ac24426e4091ddb8d2604228099b14"
"gitHead": "ffe85701ecb0fea995ac90fa22efb49007a3a1e6"
}

@@ -50,5 +50,15 @@ <p align="center">

### 3. Get session replay event properties
Any event that occurs within the span of a session replay must be tagged with properties that signal to Amplitude to include it in the scope of the replay. The following shows an example of how to use the properties
### 3. Evaluate targeting (optional)
Any event that occurs within the span of a session replay must be passed to the SDK to evaluate against targeting conditions. This should be done *before* step 4, getting the event properties. If you are not using the targeting condition logic provided via the Amplitude UI, this step is not required.
```typescript
const sessionTargetingMatch = sessionReplay.evaluateTargetingAndCapture({ event: {
event_type: EVENT_NAME,
time: EVENT_TIMESTAMP,
event_properties: eventProperties
} });
```
### 4. Get session replay event properties
Any event must be tagged with properties that signal to Amplitude to include it in the scope of the replay. The following shows an example of how to use the properties.
```typescript
const sessionReplayProperties = sessionReplay.getSessionReplayProperties();

@@ -61,3 +71,3 @@ track(EVENT_NAME, {

### 4. Update session id
### 5. Update session id
Any time that the session id for the user changes, the session replay SDK must be notified of that change. Update the session id via the following method:

@@ -72,3 +82,3 @@ ```typescript

### 5. Shutdown (optional)
### 6. Shutdown (optional)
If at any point you would like to discontinue collection of session replays, for example in a part of your application where you would not like sessions to be collected, you can use the following method to stop collection and remove collection event listeners.

@@ -75,0 +85,0 @@ ```typescript

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc