Skip to content

Commit af8f9d1

Browse files
authoredFeb 4, 2022
feat: Support seamless integration with amplitude experiment SDK (#457)
1 parent ddff63b commit af8f9d1

8 files changed

+275
-144
lines changed
 

‎.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ amplitude.umd.min.js
1919
amplitude.native.js
2020
amplitude.nocompat.js
2121
amplitude.nocompat.min.js
22+
23+
# For WebStorm IDE
24+
.idea/

‎package.json

+9-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"@amplitude/utils": "^1.0.5",
2020
"@babel/runtime": "^7.3.4",
2121
"blueimp-md5": "^2.10.0",
22-
"query-string": "5"
22+
"query-string": "5",
23+
"@amplitude/analytics-connector": "1.0.0"
2324
},
2425
"devDependencies": {
2526
"@amplitude/eslint-plugin-amplitude": "^1.0.1",
@@ -56,13 +57,13 @@
5657
"mocha": "^4.0.1",
5758
"prettier": "^2.2.1",
5859
"requirejs": "^2.3.6",
59-
"rollup": "^1.4.1",
60-
"rollup-plugin-babel": "^4.3.2",
61-
"rollup-plugin-commonjs": "^9.2.1",
62-
"rollup-plugin-json": "^4.0.0",
63-
"rollup-plugin-legacy": "^1.0.0",
64-
"rollup-plugin-node-resolve": "^4.0.1",
65-
"rollup-plugin-replace": "^2.1.0",
60+
"rollup": "^2.26.3",
61+
"@rollup/plugin-babel": "^5.2.0",
62+
"@rollup/plugin-commonjs": "^15.0.0",
63+
"@rollup/plugin-json": "^4.1.0",
64+
"@rollup/plugin-node-resolve": "^9.0.0",
65+
"@rollup/plugin-replace": "^2.3.3",
66+
"@rollup/plugin-legacy": "^2.2.0",
6667
"rollup-plugin-uglify": "^6.0.2",
6768
"semantic-release": "^17.1.1",
6869
"sinon": "^7.0.0",

‎rollup.config.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import resolve from 'rollup-plugin-node-resolve';
2-
import commonjs from 'rollup-plugin-commonjs';
3-
import replace from 'rollup-plugin-replace';
4-
import babel from 'rollup-plugin-babel';
5-
import json from 'rollup-plugin-json';
1+
import babel from '@rollup/plugin-babel';
2+
import commonjs from '@rollup/plugin-commonjs';
3+
import json from '@rollup/plugin-json';
4+
import resolve from '@rollup/plugin-node-resolve';
5+
import replace from '@rollup/plugin-replace';
66

77
export default {
88
input: 'src/index.js',
@@ -16,18 +16,22 @@ export default {
1616
},
1717
plugins: [
1818
json(),
19-
babel({
20-
exclude: 'node_modules/**',
21-
plugins: ['@babel/plugin-proposal-object-rest-spread'],
22-
}),
2319
resolve({
2420
browser: true,
2521
}),
2622
replace({
23+
preventAssignment: true,
2724
BUILD_COMPAT_SNIPPET: 'true',
2825
BUILD_COMPAT_LOCAL_STORAGE: 'true',
2926
BUILD_COMPAT_2_0: 'true',
3027
}),
3128
commonjs(),
29+
babel({
30+
babelHelpers: 'bundled',
31+
exclude: 'node_modules/**',
32+
plugins: [
33+
'@babel/plugin-proposal-object-rest-spread'
34+
],
35+
}),
3236
],
3337
};

‎rollup.esm.js

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import commonjs from 'rollup-plugin-commonjs';
2-
import replace from 'rollup-plugin-replace';
3-
import babel from 'rollup-plugin-babel';
4-
import json from 'rollup-plugin-json';
1+
import commonjs from '@rollup/plugin-commonjs';
2+
import replace from '@rollup/plugin-replace';
3+
import babel from '@rollup/plugin-babel';
4+
import json from '@rollup/plugin-json';
55

66
export default {
77
input: 'src/index.js',
@@ -12,21 +12,21 @@ export default {
1212
},
1313
plugins: [
1414
json(),
15-
babel({
16-
exclude: 'node_modules/**',
17-
plugins: [
18-
'@babel/plugin-transform-runtime',
19-
'@babel/plugin-proposal-object-rest-spread'
20-
],
21-
runtimeHelpers: true
22-
}),
2315
replace({
16+
preventAssignment: true,
2417
BUILD_COMPAT_SNIPPET: 'false',
2518
BUILD_COMPAT_LOCAL_STORAGE: 'true',
2619
BUILD_COMPAT_2_0: 'true',
2720
}),
2821
commonjs({
2922
include: "node_modules/**"
3023
}),
24+
babel({
25+
babelHelpers: 'bundled',
26+
exclude: 'node_modules/**',
27+
plugins: [
28+
'@babel/plugin-proposal-object-rest-spread'
29+
],
30+
}),
3131
],
3232
};

‎rollup.snippet-tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import config from './rollup.config.js';
2-
import legacy from 'rollup-plugin-legacy';
2+
import legacy from '@rollup/plugin-legacy';
33

44
config.plugins.push(legacy({
55
'./amplitude-snippet.min.js': 'amplitude',

‎rollup.umd.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import resolve from 'rollup-plugin-node-resolve';
2-
import commonjs from 'rollup-plugin-commonjs';
3-
import replace from 'rollup-plugin-replace';
4-
import babel from 'rollup-plugin-babel';
5-
import json from 'rollup-plugin-json';
1+
import resolve from '@rollup/plugin-node-resolve';
2+
import commonjs from '@rollup/plugin-commonjs';
3+
import replace from '@rollup/plugin-replace';
4+
import babel from '@rollup/plugin-babel';
5+
import json from '@rollup/plugin-json';
66

77
export default {
88
input: 'src/index.js',
@@ -16,18 +16,22 @@ export default {
1616
},
1717
plugins: [
1818
json(),
19-
babel({
20-
exclude: 'node_modules/**',
21-
plugins: ['@babel/plugin-proposal-object-rest-spread'],
22-
}),
2319
resolve({
2420
browser: true,
2521
}),
2622
replace({
23+
preventAssignment: true,
2724
BUILD_COMPAT_SNIPPET: 'true',
2825
BUILD_COMPAT_LOCAL_STORAGE: 'true',
2926
BUILD_COMPAT_2_0: 'true',
3027
}),
3128
commonjs(),
29+
babel({
30+
babelHelpers: 'bundled',
31+
exclude: 'node_modules/**',
32+
plugins: [
33+
'@babel/plugin-proposal-object-rest-spread'
34+
],
35+
}),
3236
],
3337
};

‎src/amplitude-client.js

+44
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { AmplitudeServerZone, getEventLogApi } from './server-zone';
2121
import ConfigManager from './config-manager';
2222
import GlobalScope from './global-scope';
2323

24+
import { AnalyticsConnector } from '@amplitude/analytics-connector';
25+
2426
/**
2527
* AmplitudeClient SDK API - instance constructor.
2628
* The Amplitude class handles creation of client instances, all you need to do is call amplitude.getInstance()
@@ -56,6 +58,9 @@ var AmplitudeClient = function AmplitudeClient(instanceName) {
5658
this._sessionId = null;
5759
this._isInitialized = false;
5860

61+
// used to integrate with experiment SDK (client-side exposure tracking & real-time user properties)
62+
this._connector = null;
63+
5964
this._userAgent = (navigator && navigator.userAgent) || null;
6065
};
6166

@@ -80,6 +85,9 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o
8085
}
8186

8287
try {
88+
// used to integrate with experiment SDK (client-side exposure tracking & real-time user properties)
89+
this._connector = AnalyticsConnector.getInstance(this._instanceName);
90+
8391
_parseConfig(this.options, opt_config);
8492
if (
8593
(isBrowserEnv() || utils.isWebWorkerEnvironment()) &&
@@ -263,6 +271,21 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o
263271
);
264272
}
265273
}
274+
275+
// Sets an event receiver to receive and forward exposure events from the experiment SDK.
276+
this._connector.eventBridge.setEventReceiver((event) => {
277+
this._logEvent(event.eventType, event.eventProperties, event.userProperties);
278+
});
279+
280+
// Set the user ID and device ID in the core identity store to enable fetching variants.
281+
const editor = this._connector.identityStore.editIdentity();
282+
if (this.options.deviceId) {
283+
editor.setDeviceId(this.options.deviceId);
284+
}
285+
if (this.options.userId) {
286+
editor.setUserId(this.options.userId);
287+
}
288+
editor.commit();
266289
} catch (err) {
267290
utils.log.error(err);
268291
if (opt_config && type(opt_config.onError) === 'function') {
@@ -925,6 +948,12 @@ AmplitudeClient.prototype.setUserId = function setUserId(userId, startNewSession
925948
}
926949

927950
_saveCookieData(this);
951+
952+
// Update core identity store to propagate new user info
953+
// to experiment SDK and trigger a fetch if the ID has changed.
954+
if (this._connector) {
955+
this._connector.identityStore.editIdentity().setUserId(this.options.userId).commit();
956+
}
928957
} catch (e) {
929958
utils.log.error(e);
930959
}
@@ -1054,6 +1083,12 @@ AmplitudeClient.prototype.setDeviceId = function setDeviceId(deviceId) {
10541083
if (!utils.isEmptyString(deviceId)) {
10551084
this.options.deviceId = '' + deviceId;
10561085
_saveCookieData(this);
1086+
1087+
// Update core identity store to propagate new user info
1088+
// to experiment SDK and trigger a fetch if the ID has changed.
1089+
if (this._connector) {
1090+
this._connector.identityStore.editIdentity().setDeviceId(this.options.deviceId).commit();
1091+
}
10571092
}
10581093
} catch (e) {
10591094
utils.log.error(e);
@@ -1395,6 +1430,15 @@ AmplitudeClient.prototype._logEvent = function _logEvent(
13951430

13961431
this._sendEventsIfReady();
13971432

1433+
// In the case of an identify event, update the core user store so the experiment SDK can fetch new variants and
1434+
// utilize user properties in real time.
1435+
if (eventType === Constants.IDENTIFY_EVENT && this._connector) {
1436+
this._connector.identityStore
1437+
.editIdentity()
1438+
.updateUserProperties(utils.truncate(utils.validateProperties(userProperties)))
1439+
.commit();
1440+
}
1441+
13981442
return eventId;
13991443
} catch (e) {
14001444
utils.log.error(e);

‎yarn.lock

+180-105
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.