Skip to content

Commit 5259cd0

Browse files
authored
Merge pull request #166 from sputh/unset-utm-params-new-session
Add support for unsetting utm params when a new session is created
2 parents 6a06852 + 31b4300 commit 5259cd0

File tree

7 files changed

+213
-24
lines changed

7 files changed

+213
-24
lines changed

amplitude.js

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,16 @@ var constants = {
948948
REVENUE_PRICE: '$price',
949949
REVENUE_REVENUE_TYPE: '$revenueType',
950950

951-
AMP_DEVICE_ID_PARAM: 'amp_device_id' // url param
951+
AMP_DEVICE_ID_PARAM: 'amp_device_id', // url param
952+
953+
REFERRER: 'referrer',
954+
955+
// UTM Params
956+
UTM_SOURCE: 'utm_source',
957+
UTM_MEDIUM: 'utm_medium',
958+
UTM_CAMPAIGN: 'utm_campaign',
959+
UTM_TERM: 'utm_term',
960+
UTM_CONTENT: 'utm_content'
952961
};
953962

954963
/* jshint bitwise: false */
@@ -2590,11 +2599,11 @@ var getUtmData = function getUtmData(rawCookie, query) {
25902599
return utils.getQueryParam(queryName, query) || utils.getQueryParam(cookieName, cookie);
25912600
};
25922601

2593-
var utmSource = fetchParam('utm_source', query, 'utmcsr', cookie);
2594-
var utmMedium = fetchParam('utm_medium', query, 'utmcmd', cookie);
2595-
var utmCampaign = fetchParam('utm_campaign', query, 'utmccn', cookie);
2596-
var utmTerm = fetchParam('utm_term', query, 'utmctr', cookie);
2597-
var utmContent = fetchParam('utm_content', query, 'utmcct', cookie);
2602+
var utmSource = fetchParam(constants.UTM_SOURCE, query, 'utmcsr', cookie);
2603+
var utmMedium = fetchParam(constants.UTM_MEDIUM, query, 'utmcmd', cookie);
2604+
var utmCampaign = fetchParam(constants.UTM_CAMPAIGN, query, 'utmccn', cookie);
2605+
var utmTerm = fetchParam(constants.UTM_TERM, query, 'utmctr', cookie);
2606+
var utmContent = fetchParam(constants.UTM_CONTENT, query, 'utmcct', cookie);
25982607

25992608
var utmData = {};
26002609
var addIfNotNull = function addIfNotNull(key, value) {
@@ -2603,11 +2612,11 @@ var getUtmData = function getUtmData(rawCookie, query) {
26032612
}
26042613
};
26052614

2606-
addIfNotNull('utm_source', utmSource);
2607-
addIfNotNull('utm_medium', utmMedium);
2608-
addIfNotNull('utm_campaign', utmCampaign);
2609-
addIfNotNull('utm_term', utmTerm);
2610-
addIfNotNull('utm_content', utmContent);
2615+
addIfNotNull(constants.UTM_SOURCE, utmSource);
2616+
addIfNotNull(constants.UTM_MEDIUM, utmMedium);
2617+
addIfNotNull(constants.UTM_CAMPAIGN, utmCampaign);
2618+
addIfNotNull(constants.UTM_TERM, utmTerm);
2619+
addIfNotNull(constants.UTM_CONTENT, utmContent);
26112620

26122621
return utmData;
26132622
};
@@ -6661,6 +6670,7 @@ var DEFAULT_OPTIONS = {
66616670
region: true,
66626671
version_name: true
66636672
},
6673+
unsetParamsReferrerOnNewSession: false,
66646674
unsentKey: 'amplitude_unsent',
66656675
unsentIdentifyKey: 'amplitude_unsent_identify',
66666676
uploadBatchSize: 100
@@ -6770,6 +6780,9 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o
67706780

67716781
var now = new Date().getTime();
67726782
if (!this._sessionId || !this._lastEventTime || now - this._lastEventTime > this.options.sessionTimeout) {
6783+
if (this.options.unsetParamsReferrerOnNewSession) {
6784+
this._unsetUTMParams();
6785+
}
67736786
this._newSession = true;
67746787
this._sessionId = now;
67756788

@@ -7167,6 +7180,21 @@ AmplitudeClient.prototype._initUtmData = function _initUtmData(queryParams, cook
71677180
_sendParamsReferrerUserProperties(this, utmProperties);
71687181
};
71697182

7183+
/**
7184+
* Unset the utm params from the Amplitude instance and update the identify.
7185+
* @private
7186+
*/
7187+
AmplitudeClient.prototype._unsetUTMParams = function _unsetUTMParams() {
7188+
var identify = new Identify();
7189+
identify.unset(constants.REFERRER);
7190+
identify.unset(constants.UTM_SOURCE);
7191+
identify.unset(constants.UTM_MEDIUM);
7192+
identify.unset(constants.UTM_CAMPAIGN);
7193+
identify.unset(constants.UTM_TERM);
7194+
identify.unset(constants.UTM_CONTENT);
7195+
this.identify(identify);
7196+
};
7197+
71707198
/**
71717199
* The calling function should determine when it is appropriate to send these user properties. This function
71727200
* will no longer contain any session storage checking logic.

amplitude.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/amplitude-client.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o
122122

123123
var now = new Date().getTime();
124124
if (!this._sessionId || !this._lastEventTime || now - this._lastEventTime > this.options.sessionTimeout) {
125+
if (this.options.unsetParamsReferrerOnNewSession) {
126+
this._unsetUTMParams();
127+
}
125128
this._newSession = true;
126129
this._sessionId = now;
127130

@@ -520,6 +523,21 @@ AmplitudeClient.prototype._initUtmData = function _initUtmData(queryParams, cook
520523
_sendParamsReferrerUserProperties(this, utmProperties);
521524
};
522525

526+
/**
527+
* Unset the utm params from the Amplitude instance and update the identify.
528+
* @private
529+
*/
530+
AmplitudeClient.prototype._unsetUTMParams = function _unsetUTMParams() {
531+
var identify = new Identify();
532+
identify.unset(Constants.REFERRER);
533+
identify.unset(Constants.UTM_SOURCE);
534+
identify.unset(Constants.UTM_MEDIUM);
535+
identify.unset(Constants.UTM_CAMPAIGN);
536+
identify.unset(Constants.UTM_TERM);
537+
identify.unset(Constants.UTM_CONTENT);
538+
this.identify(identify);
539+
};
540+
523541
/**
524542
* The calling function should determine when it is appropriate to send these user properties. This function
525543
* will no longer contain any session storage checking logic.
@@ -980,7 +998,7 @@ AmplitudeClient.prototype._logEvent = function _logEvent(eventType, eventPropert
980998
},
981999
sequence_number: sequenceNumber, // for ordering events and identifys
9821000
groups: utils.truncate(utils.validateGroups(groups)),
983-
group_properties: utils.truncate(utils.validateProperties(groupProperties)),
1001+
group_properties: utils.truncate(utils.validateProperties(groupProperties)),
9841002
user_agent: this._userAgent
9851003
};
9861004

src/constants.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,14 @@ export default {
2727
REVENUE_PRICE: '$price',
2828
REVENUE_REVENUE_TYPE: '$revenueType',
2929

30-
AMP_DEVICE_ID_PARAM: 'amp_device_id' // url param
30+
AMP_DEVICE_ID_PARAM: 'amp_device_id', // url param
31+
32+
REFERRER: 'referrer',
33+
34+
// UTM Params
35+
UTM_SOURCE: 'utm_source',
36+
UTM_MEDIUM: 'utm_medium',
37+
UTM_CAMPAIGN: 'utm_campaign',
38+
UTM_TERM: 'utm_term',
39+
UTM_CONTENT: 'utm_content'
3140
};

src/options.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default {
3535
region: true,
3636
version_name: true
3737
},
38+
unsetParamsReferrerOnNewSession: false,
3839
unsentKey: 'amplitude_unsent',
3940
unsentIdentifyKey: 'amplitude_unsent_identify',
4041
uploadBatchSize: 100,

src/utm.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import utils from './utils';
2+
import Constants from './constants';
23

34
var getUtmData = function getUtmData(rawCookie, query) {
45
// Translate the utmz cookie format into url query string format.
@@ -9,11 +10,11 @@ var getUtmData = function getUtmData(rawCookie, query) {
910
utils.getQueryParam(cookieName, cookie);
1011
};
1112

12-
var utmSource = fetchParam('utm_source', query, 'utmcsr', cookie);
13-
var utmMedium = fetchParam('utm_medium', query, 'utmcmd', cookie);
14-
var utmCampaign = fetchParam('utm_campaign', query, 'utmccn', cookie);
15-
var utmTerm = fetchParam('utm_term', query, 'utmctr', cookie);
16-
var utmContent = fetchParam('utm_content', query, 'utmcct', cookie);
13+
var utmSource = fetchParam(Constants.UTM_SOURCE, query, 'utmcsr', cookie);
14+
var utmMedium = fetchParam(Constants.UTM_MEDIUM, query, 'utmcmd', cookie);
15+
var utmCampaign = fetchParam(Constants.UTM_CAMPAIGN, query, 'utmccn', cookie);
16+
var utmTerm = fetchParam(Constants.UTM_TERM, query, 'utmctr', cookie);
17+
var utmContent = fetchParam(Constants.UTM_CONTENT, query, 'utmcct', cookie);
1718

1819
var utmData = {};
1920
var addIfNotNull = function addIfNotNull(key, value) {
@@ -22,11 +23,11 @@ var getUtmData = function getUtmData(rawCookie, query) {
2223
}
2324
};
2425

25-
addIfNotNull('utm_source', utmSource);
26-
addIfNotNull('utm_medium', utmMedium);
27-
addIfNotNull('utm_campaign', utmCampaign);
28-
addIfNotNull('utm_term', utmTerm);
29-
addIfNotNull('utm_content', utmContent);
26+
addIfNotNull(Constants.UTM_SOURCE, utmSource);
27+
addIfNotNull(Constants.UTM_MEDIUM, utmMedium);
28+
addIfNotNull(Constants.UTM_CAMPAIGN, utmCampaign);
29+
addIfNotNull(Constants.UTM_TERM, utmTerm);
30+
addIfNotNull(Constants.UTM_CONTENT, utmContent);
3031

3132
return utmData;
3233
};

test/amplitude-client.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,6 +2566,8 @@ describe('setVersionName', function() {
25662566

25672567
afterEach(function() {
25682568
reset();
2569+
cookie.remove('__utmz');
2570+
cookie.reset();
25692571
clock.restore();
25702572
});
25712573

@@ -2701,6 +2703,136 @@ describe('setVersionName', function() {
27012703
}
27022704
});
27032705
});
2706+
2707+
it('should allow utm parameters to unset upon instantiating a new session', function(done) {
2708+
reset();
2709+
// send first $identify call with UTM params
2710+
sinon.stub(amplitude, '_getUrlParams').returns('?utm_source=google&utm_campaign=(organic)&utm_medium=organic&utm_term=(none)&utm_content=link');
2711+
amplitude.init(apiKey, undefined, {includeUtm: true, saveParamsReferrerOncePerSession: false, unsetParamsReferrerOnNewSession: true});
2712+
2713+
// advance clock to force new session
2714+
clock.tick(30 * 60 * 1000 + 1);
2715+
amplitude._getUrlParams.restore();
2716+
2717+
// send new session events
2718+
amplitude.init(apiKey, undefined, {includeUtm: true, saveParamsReferrerOncePerSession: false, unsetParamsReferrerOnNewSession: true});
2719+
amplitude.logEvent('UTM Test Event', {});
2720+
2721+
// ensure the server has responded
2722+
server.respondWith('success');
2723+
server.respond();
2724+
2725+
var firstSessionEvents = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
2726+
var secondSessionEvents = JSON.parse(querystring.parse(server.requests[1].requestBody).e);
2727+
var firstSessionInit = firstSessionEvents[0];
2728+
var secondSessionInit = secondSessionEvents[0];
2729+
var secondSessionEvent = secondSessionEvents[1];
2730+
2731+
assert.equal(firstSessionInit.event_type, '$identify', 'should correctly called $identify');
2732+
assert.deepEqual(firstSessionInit.user_properties, {
2733+
$setOnce: {
2734+
initial_utm_source: "google",
2735+
initial_utm_medium: "organic",
2736+
initial_utm_campaign: "(organic)",
2737+
initial_utm_term: "(none)",
2738+
initial_utm_content: "link"
2739+
},
2740+
$set: {
2741+
utm_source: "google",
2742+
utm_medium: "organic",
2743+
utm_campaign: "(organic)",
2744+
utm_term: "(none)",
2745+
utm_content: "link"
2746+
}
2747+
}, 'should call $identify to set the correct UTM params');
2748+
assert.equal(secondSessionInit.event_type, '$identify', 'should have re-called $identify to unset utm params upon a new session');
2749+
assert.deepEqual(secondSessionInit.user_properties, {
2750+
'$unset': {
2751+
referrer: "-",
2752+
utm_source:"-",
2753+
utm_medium:"-",
2754+
utm_campaign:"-",
2755+
utm_term:"-",
2756+
utm_content:"-"
2757+
}
2758+
}, 'should correctly unset UTM params');
2759+
assert.deepEqual(secondSessionEvent.user_properties, {}, 'should correctly unset UTM params upon a new session');
2760+
done()
2761+
});
2762+
2763+
it('should reset utm parameters if it has changed during a new session', function(done) {
2764+
reset();
2765+
// send first $identify call with UTM params
2766+
sinon.stub(amplitude, '_getUrlParams').returns('?utm_source=google&utm_campaign=(organic)&utm_medium=organic&utm_term=(none)&utm_content=link');
2767+
amplitude.init(apiKey, undefined, {includeUtm: true, saveParamsReferrerOncePerSession: false, unsetParamsReferrerOnNewSession: true});
2768+
2769+
// advance clock to force new session, enter through a different campaign
2770+
clock.tick(30 * 60 * 1000 + 1);
2771+
amplitude._getUrlParams.restore();
2772+
sinon.stub(amplitude, '_getUrlParams').returns('?utm_source=google&utm_campaign=(mail_promotion)&utm_medium=email&utm_term=(none)&utm_content=click');
2773+
amplitude.init(apiKey, undefined, {includeUtm: true, saveParamsReferrerOncePerSession: false, unsetParamsReferrerOnNewSession: true});
2774+
2775+
// send new session events
2776+
amplitude.init(apiKey, undefined, {includeUtm: true, saveParamsReferrerOncePerSession: false, unsetParamsReferrerOnNewSession: true});
2777+
amplitude.logEvent('UTM Test Event', {});
2778+
2779+
// ensure the server has responded
2780+
server.respondWith('success');
2781+
server.respond();
2782+
2783+
amplitude._getUrlParams.restore();
2784+
var firstSessionEvents = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
2785+
var secondSessionEvents = JSON.parse(querystring.parse(server.requests[1].requestBody).e);
2786+
var firstSessionInit = firstSessionEvents[0];
2787+
var secondSessionInit = secondSessionEvents[0];
2788+
var secondSessionEvent = secondSessionEvents[1];
2789+
2790+
assert.equal(firstSessionInit.event_type, '$identify', 'should correctly called $identify');
2791+
assert.deepEqual(firstSessionInit.user_properties, {
2792+
$setOnce: {
2793+
initial_utm_source: "google",
2794+
initial_utm_medium: "organic",
2795+
initial_utm_campaign: "(organic)",
2796+
initial_utm_term: "(none)",
2797+
initial_utm_content: "link"
2798+
},
2799+
$set: {
2800+
utm_source: "google",
2801+
utm_medium: "organic",
2802+
utm_campaign: "(organic)",
2803+
utm_term: "(none)",
2804+
utm_content: "link"
2805+
}
2806+
}, 'should call $identify to set the correct UTM params');
2807+
assert.equal(secondSessionInit.event_type, '$identify', 'should have re-called $identify to unset utm params upon a new session');
2808+
assert.deepEqual(secondSessionInit.user_properties, {
2809+
'$unset': {
2810+
referrer: "-",
2811+
utm_source:"-",
2812+
utm_medium:"-",
2813+
utm_campaign:"-",
2814+
utm_term:"-",
2815+
utm_content:"-"
2816+
}
2817+
}, 'should correctly unset UTM params');
2818+
assert.deepEqual(secondSessionEvent.user_properties, {
2819+
$setOnce: {
2820+
initial_utm_source: "google",
2821+
initial_utm_medium: "email",
2822+
initial_utm_campaign: "(mail_promotion)",
2823+
initial_utm_term: "(none)",
2824+
initial_utm_content: "click"
2825+
},
2826+
"$set": {
2827+
"utm_source": "google",
2828+
"utm_medium": "email",
2829+
"utm_campaign": "(mail_promotion)",
2830+
"utm_term": "(none)",
2831+
"utm_content": "click"
2832+
}
2833+
}, 'should correctly set new UTM params upon a new session');
2834+
done()
2835+
});
27042836
});
27052837

27062838
describe('gatherReferrer', function() {

0 commit comments

Comments
 (0)