Skip to content

Commit

Permalink
feat: add logAttributionCapturedEvent option (#295)
Browse files Browse the repository at this point in the history
* GROWTH-1094 add logAttributionCapturedEvent option to log Amplitude Events when attribution data is captured

* Add spread property

* Revert changes to test html

* Rename ATTRIBUTION_EVENT to

* GROWTH-1094 add missing semicolon

* Rename ATTRIBUTION_CAPTURED

* Add tests for feature
  • Loading branch information
kelsonpw authored Sep 19, 2020
1 parent 61b6590 commit 309dac3
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 4 deletions.
22 changes: 19 additions & 3 deletions src/amplitude-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,14 +354,27 @@ AmplitudeClient.prototype._migrateUnsentEvents = function _migrateUnsentEvents(c
* @private
*/
AmplitudeClient.prototype._trackParamsAndReferrer = function _trackParamsAndReferrer() {
let utmProperties;
let referrerProperties;
let gclidProperties;
if (this.options.includeUtm) {
this._initUtmData();
utmProperties = this._initUtmData();
}
if (this.options.includeReferrer) {
this._saveReferrer(this._getReferrer());
referrerProperties = this._saveReferrer(this._getReferrer());
}
if (this.options.includeGclid) {
this._saveGclid(this._getUrlParams());
gclidProperties = this._saveGclid(this._getUrlParams());
}
if (this.options.logAttributionCapturedEvent) {
const attributionProperties = {
...utmProperties,
...referrerProperties,
...gclidProperties,
};
if (Object.keys(attributionProperties).length > 0) {
this.logEvent(Constants.ATTRIBUTION_EVENT, attributionProperties);
}
}
};

Expand Down Expand Up @@ -675,6 +688,7 @@ AmplitudeClient.prototype._initUtmData = function _initUtmData(queryParams, cook
cookieParams = cookieParams || this.cookieStorage.get('__utmz');
var utmProperties = getUtmData(cookieParams, queryParams);
_sendParamsReferrerUserProperties(this, utmProperties);
return utmProperties;
};

/**
Expand Down Expand Up @@ -739,6 +753,7 @@ AmplitudeClient.prototype._saveGclid = function _saveGclid(urlParams) {
}
var gclidProperties = {'gclid': gclid};
_sendParamsReferrerUserProperties(this, gclidProperties);
return gclidProperties;
};

/**
Expand Down Expand Up @@ -778,6 +793,7 @@ AmplitudeClient.prototype._saveReferrer = function _saveReferrer(referrer) {
'referring_domain': this._getReferringDomain(referrer)
};
_sendParamsReferrerUserProperties(this, referrerInfo);
return referrerInfo;
};

/**
Expand Down
4 changes: 3 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@ export default {
UTM_MEDIUM: 'utm_medium',
UTM_CAMPAIGN: 'utm_campaign',
UTM_TERM: 'utm_term',
UTM_CONTENT: 'utm_content'
UTM_CONTENT: 'utm_content',

ATTRIBUTION_EVENT: '[Amplitude] Attribution Captured'
};
1 change: 1 addition & 0 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default {
includeUtm: false,
language: language.getLanguage(),
logLevel: 'WARN',
logAttributionCapturedEvent: false,
optOut: false,
onError: () => {},
platform,
Expand Down
103 changes: 103 additions & 0 deletions test/amplitude-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2952,6 +2952,32 @@ describe('setVersionName', function() {
});
});

it('should log attribution event when referrer is updated if configured', function() {
clock.tick(30 * 60 * 1000 + 1); // force new session
amplitude.init(apiKey, undefined, {includeReferrer: true, logAttributionCapturedEvent: true, batchEvents: true, eventUploadThreshold: 2});
assert.lengthOf(server.requests, 1);
var events = JSON.parse(queryString.parse(server.requests[0].requestBody).e);
assert.lengthOf(events, 2);
// first event should be identify with initial_referrer and referrer
assert.equal(events[0].event_type, '$identify');
assert.deepEqual(events[0].user_properties, {
'$set': {
'referrer': 'https://amplitude.com/contact',
'referring_domain': 'amplitude.com'
},
'$setOnce': {
'initial_referrer': 'https://amplitude.com/contact',
'initial_referring_domain': 'amplitude.com'
}
});
// second event should be the attribution captured event with referrer information
assert.equal(events[1].event_type, constants.ATTRIBUTION_EVENT);
assert.deepEqual(events[1].event_properties, {
'referrer': 'https://amplitude.com/contact',
'referring_domain': 'amplitude.com'
});
});

it('should not delete unsent events saved to localStorage', function() {
var existingEvent = '[{"device_id":"test_device_id","user_id":"test_user_id","timestamp":1453769146589,' +
'"event_id":49,"session_id":1453763315544,"event_type":"clicked","version_name":"Web","platform":"Web"' +
Expand Down Expand Up @@ -2993,6 +3019,62 @@ describe('setVersionName', function() {
}
});
});

it('should log attribution event when UTMs are captured if configured', function() {
reset();
cookie.set('__utmz', '133232535.1424926227.1.1.utmcct=top&utmccn=new');
clock.tick(30 * 60 * 1000 + 1);
amplitude.init(apiKey, undefined, {includeUtm: true, logAttributionCapturedEvent: true, batchEvents: true, eventUploadThreshold: 2});
assert.lengthOf(server.requests, 1);
var events = JSON.parse(queryString.parse(server.requests[0].requestBody).e);
// first event should be identify with UTM state
assert.equal(events[0].event_type, '$identify');
assert.deepEqual(events[0].user_properties, {
'$setOnce': {
initial_utm_campaign: 'new',
initial_utm_content: 'top'
},
'$set': {
utm_campaign: 'new',
utm_content: 'top'
}
});
// second event should be the attribution captured event with UTMs populated
assert.equal(events[1].event_type, constants.ATTRIBUTION_EVENT);
assert.deepEqual(events[1].event_properties, {
utm_campaign: 'new',
utm_content: 'top'
});
});

it('should log attribution event more than once per session if configured and UTMs changes', function() {
reset();
cookie.set('__utmz', '133232535.1424926227.1.1.utmcct=top&utmccn=new');
amplitude.init(apiKey, undefined, {
includeUtm: true, logAttributionCapturedEvent: true, saveParamsReferrerOncePerSession: false, batchEvents: true, eventUploadThreshold: 2
});
// even though same session, utm params are sent again
assert.lengthOf(server.requests, 1);
var events = JSON.parse(queryString.parse(server.requests[0].requestBody).e);
// first event should be identify with UTM state
assert.equal(events[0].event_type, '$identify');
assert.deepEqual(events[0].user_properties, {
'$setOnce': {
initial_utm_campaign: 'new',
initial_utm_content: 'top'
},
'$set': {
utm_campaign: 'new',
utm_content: 'top'
}
});
// second event should be the attribution captured event with UTMs populated
assert.equal(events[1].event_type, constants.ATTRIBUTION_EVENT);
assert.deepEqual(events[1].event_properties, {
utm_campaign: 'new',
utm_content: 'top'
});
});
});

describe('gatherGclid', function() {
Expand Down Expand Up @@ -3050,6 +3132,27 @@ describe('setVersionName', function() {
'$setOnce': {'initial_gclid': '12345'}
});
});

it('should log attribution event when gclid is captured if configured', () => {
clock.tick(30 * 60 * 1000 + 1);
amplitude.init(apiKey, undefined, {includeGclid: true, logAttributionCapturedEvent: true, batchEvents: true, eventUploadThreshold: 2});

assert.lengthOf(server.requests, 1);
var events = JSON.parse(queryString.parse(server.requests[0].requestBody).e);
assert.lengthOf(events, 2);

// first event should be identify with gclid
assert.equal(events[0].event_type, '$identify');
assert.deepEqual(events[0].user_properties, {
'$set': {'gclid': '12345'},
'$setOnce': {'initial_gclid': '12345'}
});
// second event should be the attribution captured event with gclid populated
assert.equal(events[1].event_type, constants.ATTRIBUTION_EVENT);
assert.deepEqual(events[1].event_properties, {
'gclid': '12345'
})
});
});

describe('logRevenue', function() {
Expand Down

0 comments on commit 309dac3

Please sign in to comment.