diff --git a/packages/optimizely-sdk/CHANGELOG.MD b/packages/optimizely-sdk/CHANGELOG.MD index 0986511b7..f976232b5 100644 --- a/packages/optimizely-sdk/CHANGELOG.MD +++ b/packages/optimizely-sdk/CHANGELOG.MD @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - In `Optimizely` class, use `any` type when assigning the return value of `setTimeout`. This is to allow it to type check regardless of whether it uses the browser or Node version of `setTimeout` ([PR #623](https://github.com/optimizely/javascript-sdk/pull/623)), ([Issue #622](https://github.com/optimizely/javascript-sdk/issues/622)) +### New Features + +- Added `enabled` field to decision metadata structure to support upcoming application-controlled introduction of tracking for non-experiment Flag decisions ([#619](https://github.com/optimizely/javascript-sdk/pull/619)) + ## [4.4.1] - November 5, 2020 ### Bug fixes diff --git a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.d.ts b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.d.ts index 334dcea13..1d2d68278 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.d.ts +++ b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.d.ts @@ -21,6 +21,7 @@ interface ImpressionConfig { decisionObj: DecisionObj; userId: string; flagKey: string; + enabled: boolean; userAttributes?: UserAttributes; clientEngine: string; clientVersion: string; @@ -65,6 +66,7 @@ interface ImpressionEvent { ruleKey: string, flagKey: string, ruleType: string, + enabled: boolean, } interface ConversionConfig { diff --git a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js index 6d85191f4..20ad04ad2 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js +++ b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.js @@ -25,19 +25,22 @@ var logger = getLogger('EVENT_BUILDER'); /** * Creates an ImpressionEvent object from decision data - * @param {Object} config - * @param {Object} config.decisionObj - * @param {String} config.userId - * @param {Object} config.userAttributes - * @param {String} config.clientEngine - * @param {String} config.clientVersion - * @return {Object} an ImpressionEvent object + * @param {Object} config + * @param {Object} config.decisionObj + * @param {String} config.userId + * @param {String} config.flagKey + * @param {boolean} config.enabled + * @param {Object} config.userAttributes + * @param {String} config.clientEngine + * @param {String} config.clientVersion + * @return {Object} an ImpressionEvent object */ export var buildImpressionEvent = function(config) { var configObj = config.configObj; var decisionObj = config.decisionObj; var userId = config.userId; var flagKey = config.flagKey; + var enabled = config.enabled; var userAttributes = config.userAttributes; var clientEngine = config.clientEngine; var clientVersion = config.clientVersion; @@ -95,6 +98,7 @@ export var buildImpressionEvent = function(config) { ruleKey: experimentKey, flagKey: flagKey, ruleType: ruleType, + enabled: enabled, }; }; diff --git a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js index fd168a1b0..889475f36 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js +++ b/packages/optimizely-sdk/lib/core/event_builder/event_helpers.tests.js @@ -90,6 +90,7 @@ describe('lib/event_builder/event_helpers', function() { var result = buildImpressionEvent({ configObj: configObj, decisionObj: decision, + enabled: true, flagKey: 'flagkey1', userId: 'user1', userAttributes: { @@ -140,6 +141,7 @@ describe('lib/event_builder/event_helpers', function() { ruleKey: "exp1", flagKey: 'flagkey1', ruleType: 'experiment', + enabled: true, }); }); }); @@ -184,6 +186,7 @@ describe('lib/event_builder/event_helpers', function() { configObj: configObj, decisionObj: decision, flagKey: 'flagkey1', + enabled: false, userId: 'user1', userAttributes: { plan_type: 'bronze', @@ -233,6 +236,7 @@ describe('lib/event_builder/event_helpers', function() { ruleKey: "exp1", flagKey: 'flagkey1', ruleType: 'experiment', + enabled: false, }); }); }); diff --git a/packages/optimizely-sdk/lib/core/event_builder/index.d.ts b/packages/optimizely-sdk/lib/core/event_builder/index.d.ts index b6d06345a..b90a65949 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/index.d.ts +++ b/packages/optimizely-sdk/lib/core/event_builder/index.d.ts @@ -25,6 +25,7 @@ interface ImpressionOptions { experimentId: string | null; ruleKey: string; flagKey: string; + enabled: boolean; ruleType: string; eventKey?: string; variationId: string | null; diff --git a/packages/optimizely-sdk/lib/core/event_builder/index.js b/packages/optimizely-sdk/lib/core/event_builder/index.js index cc66c6840..3414f6258 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/index.js +++ b/packages/optimizely-sdk/lib/core/event_builder/index.js @@ -90,15 +90,16 @@ function getCommonEventParams(options) { /** * Creates object of params specific to impression events - * @param {Object} configObj Object representing project configuration - * @param {string} experimentId ID of experiment for which impression needs to be recorded - * @param {string} variationId ID for variation which would be presented to user - * @param {string} ruleKey Key of experiment for which impression needs to be recorded - * @param {string} ruleType Type for the decision source - * @param {string} flagKey Key for a feature flag - * @return {Object} Impression event params + * @param {Object} configObj Object representing project configuration + * @param {string} experimentId ID of experiment for which impression needs to be recorded + * @param {string} variationId ID for variation which would be presented to user + * @param {string} ruleKey Key of experiment for which impression needs to be recorded + * @param {string} ruleType Type for the decision source + * @param {string} flagKey Key for a feature flag + * @param {boolean} enabled Boolean representing if feature is enabled + * @return {Object} Impression event params */ -function getImpressionEventParams(configObj, experimentId, variationId, ruleKey, ruleType, flagKey) { +function getImpressionEventParams(configObj, experimentId, variationId, ruleKey, ruleType, flagKey, enabled) { let campaignId = null; if (experimentId !== null) { campaignId = projectConfig.getLayerId(configObj, experimentId); @@ -120,6 +121,7 @@ function getImpressionEventParams(configObj, experimentId, variationId, ruleKey, rule_key: ruleKey, rule_type: ruleType, variation_key: variationKey, + enabled: enabled, } }, ], @@ -176,18 +178,19 @@ function getVisitorSnapshot(configObj, eventKey, eventTags, logger) { /** * Create impression event params to be sent to the logging endpoint - * @param {Object} options Object containing values needed to build impression event - * @param {Object} options.attributes Object representing user attributes and values which need to be recorded - * @param {string} options.clientEngine The client we are using: node or javascript - * @param {string} options.clientVersion The version of the client - * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup - * @param {string} options.experimentId Experiment for which impression needs to be recorded - * @param {string} options.userId ID for user - * @param {string} options.variationId ID for variation which would be presented to user - * @param {string} options.ruleKey Key of an experiment for which impression needs to be recorded - * @param {string} options.ruleType Type for the decision source - * @param {string} options.flagKey Key for a feature flag - * @return {Object} Params to be used in impression event logging endpoint call + * @param {Object} options Object containing values needed to build impression event + * @param {Object} options.attributes Object representing user attributes and values which need to be recorded + * @param {string} options.clientEngine The client we are using: node or javascript + * @param {string} options.clientVersion The version of the client + * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup + * @param {string} options.experimentId Experiment for which impression needs to be recorded + * @param {string} options.userId ID for user + * @param {string} options.variationId ID for variation which would be presented to user + * @param {string} options.ruleKey Key of an experiment for which impression needs to be recorded + * @param {string} options.ruleType Type for the decision source + * @param {string} options.flagKey Key for a feature flag + * @param {boolean} options.enabled Boolean representing if feature is enabled + * @return {Object} Params to be used in impression event logging endpoint call */ export var getImpressionEvent = function(options) { var impressionEvent = { @@ -203,7 +206,8 @@ export var getImpressionEvent = function(options) { options.variationId, options.ruleKey, options.ruleType, - options.flagKey + options.flagKey, + options.enabled, ); // combine Event params into visitor obj commonParams.visitors[0].snapshots.push(impressionEventParams); diff --git a/packages/optimizely-sdk/lib/core/event_builder/index.tests.js b/packages/optimizely-sdk/lib/core/event_builder/index.tests.js index 2cd4c268f..4f4c2e955 100644 --- a/packages/optimizely-sdk/lib/core/event_builder/index.tests.js +++ b/packages/optimizely-sdk/lib/core/event_builder/index.tests.js @@ -66,6 +66,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: true, }, }, ], @@ -96,6 +97,7 @@ describe('lib/core/event_builder', function() { experimentId: '111127', ruleKey: 'exp1', flagKey: 'flagKey1', + enabled: true, ruleType: 'experiment', variationId: '111128', userId: 'testUser', @@ -136,6 +138,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: false, }, }, ], @@ -167,6 +170,7 @@ describe('lib/core/event_builder', function() { variationId: '111128', ruleKey: 'exp1', flagKey: 'flagKey1', + enabled: false, ruleType: 'experiment', userId: 'testUser', }; @@ -206,6 +210,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: true, }, }, ], @@ -238,6 +243,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp1', flagKey: 'flagKey1', ruleType: 'experiment', + enabled: true, variationId: '111128', userId: 'testUser', }; @@ -277,6 +283,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: true, }, }, ], @@ -309,6 +316,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp1', flagKey: 'flagKey1', ruleType: 'experiment', + enabled: true, variationId: '111128', userId: 'testUser', }; @@ -341,6 +349,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: false, }, }, ], @@ -373,6 +382,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp1', flagKey: 'flagKey1', ruleType: 'experiment', + enabled: false, variationId: '111128', userId: 'testUser', logger: mockLogger, @@ -420,6 +430,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp2', rule_type: 'experiment', variation_key: 'var', + enabled: false, }, }, ], @@ -452,6 +463,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp2', flagKey: 'flagKey2', ruleType: 'experiment', + enabled: false, variationId: '595008', userId: 'testUser', }; @@ -499,6 +511,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp2', rule_type: 'experiment', variation_key: 'var', + enabled: false, }, }, ], @@ -531,6 +544,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp2', flagKey: 'flagKey2', ruleType: 'experiment', + enabled: false, variationId: '595008', userId: 'testUser', }; @@ -588,6 +602,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: false, }, }, ], @@ -625,6 +640,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp1', flagKey: 'flagKey1', ruleType: 'experiment', + enabled: false, variationId: '111128', userId: 'testUser', }; @@ -676,6 +692,7 @@ describe('lib/core/event_builder', function() { rule_key: 'exp1', rule_type: 'experiment', variation_key: 'control', + enabled: true, }, }, ], @@ -714,6 +731,7 @@ describe('lib/core/event_builder', function() { ruleKey: 'exp1', flagKey: 'flagKey1', ruleType: 'experiment', + enabled: true, variationId: '111128', userId: 'testUser', }; diff --git a/packages/optimizely-sdk/lib/optimizely/index.tests.js b/packages/optimizely-sdk/lib/optimizely/index.tests.js index 48c8e5390..d49aa3cee 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.tests.js +++ b/packages/optimizely-sdk/lib/optimizely/index.tests.js @@ -335,6 +335,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperiment', rule_type: 'experiment', variation_key: 'variation', + enabled: true, }, }, ], @@ -394,6 +395,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperimentWithAudiences', rule_type: 'experiment', variation_key: 'variationWithAudience', + enabled: true, }, }, @@ -459,6 +461,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperimentWithAudiences', rule_type: 'experiment', variation_key: 'variationWithAudience', + enabled: true, }, }, ], @@ -528,6 +531,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperimentWithAudiences', rule_type: 'experiment', variation_key: 'variationWithAudience', + enabled: true, }, }, ], @@ -626,6 +630,7 @@ describe('lib/optimizely', function() { rule_key: 'groupExperiment2', rule_type: 'experiment', variation_key: 'var2exp2', + enabled: true, }, }, ], @@ -683,6 +688,7 @@ describe('lib/optimizely', function() { rule_key: 'groupExperiment1', rule_type: 'experiment', variation_key: 'var2exp1', + enabled: true, }, }, ], @@ -2340,6 +2346,7 @@ describe('lib/optimizely', function() { rule_key: "testExperiment", rule_type: "experiment", variation_key: "variation", + enabled: true, }, }, ], @@ -2401,6 +2408,7 @@ describe('lib/optimizely', function() { rule_key: "testExperiment", rule_type: "experiment", variation_key: "variation", + enabled: true, }, }, ], @@ -4467,6 +4475,7 @@ describe('lib/optimizely', function() { rule_key: 'testing_my_feature', rule_type: 'feature-test', variation_key: 'variation', + enabled: true, }, }, ], @@ -4686,6 +4695,7 @@ describe('lib/optimizely', function() { rule_key: 'test_shared_feature', rule_type: 'feature-test', variation_key: 'control', + enabled: false, }, }, ], @@ -4874,6 +4884,7 @@ describe('lib/optimizely', function() { rule_key: '', rule_type: 'rollout', variation_key: '', + enabled: false, }, }, ], @@ -7504,6 +7515,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperiment', rule_type: 'experiment', variation_key: 'variation', + enabled: true, }, }, ], @@ -7598,6 +7610,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperiment', rule_type: 'experiment', variation_key: 'variation', + enabled: true, }, }, ], @@ -7675,6 +7688,7 @@ describe('lib/optimizely', function() { rule_key: 'testExperiment', rule_type: 'experiment', variation_key: 'variation', + enabled: true, }, }, ], diff --git a/packages/optimizely-sdk/lib/optimizely/index.ts b/packages/optimizely-sdk/lib/optimizely/index.ts index 6d39c5dce..75242a594 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.ts +++ b/packages/optimizely-sdk/lib/optimizely/index.ts @@ -251,9 +251,9 @@ export default class Optimizely { decisionObj, '', userId, + true, attributes ); - return variationKey; } catch (ex) { this.logger.log(LOG_LEVEL.ERROR, ex.message); @@ -282,12 +282,14 @@ export default class Optimizely { * @param {string} flagKey Key for a feature flag * @param {string} userId ID of user to whom the variation was shown * @param {UserAttributes} attributes Optional user attributes + * @param {boolean} enabled Boolean representing if feature is enabled */ private sendImpressionEvent( decisionObj: DecisionObj, flagKey: string, userId: string, - attributes?: UserAttributes + enabled: boolean, + attributes?: UserAttributes, ): void { const configObj = this.projectConfigManager.getConfig(); if (!configObj) { @@ -297,6 +299,7 @@ export default class Optimizely { const impressionEvent = buildImpressionEvent({ decisionObj: decisionObj, flagKey: flagKey, + enabled: enabled, userId: userId, userAttributes: attributes, clientEngine: this.clientEngine, @@ -305,7 +308,7 @@ export default class Optimizely { }); // TODO is it okay to not pass a projectConfig as second argument this.eventProcessor.process(impressionEvent); - this.emitNotificationCenterActivate(decisionObj, flagKey, userId, attributes); + this.emitNotificationCenterActivate(decisionObj, flagKey, userId, enabled, attributes); } /** @@ -313,12 +316,14 @@ export default class Optimizely { * @param {DecisionObj} decisionObj Decision object * @param {string} flagKey Key for a feature flag * @param {string} userId ID of user to whom the variation was shown + * @param {boolean} enabled Boolean representing if feature is enabled * @param {UserAttributes} attributes Optional user attributes */ private emitNotificationCenterActivate( decisionObj: DecisionObj, flagKey: string, userId: string, + enabled: boolean, attributes?: UserAttributes ): void { const configObj = this.projectConfigManager.getConfig(); @@ -348,6 +353,7 @@ export default class Optimizely { flagKey: flagKey, ruleType: ruleType, userId: userId, + enabled: enabled, variationId: variationId, logger: this.logger, }; @@ -701,6 +707,7 @@ export default class Optimizely { decisionObj, feature.key, userId, + featureEnabled, attributes ); } diff --git a/packages/optimizely-sdk/package-lock.json b/packages/optimizely-sdk/package-lock.json index c898be9c4..7736d9f94 100644 --- a/packages/optimizely-sdk/package-lock.json +++ b/packages/optimizely-sdk/package-lock.json @@ -291,9 +291,9 @@ } }, "@optimizely/js-sdk-event-processor": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-event-processor/-/js-sdk-event-processor-0.7.0.tgz", - "integrity": "sha512-HFXPeM5xCCy2qRrVcYeYcy6JIwaGRVb8GnoDQjEsyB8M5AgNzoOTBFWPstCMFHE5jyjrE+QbhXpRcTBLBvRnEA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-event-processor/-/js-sdk-event-processor-0.8.0.tgz", + "integrity": "sha512-fq1OcZtYIkMLGXB60I+aetkMWmBl7jjeHEFbaiAmbwwqLcdxQZXIfRhGnCJ+I3MA8OGvqzxZK+dlS5PqeoGt9g==", "requires": { "@optimizely/js-sdk-logging": "^0.1.0", "@optimizely/js-sdk-utils": "^0.4.0" diff --git a/packages/optimizely-sdk/package.json b/packages/optimizely-sdk/package.json index b0dd0cc7f..5394bcdb3 100644 --- a/packages/optimizely-sdk/package.json +++ b/packages/optimizely-sdk/package.json @@ -42,7 +42,7 @@ "homepage": "https://github.com/optimizely/javascript-sdk/tree/master/packages/optimizely-sdk", "dependencies": { "@optimizely/js-sdk-datafile-manager": "^0.8.0", - "@optimizely/js-sdk-event-processor": "^0.7.0", + "@optimizely/js-sdk-event-processor": "^0.8.0", "@optimizely/js-sdk-logging": "^0.1.0", "@optimizely/js-sdk-utils": "^0.4.0", "json-schema": "^0.2.3",