@coframe/sdk 1.1.24 → 1.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/pkg/cf.cjs.js +164 -2
- package/dist/pkg/cf.esm.mjs +164 -2
- package/dist/pkg/types/index.d.ts +11 -0
- package/dist/pkg/types/react.d.ts +11 -0
- package/dist/pkg/types/server.d.ts +10 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ await init({
|
|
|
51
51
|
projectId: 'your-project-id',
|
|
52
52
|
projectUrl: 'https://cdn.example.com/coframe/project.json',
|
|
53
53
|
ingestUrl: 'https://www.example.com/ingest/v2',
|
|
54
|
+
replayScriptUrl: 'https://www.example.com/replay/latest.js',
|
|
54
55
|
enableDebug: false,
|
|
55
56
|
},
|
|
56
57
|
})
|
|
@@ -65,11 +66,14 @@ only has to forward `<ingestUrl>/*` to `https://ingest.app.coframe.com/ingest/v2
|
|
|
65
66
|
with the path unchanged. Both overrides are optional and retain the compiled
|
|
66
67
|
Coframe endpoints when omitted.
|
|
67
68
|
|
|
69
|
+
`replayScriptUrl` replaces the session replay recorder script URL. A proxy must
|
|
70
|
+
forward it to `<edge>/replay/latest.js` unchanged.
|
|
71
|
+
|
|
68
72
|
Configuring either `projectUrl` or `ingestUrl` makes CMAB experiments use
|
|
69
73
|
deterministic local assignment without calling the Edge assignment API.
|
|
70
|
-
Configure
|
|
71
|
-
project and
|
|
72
|
-
`enableDebug`.
|
|
74
|
+
Configure all three overrides when the browser must avoid the SDK-compiled
|
|
75
|
+
Coframe project, ingest and replay script endpoints entirely. Debug tools
|
|
76
|
+
remain controlled by `enableDebug`.
|
|
73
77
|
|
|
74
78
|
### URL controls
|
|
75
79
|
|
package/dist/pkg/cf.cjs.js
CHANGED
|
@@ -2835,7 +2835,7 @@ function keepRolledOutExperiments(frames) {
|
|
|
2835
2835
|
function buildSessionContext(isInitialApply) {
|
|
2836
2836
|
const context = {};
|
|
2837
2837
|
const viewport = getScreenSize();
|
|
2838
|
-
if (isReportedSize(viewport.width) && isReportedSize(viewport.height)) {
|
|
2838
|
+
if (isReportedSize$1(viewport.width) && isReportedSize$1(viewport.height)) {
|
|
2839
2839
|
context.viewport_width = viewport.width;
|
|
2840
2840
|
context.viewport_height = viewport.height;
|
|
2841
2841
|
}
|
|
@@ -2858,7 +2858,7 @@ function buildSessionContext(isInitialApply) {
|
|
|
2858
2858
|
}
|
|
2859
2859
|
return context;
|
|
2860
2860
|
}
|
|
2861
|
-
function isReportedSize(size) {
|
|
2861
|
+
function isReportedSize$1(size) {
|
|
2862
2862
|
return (typeof size === 'number' && size > 0 && size !== Number.POSITIVE_INFINITY);
|
|
2863
2863
|
}
|
|
2864
2864
|
function getNavigationType(isInitialApply) {
|
|
@@ -3231,6 +3231,20 @@ function observeUrlChanges(baseUrlMatch, onUrlChange) {
|
|
|
3231
3231
|
patchHistoryMethod('replaceState');
|
|
3232
3232
|
}
|
|
3233
3233
|
|
|
3234
|
+
const callbacks = [];
|
|
3235
|
+
function onEventsFlushed(callback) {
|
|
3236
|
+
callbacks.push(callback);
|
|
3237
|
+
}
|
|
3238
|
+
function notifyEventsFlushed() {
|
|
3239
|
+
const pendingCallbacks = callbacks.splice(0);
|
|
3240
|
+
for (const callback of pendingCallbacks) {
|
|
3241
|
+
try {
|
|
3242
|
+
callback();
|
|
3243
|
+
}
|
|
3244
|
+
catch (_a) { }
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
|
|
3234
3248
|
function startSession(Coframe, cookiesEnabled, executionStartTime, personalizationHeaders, sessionContext, pageUrl = getCurrentPageUrl()) {
|
|
3235
3249
|
const sessionPayload = [
|
|
3236
3250
|
Coframe,
|
|
@@ -3505,6 +3519,7 @@ function setupListeners(Coframe, executionStartTime) {
|
|
|
3505
3519
|
personalizationHeaders: Coframe.personalizationHeaders,
|
|
3506
3520
|
});
|
|
3507
3521
|
flushQueuedEvents(Coframe.projectId);
|
|
3522
|
+
notifyEventsFlushed();
|
|
3508
3523
|
}, 1);
|
|
3509
3524
|
window.addEventListener('beforeunload', () => handleEventFlush('before_unload'));
|
|
3510
3525
|
window.addEventListener('pagehide', () => handleEventFlush('page_hide'));
|
|
@@ -3778,7 +3793,131 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3778
3793
|
setupFlushInterval(Coframe);
|
|
3779
3794
|
}
|
|
3780
3795
|
|
|
3796
|
+
let startRequested = false;
|
|
3797
|
+
let replayScriptUrl;
|
|
3798
|
+
const COMPILED_REPLAY_SCRIPT_URL = `${"https://edge.cofra.me"}/replay/latest.js`;
|
|
3799
|
+
function configureReplayScriptUrl(url) {
|
|
3800
|
+
replayScriptUrl = (url === null || url === void 0 ? void 0 : url.trim()) || undefined;
|
|
3801
|
+
}
|
|
3802
|
+
function createMonitoringPayload(coframe, monitoringType, metadata) {
|
|
3803
|
+
return {
|
|
3804
|
+
event_id: generateUUID(),
|
|
3805
|
+
monitoring_type: monitoringType,
|
|
3806
|
+
local_time: new Date().toISOString(),
|
|
3807
|
+
project_id: coframe.projectId,
|
|
3808
|
+
session_id: coframe.sessionId,
|
|
3809
|
+
url: location.href,
|
|
3810
|
+
org_id: coframe.orgId,
|
|
3811
|
+
metadata,
|
|
3812
|
+
};
|
|
3813
|
+
}
|
|
3814
|
+
function reportStartFailure(coframe, reason) {
|
|
3815
|
+
try {
|
|
3816
|
+
queueMonitoringEvent(coframe, createMonitoringPayload(coframe, 'replay_start_failed', { reason }));
|
|
3817
|
+
}
|
|
3818
|
+
catch (_a) { }
|
|
3819
|
+
}
|
|
3820
|
+
function createStartContext(coframe, settings, forceSample) {
|
|
3821
|
+
return {
|
|
3822
|
+
projectId: coframe.projectId,
|
|
3823
|
+
ingestUrl: resolveIngestUrl("https://ingest.app.coframe.com/ingest/v2"),
|
|
3824
|
+
settings,
|
|
3825
|
+
forceSample,
|
|
3826
|
+
getPageViewId: () => coframe.sessionId,
|
|
3827
|
+
getUserToken: () => coframe.userToken,
|
|
3828
|
+
getVariantIds: () => { var _a; return ((_a = coframe.experimentInfo) !== null && _a !== void 0 ? _a : []).map((experiment) => experiment.variant_id); },
|
|
3829
|
+
canSend: shouldSendEvents,
|
|
3830
|
+
onEventsFlushed: (callback) => {
|
|
3831
|
+
if (queuedEvents.length === 0 && queuedSessions.length === 0) {
|
|
3832
|
+
callback();
|
|
3833
|
+
}
|
|
3834
|
+
else {
|
|
3835
|
+
onEventsFlushed(callback);
|
|
3836
|
+
}
|
|
3837
|
+
},
|
|
3838
|
+
report: (type, metadata) => queueMonitoringEvent(coframe, createMonitoringPayload(coframe, type, metadata)),
|
|
3839
|
+
};
|
|
3840
|
+
}
|
|
3841
|
+
function startReplayIfEnabled(coframe, project, nonce) {
|
|
3842
|
+
var _a;
|
|
3843
|
+
try {
|
|
3844
|
+
const settings = (_a = project.settings) === null || _a === void 0 ? void 0 : _a.session_replay;
|
|
3845
|
+
if ((settings === null || settings === void 0 ? void 0 : settings.enabled) !== true ||
|
|
3846
|
+
typeof CompressionStream !== 'function' ||
|
|
3847
|
+
!shouldSendEvents() ||
|
|
3848
|
+
startRequested) {
|
|
3849
|
+
return;
|
|
3850
|
+
}
|
|
3851
|
+
let forceSample = false;
|
|
3852
|
+
try {
|
|
3853
|
+
forceSample = localStorage.getItem('coframe.enableRecording') === 'true';
|
|
3854
|
+
}
|
|
3855
|
+
catch (_b) { }
|
|
3856
|
+
const script = document.createElement('script');
|
|
3857
|
+
script.id = 'coframe-replay-script';
|
|
3858
|
+
script.async = true;
|
|
3859
|
+
script.src = replayScriptUrl !== null && replayScriptUrl !== void 0 ? replayScriptUrl : COMPILED_REPLAY_SCRIPT_URL;
|
|
3860
|
+
if (nonce)
|
|
3861
|
+
script.nonce = nonce;
|
|
3862
|
+
script.onload = () => {
|
|
3863
|
+
try {
|
|
3864
|
+
const replay = window.CoframeReplay;
|
|
3865
|
+
if ((replay === null || replay === void 0 ? void 0 : replay.protocolVersion) === 1) {
|
|
3866
|
+
replay.start(createStartContext(coframe, settings, forceSample));
|
|
3867
|
+
}
|
|
3868
|
+
else {
|
|
3869
|
+
reportStartFailure(coframe, 'incompatible_protocol');
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
catch (error) {
|
|
3873
|
+
reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
|
|
3874
|
+
}
|
|
3875
|
+
};
|
|
3876
|
+
script.onerror = () => {
|
|
3877
|
+
reportStartFailure(coframe, 'script_load_failed');
|
|
3878
|
+
};
|
|
3879
|
+
startRequested = true;
|
|
3880
|
+
document.head.appendChild(script);
|
|
3881
|
+
}
|
|
3882
|
+
catch (error) {
|
|
3883
|
+
reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
|
|
3884
|
+
}
|
|
3885
|
+
}
|
|
3886
|
+
|
|
3781
3887
|
const TIMEOUT_MAX_MS = 5000;
|
|
3888
|
+
const MAX_NOT_RENDERED_REASON_CHARS = 200;
|
|
3889
|
+
function isReportedSize(size) {
|
|
3890
|
+
return (typeof size === 'number' && size > 0 && size !== Number.POSITIVE_INFINITY);
|
|
3891
|
+
}
|
|
3892
|
+
function describeEnvironment(initTime) {
|
|
3893
|
+
const metadata = {};
|
|
3894
|
+
if (typeof window !== 'undefined') {
|
|
3895
|
+
if (isReportedSize(window.innerWidth)) {
|
|
3896
|
+
metadata.viewport_width = window.innerWidth;
|
|
3897
|
+
}
|
|
3898
|
+
if (isReportedSize(window.innerHeight)) {
|
|
3899
|
+
metadata.viewport_height = window.innerHeight;
|
|
3900
|
+
}
|
|
3901
|
+
const screen = window.screen;
|
|
3902
|
+
if (screen && isReportedSize(screen.width)) {
|
|
3903
|
+
metadata.screen_width = screen.width;
|
|
3904
|
+
}
|
|
3905
|
+
if (screen && isReportedSize(screen.height)) {
|
|
3906
|
+
metadata.screen_height = screen.height;
|
|
3907
|
+
}
|
|
3908
|
+
if (isReportedSize(window.devicePixelRatio)) {
|
|
3909
|
+
metadata.device_pixel_ratio = window.devicePixelRatio;
|
|
3910
|
+
}
|
|
3911
|
+
if (typeof navigator.userAgent === 'string') {
|
|
3912
|
+
metadata.user_agent = navigator.userAgent;
|
|
3913
|
+
}
|
|
3914
|
+
if (typeof document.readyState === 'string') {
|
|
3915
|
+
metadata.document_ready_state = document.readyState;
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
metadata.ms_since_init = Math.max(0, Date.now() - initTime);
|
|
3919
|
+
return metadata;
|
|
3920
|
+
}
|
|
3782
3921
|
function getFeatureFlagValue(cmd) {
|
|
3783
3922
|
if (cmd.featureFlagSet !== undefined)
|
|
3784
3923
|
return cmd.featureFlagSet;
|
|
@@ -3812,6 +3951,7 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3812
3951
|
const executionStartTime = new Date();
|
|
3813
3952
|
Coframe.batchSize = config.batchSize || 32;
|
|
3814
3953
|
configureIngestUrl(config.ingestUrl);
|
|
3954
|
+
configureReplayScriptUrl(config.replayScriptUrl);
|
|
3815
3955
|
const gracefulExit = (msg) => {
|
|
3816
3956
|
console.warn(`[Coframe] ${msg}`);
|
|
3817
3957
|
revealPage();
|
|
@@ -3832,6 +3972,15 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3832
3972
|
logger.warn('Failed to wait for variant rendered command', 'missing_variant_rendered');
|
|
3833
3973
|
}
|
|
3834
3974
|
};
|
|
3975
|
+
const warnVariantNotRendered = (reason) => {
|
|
3976
|
+
if (!applyVariantChangesStarted)
|
|
3977
|
+
return;
|
|
3978
|
+
const metadata = describeEnvironment(executionStartTime.getTime());
|
|
3979
|
+
if (typeof reason === 'string') {
|
|
3980
|
+
metadata.reason = reason.slice(0, MAX_NOT_RENDERED_REASON_CHARS);
|
|
3981
|
+
}
|
|
3982
|
+
logger.warn('Variant not rendered', 'variant_not_rendered', metadata);
|
|
3983
|
+
};
|
|
3835
3984
|
waitForCmd((cmd) => cmd.variantRendered === true || cmd.emit === 'variantRendered', Coframe, timeoutMs)
|
|
3836
3985
|
.then((cmd) => {
|
|
3837
3986
|
if (!cmd) {
|
|
@@ -3841,6 +3990,13 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3841
3990
|
.finally(() => {
|
|
3842
3991
|
revealPage();
|
|
3843
3992
|
});
|
|
3993
|
+
const loggedReasons = [];
|
|
3994
|
+
listenForCmd((cmd) => cmd.emit === 'variantNotRendered', (cmd) => {
|
|
3995
|
+
if (loggedReasons.indexOf(cmd.reason) !== -1)
|
|
3996
|
+
return;
|
|
3997
|
+
loggedReasons.push(cmd.reason);
|
|
3998
|
+
warnVariantNotRendered(cmd.reason);
|
|
3999
|
+
});
|
|
3844
4000
|
if (!projectId) {
|
|
3845
4001
|
logger.error('No project ID', 'no_project_id', {
|
|
3846
4002
|
description: 'No Coframe Page ID',
|
|
@@ -4106,6 +4262,12 @@ async function init(options) {
|
|
|
4106
4262
|
return;
|
|
4107
4263
|
const analytics = setupTracking(Coframe, projectResult, configResult.previewVariantId, configResult.executionStartTime, configResult.config.nonce, configResult.config.waitForCookiesEnabled, identity.onConsentChange);
|
|
4108
4264
|
await modifyPage(Coframe, configResult, projectResult, analytics);
|
|
4265
|
+
try {
|
|
4266
|
+
startReplayIfEnabled(Coframe, projectResult.project, configResult.config.nonce);
|
|
4267
|
+
}
|
|
4268
|
+
catch (error) {
|
|
4269
|
+
console.warn('[Coframe] Failed to start session replay', error);
|
|
4270
|
+
}
|
|
4109
4271
|
}
|
|
4110
4272
|
Coframe.debug = {
|
|
4111
4273
|
getSelector,
|
package/dist/pkg/cf.esm.mjs
CHANGED
|
@@ -2833,7 +2833,7 @@ function keepRolledOutExperiments(frames) {
|
|
|
2833
2833
|
function buildSessionContext(isInitialApply) {
|
|
2834
2834
|
const context = {};
|
|
2835
2835
|
const viewport = getScreenSize();
|
|
2836
|
-
if (isReportedSize(viewport.width) && isReportedSize(viewport.height)) {
|
|
2836
|
+
if (isReportedSize$1(viewport.width) && isReportedSize$1(viewport.height)) {
|
|
2837
2837
|
context.viewport_width = viewport.width;
|
|
2838
2838
|
context.viewport_height = viewport.height;
|
|
2839
2839
|
}
|
|
@@ -2856,7 +2856,7 @@ function buildSessionContext(isInitialApply) {
|
|
|
2856
2856
|
}
|
|
2857
2857
|
return context;
|
|
2858
2858
|
}
|
|
2859
|
-
function isReportedSize(size) {
|
|
2859
|
+
function isReportedSize$1(size) {
|
|
2860
2860
|
return (typeof size === 'number' && size > 0 && size !== Number.POSITIVE_INFINITY);
|
|
2861
2861
|
}
|
|
2862
2862
|
function getNavigationType(isInitialApply) {
|
|
@@ -3229,6 +3229,20 @@ function observeUrlChanges(baseUrlMatch, onUrlChange) {
|
|
|
3229
3229
|
patchHistoryMethod('replaceState');
|
|
3230
3230
|
}
|
|
3231
3231
|
|
|
3232
|
+
const callbacks = [];
|
|
3233
|
+
function onEventsFlushed(callback) {
|
|
3234
|
+
callbacks.push(callback);
|
|
3235
|
+
}
|
|
3236
|
+
function notifyEventsFlushed() {
|
|
3237
|
+
const pendingCallbacks = callbacks.splice(0);
|
|
3238
|
+
for (const callback of pendingCallbacks) {
|
|
3239
|
+
try {
|
|
3240
|
+
callback();
|
|
3241
|
+
}
|
|
3242
|
+
catch (_a) { }
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3232
3246
|
function startSession(Coframe, cookiesEnabled, executionStartTime, personalizationHeaders, sessionContext, pageUrl = getCurrentPageUrl()) {
|
|
3233
3247
|
const sessionPayload = [
|
|
3234
3248
|
Coframe,
|
|
@@ -3503,6 +3517,7 @@ function setupListeners(Coframe, executionStartTime) {
|
|
|
3503
3517
|
personalizationHeaders: Coframe.personalizationHeaders,
|
|
3504
3518
|
});
|
|
3505
3519
|
flushQueuedEvents(Coframe.projectId);
|
|
3520
|
+
notifyEventsFlushed();
|
|
3506
3521
|
}, 1);
|
|
3507
3522
|
window.addEventListener('beforeunload', () => handleEventFlush('before_unload'));
|
|
3508
3523
|
window.addEventListener('pagehide', () => handleEventFlush('page_hide'));
|
|
@@ -3776,7 +3791,131 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3776
3791
|
setupFlushInterval(Coframe);
|
|
3777
3792
|
}
|
|
3778
3793
|
|
|
3794
|
+
let startRequested = false;
|
|
3795
|
+
let replayScriptUrl;
|
|
3796
|
+
const COMPILED_REPLAY_SCRIPT_URL = `${"https://edge.cofra.me"}/replay/latest.js`;
|
|
3797
|
+
function configureReplayScriptUrl(url) {
|
|
3798
|
+
replayScriptUrl = (url === null || url === void 0 ? void 0 : url.trim()) || undefined;
|
|
3799
|
+
}
|
|
3800
|
+
function createMonitoringPayload(coframe, monitoringType, metadata) {
|
|
3801
|
+
return {
|
|
3802
|
+
event_id: generateUUID(),
|
|
3803
|
+
monitoring_type: monitoringType,
|
|
3804
|
+
local_time: new Date().toISOString(),
|
|
3805
|
+
project_id: coframe.projectId,
|
|
3806
|
+
session_id: coframe.sessionId,
|
|
3807
|
+
url: location.href,
|
|
3808
|
+
org_id: coframe.orgId,
|
|
3809
|
+
metadata,
|
|
3810
|
+
};
|
|
3811
|
+
}
|
|
3812
|
+
function reportStartFailure(coframe, reason) {
|
|
3813
|
+
try {
|
|
3814
|
+
queueMonitoringEvent(coframe, createMonitoringPayload(coframe, 'replay_start_failed', { reason }));
|
|
3815
|
+
}
|
|
3816
|
+
catch (_a) { }
|
|
3817
|
+
}
|
|
3818
|
+
function createStartContext(coframe, settings, forceSample) {
|
|
3819
|
+
return {
|
|
3820
|
+
projectId: coframe.projectId,
|
|
3821
|
+
ingestUrl: resolveIngestUrl("https://ingest.app.coframe.com/ingest/v2"),
|
|
3822
|
+
settings,
|
|
3823
|
+
forceSample,
|
|
3824
|
+
getPageViewId: () => coframe.sessionId,
|
|
3825
|
+
getUserToken: () => coframe.userToken,
|
|
3826
|
+
getVariantIds: () => { var _a; return ((_a = coframe.experimentInfo) !== null && _a !== void 0 ? _a : []).map((experiment) => experiment.variant_id); },
|
|
3827
|
+
canSend: shouldSendEvents,
|
|
3828
|
+
onEventsFlushed: (callback) => {
|
|
3829
|
+
if (queuedEvents.length === 0 && queuedSessions.length === 0) {
|
|
3830
|
+
callback();
|
|
3831
|
+
}
|
|
3832
|
+
else {
|
|
3833
|
+
onEventsFlushed(callback);
|
|
3834
|
+
}
|
|
3835
|
+
},
|
|
3836
|
+
report: (type, metadata) => queueMonitoringEvent(coframe, createMonitoringPayload(coframe, type, metadata)),
|
|
3837
|
+
};
|
|
3838
|
+
}
|
|
3839
|
+
function startReplayIfEnabled(coframe, project, nonce) {
|
|
3840
|
+
var _a;
|
|
3841
|
+
try {
|
|
3842
|
+
const settings = (_a = project.settings) === null || _a === void 0 ? void 0 : _a.session_replay;
|
|
3843
|
+
if ((settings === null || settings === void 0 ? void 0 : settings.enabled) !== true ||
|
|
3844
|
+
typeof CompressionStream !== 'function' ||
|
|
3845
|
+
!shouldSendEvents() ||
|
|
3846
|
+
startRequested) {
|
|
3847
|
+
return;
|
|
3848
|
+
}
|
|
3849
|
+
let forceSample = false;
|
|
3850
|
+
try {
|
|
3851
|
+
forceSample = localStorage.getItem('coframe.enableRecording') === 'true';
|
|
3852
|
+
}
|
|
3853
|
+
catch (_b) { }
|
|
3854
|
+
const script = document.createElement('script');
|
|
3855
|
+
script.id = 'coframe-replay-script';
|
|
3856
|
+
script.async = true;
|
|
3857
|
+
script.src = replayScriptUrl !== null && replayScriptUrl !== void 0 ? replayScriptUrl : COMPILED_REPLAY_SCRIPT_URL;
|
|
3858
|
+
if (nonce)
|
|
3859
|
+
script.nonce = nonce;
|
|
3860
|
+
script.onload = () => {
|
|
3861
|
+
try {
|
|
3862
|
+
const replay = window.CoframeReplay;
|
|
3863
|
+
if ((replay === null || replay === void 0 ? void 0 : replay.protocolVersion) === 1) {
|
|
3864
|
+
replay.start(createStartContext(coframe, settings, forceSample));
|
|
3865
|
+
}
|
|
3866
|
+
else {
|
|
3867
|
+
reportStartFailure(coframe, 'incompatible_protocol');
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3870
|
+
catch (error) {
|
|
3871
|
+
reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
|
|
3872
|
+
}
|
|
3873
|
+
};
|
|
3874
|
+
script.onerror = () => {
|
|
3875
|
+
reportStartFailure(coframe, 'script_load_failed');
|
|
3876
|
+
};
|
|
3877
|
+
startRequested = true;
|
|
3878
|
+
document.head.appendChild(script);
|
|
3879
|
+
}
|
|
3880
|
+
catch (error) {
|
|
3881
|
+
reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3779
3885
|
const TIMEOUT_MAX_MS = 5000;
|
|
3886
|
+
const MAX_NOT_RENDERED_REASON_CHARS = 200;
|
|
3887
|
+
function isReportedSize(size) {
|
|
3888
|
+
return (typeof size === 'number' && size > 0 && size !== Number.POSITIVE_INFINITY);
|
|
3889
|
+
}
|
|
3890
|
+
function describeEnvironment(initTime) {
|
|
3891
|
+
const metadata = {};
|
|
3892
|
+
if (typeof window !== 'undefined') {
|
|
3893
|
+
if (isReportedSize(window.innerWidth)) {
|
|
3894
|
+
metadata.viewport_width = window.innerWidth;
|
|
3895
|
+
}
|
|
3896
|
+
if (isReportedSize(window.innerHeight)) {
|
|
3897
|
+
metadata.viewport_height = window.innerHeight;
|
|
3898
|
+
}
|
|
3899
|
+
const screen = window.screen;
|
|
3900
|
+
if (screen && isReportedSize(screen.width)) {
|
|
3901
|
+
metadata.screen_width = screen.width;
|
|
3902
|
+
}
|
|
3903
|
+
if (screen && isReportedSize(screen.height)) {
|
|
3904
|
+
metadata.screen_height = screen.height;
|
|
3905
|
+
}
|
|
3906
|
+
if (isReportedSize(window.devicePixelRatio)) {
|
|
3907
|
+
metadata.device_pixel_ratio = window.devicePixelRatio;
|
|
3908
|
+
}
|
|
3909
|
+
if (typeof navigator.userAgent === 'string') {
|
|
3910
|
+
metadata.user_agent = navigator.userAgent;
|
|
3911
|
+
}
|
|
3912
|
+
if (typeof document.readyState === 'string') {
|
|
3913
|
+
metadata.document_ready_state = document.readyState;
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
metadata.ms_since_init = Math.max(0, Date.now() - initTime);
|
|
3917
|
+
return metadata;
|
|
3918
|
+
}
|
|
3780
3919
|
function getFeatureFlagValue(cmd) {
|
|
3781
3920
|
if (cmd.featureFlagSet !== undefined)
|
|
3782
3921
|
return cmd.featureFlagSet;
|
|
@@ -3810,6 +3949,7 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3810
3949
|
const executionStartTime = new Date();
|
|
3811
3950
|
Coframe.batchSize = config.batchSize || 32;
|
|
3812
3951
|
configureIngestUrl(config.ingestUrl);
|
|
3952
|
+
configureReplayScriptUrl(config.replayScriptUrl);
|
|
3813
3953
|
const gracefulExit = (msg) => {
|
|
3814
3954
|
console.warn(`[Coframe] ${msg}`);
|
|
3815
3955
|
revealPage();
|
|
@@ -3830,6 +3970,15 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3830
3970
|
logger.warn('Failed to wait for variant rendered command', 'missing_variant_rendered');
|
|
3831
3971
|
}
|
|
3832
3972
|
};
|
|
3973
|
+
const warnVariantNotRendered = (reason) => {
|
|
3974
|
+
if (!applyVariantChangesStarted)
|
|
3975
|
+
return;
|
|
3976
|
+
const metadata = describeEnvironment(executionStartTime.getTime());
|
|
3977
|
+
if (typeof reason === 'string') {
|
|
3978
|
+
metadata.reason = reason.slice(0, MAX_NOT_RENDERED_REASON_CHARS);
|
|
3979
|
+
}
|
|
3980
|
+
logger.warn('Variant not rendered', 'variant_not_rendered', metadata);
|
|
3981
|
+
};
|
|
3833
3982
|
waitForCmd((cmd) => cmd.variantRendered === true || cmd.emit === 'variantRendered', Coframe, timeoutMs)
|
|
3834
3983
|
.then((cmd) => {
|
|
3835
3984
|
if (!cmd) {
|
|
@@ -3839,6 +3988,13 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3839
3988
|
.finally(() => {
|
|
3840
3989
|
revealPage();
|
|
3841
3990
|
});
|
|
3991
|
+
const loggedReasons = [];
|
|
3992
|
+
listenForCmd((cmd) => cmd.emit === 'variantNotRendered', (cmd) => {
|
|
3993
|
+
if (loggedReasons.indexOf(cmd.reason) !== -1)
|
|
3994
|
+
return;
|
|
3995
|
+
loggedReasons.push(cmd.reason);
|
|
3996
|
+
warnVariantNotRendered(cmd.reason);
|
|
3997
|
+
});
|
|
3842
3998
|
if (!projectId) {
|
|
3843
3999
|
logger.error('No project ID', 'no_project_id', {
|
|
3844
4000
|
description: 'No Coframe Page ID',
|
|
@@ -4104,6 +4260,12 @@ async function init(options) {
|
|
|
4104
4260
|
return;
|
|
4105
4261
|
const analytics = setupTracking(Coframe, projectResult, configResult.previewVariantId, configResult.executionStartTime, configResult.config.nonce, configResult.config.waitForCookiesEnabled, identity.onConsentChange);
|
|
4106
4262
|
await modifyPage(Coframe, configResult, projectResult, analytics);
|
|
4263
|
+
try {
|
|
4264
|
+
startReplayIfEnabled(Coframe, projectResult.project, configResult.config.nonce);
|
|
4265
|
+
}
|
|
4266
|
+
catch (error) {
|
|
4267
|
+
console.warn('[Coframe] Failed to start session replay', error);
|
|
4268
|
+
}
|
|
4107
4269
|
}
|
|
4108
4270
|
Coframe.debug = {
|
|
4109
4271
|
getSelector,
|
|
@@ -74,6 +74,15 @@ type ModalTrigger = 'exit' | 'scroll' | 'enter' | 'timer';
|
|
|
74
74
|
interface AnalyticsCallback {
|
|
75
75
|
callback: string;
|
|
76
76
|
}
|
|
77
|
+
interface SessionReplaySettings {
|
|
78
|
+
enabled: boolean;
|
|
79
|
+
sample_rate: number;
|
|
80
|
+
mask_text_selector: string;
|
|
81
|
+
block_selector: string;
|
|
82
|
+
url_deny_patterns: string[];
|
|
83
|
+
max_session_minutes: number;
|
|
84
|
+
max_session_bytes: number;
|
|
85
|
+
}
|
|
77
86
|
interface TreatmentData {
|
|
78
87
|
impressionId: string;
|
|
79
88
|
userToken: string;
|
|
@@ -141,6 +150,7 @@ interface ProjectSettings {
|
|
|
141
150
|
bot_cloaking_enabled?: boolean;
|
|
142
151
|
bot_score_threshold?: number;
|
|
143
152
|
analytics_callback?: AnalyticsCallback;
|
|
153
|
+
session_replay?: SessionReplaySettings | null;
|
|
144
154
|
}
|
|
145
155
|
interface Project {
|
|
146
156
|
org_id: string;
|
|
@@ -252,6 +262,7 @@ type CoframeConfig = {
|
|
|
252
262
|
currentUrl?: string;
|
|
253
263
|
projectUrl?: string;
|
|
254
264
|
ingestUrl?: string;
|
|
265
|
+
replayScriptUrl?: string;
|
|
255
266
|
referrer?: string;
|
|
256
267
|
userContext?: Record<string, unknown>;
|
|
257
268
|
nonce?: string;
|
|
@@ -93,6 +93,15 @@ type ModalTrigger = 'exit' | 'scroll' | 'enter' | 'timer';
|
|
|
93
93
|
interface AnalyticsCallback {
|
|
94
94
|
callback: string;
|
|
95
95
|
}
|
|
96
|
+
interface SessionReplaySettings {
|
|
97
|
+
enabled: boolean;
|
|
98
|
+
sample_rate: number;
|
|
99
|
+
mask_text_selector: string;
|
|
100
|
+
block_selector: string;
|
|
101
|
+
url_deny_patterns: string[];
|
|
102
|
+
max_session_minutes: number;
|
|
103
|
+
max_session_bytes: number;
|
|
104
|
+
}
|
|
96
105
|
interface TreatmentData {
|
|
97
106
|
impressionId: string;
|
|
98
107
|
userToken: string;
|
|
@@ -160,6 +169,7 @@ interface ProjectSettings {
|
|
|
160
169
|
bot_cloaking_enabled?: boolean;
|
|
161
170
|
bot_score_threshold?: number;
|
|
162
171
|
analytics_callback?: AnalyticsCallback;
|
|
172
|
+
session_replay?: SessionReplaySettings | null;
|
|
163
173
|
}
|
|
164
174
|
interface Project {
|
|
165
175
|
org_id: string;
|
|
@@ -271,6 +281,7 @@ type CoframeConfig = {
|
|
|
271
281
|
currentUrl?: string;
|
|
272
282
|
projectUrl?: string;
|
|
273
283
|
ingestUrl?: string;
|
|
284
|
+
replayScriptUrl?: string;
|
|
274
285
|
referrer?: string;
|
|
275
286
|
userContext?: Record<string, unknown>;
|
|
276
287
|
nonce?: string;
|
|
@@ -74,6 +74,15 @@ type ModalTrigger = 'exit' | 'scroll' | 'enter' | 'timer';
|
|
|
74
74
|
interface AnalyticsCallback {
|
|
75
75
|
callback: string;
|
|
76
76
|
}
|
|
77
|
+
interface SessionReplaySettings {
|
|
78
|
+
enabled: boolean;
|
|
79
|
+
sample_rate: number;
|
|
80
|
+
mask_text_selector: string;
|
|
81
|
+
block_selector: string;
|
|
82
|
+
url_deny_patterns: string[];
|
|
83
|
+
max_session_minutes: number;
|
|
84
|
+
max_session_bytes: number;
|
|
85
|
+
}
|
|
77
86
|
interface Audience {
|
|
78
87
|
selector: ActivationCondition;
|
|
79
88
|
}
|
|
@@ -107,6 +116,7 @@ interface ProjectSettings {
|
|
|
107
116
|
bot_cloaking_enabled?: boolean;
|
|
108
117
|
bot_score_threshold?: number;
|
|
109
118
|
analytics_callback?: AnalyticsCallback;
|
|
119
|
+
session_replay?: SessionReplaySettings | null;
|
|
110
120
|
}
|
|
111
121
|
interface Project {
|
|
112
122
|
org_id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coframe/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.26",
|
|
4
4
|
"description": "Coframe optimizes your website using generative AI to deliver maximum impact to your audience and allow your site to improve itself as you sleep. Learn more at coframe.com.",
|
|
5
5
|
"main": "dist/pkg/cf.cjs.js",
|
|
6
6
|
"module": "dist/pkg/cf.esm.mjs",
|
|
@@ -98,6 +98,8 @@
|
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
+
"@rrweb/record": "2.1.0",
|
|
102
|
+
"fflate": "0.8.3",
|
|
101
103
|
"typescript": "^6.0.2"
|
|
102
104
|
},
|
|
103
105
|
"devDependencies": {
|
|
@@ -136,4 +138,4 @@
|
|
|
136
138
|
"ua-parser-js": "^2.0.10"
|
|
137
139
|
},
|
|
138
140
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
139
|
-
}
|
|
141
|
+
}
|