Skip to content

Commit 63b80bf

Browse files
committed
capture gclid
1 parent 99acda0 commit 63b80bf

File tree

9 files changed

+133
-28
lines changed

9 files changed

+133
-28
lines changed

amplitude.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,9 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o
578578
if (this.options.includeReferrer) {
579579
this._saveReferrer(this._getReferrer());
580580
}
581+
if (this.options.includeGclid) {
582+
this._saveGclid();
583+
}
581584
}
582585
this._lastEventTime = now;
583586
_saveCookieData(this);
@@ -960,6 +963,21 @@ AmplitudeClient.prototype._getReferrer = function _getReferrer() {
960963
return document.referrer;
961964
};
962965

966+
/**
967+
* Try to fetch Google Gclid from url params.
968+
* @private
969+
*/
970+
AmplitudeClient.prototype._saveGclid = function _saveGclid(queryParams) {
971+
queryParams = queryParams || location.search;
972+
debugger;
973+
var gclid = utils.getQueryParam('gclid', queryParams);
974+
if (utils.isEmptyString(gclid)) {
975+
return;
976+
}
977+
var gclidProperties = {'gclid': gclid};
978+
_sendUserPropertiesOncePerSession(this, Constants.GCLID, gclidProperties);
979+
};
980+
963981
/**
964982
* Parse the domain from referrer info
965983
* @private
@@ -1635,6 +1653,7 @@ module.exports = {
16351653
REFERRER: 'amplitude_referrer',
16361654
SESSION_ID: 'amplitude_sessionId',
16371655
UTM_PROPERTIES: 'amplitude_utm_properties',
1656+
GCLID: 'amplitude_gclid',
16381657

16391658
// Used in cookie as well
16401659
DEVICE_ID: 'amplitude_deviceId',
@@ -2561,12 +2580,12 @@ var regexp = /[a-z0-9][a-z0-9\-]*[a-z0-9]\.[a-z\.]{2,6}$/i;
25612580

25622581
/**
25632582
* Get the top domain.
2564-
*
2583+
*
25652584
* Official Grammar: http://tools.ietf.org/html/rfc883#page-56
25662585
* Look for tlds with up to 2-6 characters.
2567-
*
2586+
*
25682587
* Example:
2569-
*
2588+
*
25702589
* domain('http://localhost:3000/baz');
25712590
* // => ''
25722591
* domain('http://dev:3000/baz');
@@ -2575,7 +2594,7 @@ var regexp = /[a-z0-9][a-z0-9\-]*[a-z0-9]\.[a-z\.]{2,6}$/i;
25752594
* // => ''
25762595
* domain('http://segment.io/baz');
25772596
* // => 'segment.io'
2578-
*
2597+
*
25792598
* @param {String} url
25802599
* @return {String}
25812600
* @api public
@@ -2864,9 +2883,18 @@ var validateGroupName = function validateGroupName(key, groupName) {
28642883
'. Please use strings or array of strings for groupName');
28652884
};
28662885

2886+
// parses the value of a url param (for example ?gclid=1234&...)
2887+
var getQueryParam = function getQueryParam(name, query) {
2888+
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
2889+
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
2890+
var results = regex.exec(query);
2891+
return results === null ? undefined : decodeURIComponent(results[1].replace(/\+/g, " "));
2892+
};
2893+
28672894
module.exports = {
28682895
log: log,
28692896
isEmptyString: isEmptyString,
2897+
getQueryParam: getQueryParam,
28702898
sessionStorageEnabled: sessionStorageEnabled,
28712899
truncate: truncate,
28722900
validateGroups: validateGroups,
@@ -3029,20 +3057,13 @@ module.exports = localStorage;
30293057
13: [function(require, module, exports) {
30303058
var utils = require('./utils');
30313059

3032-
var getUtmParam = function getUtmParam(name, query) {
3033-
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
3034-
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
3035-
var results = regex.exec(query);
3036-
return results === null ? undefined : decodeURIComponent(results[1].replace(/\+/g, " "));
3037-
};
3038-
30393060
var getUtmData = function getUtmData(rawCookie, query) {
30403061
// Translate the utmz cookie format into url query string format.
30413062
var cookie = rawCookie ? '?' + rawCookie.split('.').slice(-1)[0].replace(/\|/g, '&') : '';
30423063

30433064
var fetchParam = function fetchParam(queryName, query, cookieName, cookie) {
3044-
return getUtmParam(queryName, query) ||
3045-
getUtmParam(cookieName, cookie);
3065+
return utils.getQueryParam(queryName, query) ||
3066+
utils.getQueryParam(cookieName, cookie);
30463067
};
30473068

30483069
var utmSource = fetchParam('utm_source', query, 'utmcsr', cookie);
@@ -3267,7 +3288,7 @@ module.exports = Identify;
32673288
*
32683289
* Licensed under the MIT license:
32693290
* http://www.opensource.org/licenses/MIT
3270-
*
3291+
*
32713292
* Based on
32723293
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
32733294
* Digest Algorithm, as defined in RFC 1321.
@@ -4950,6 +4971,7 @@ module.exports = {
49504971
eventUploadThreshold: 30,
49514972
eventUploadPeriodMillis: 30 * 1000, // 30s
49524973
forceHttps: false,
4974+
includeGclid: false,
49534975
};
49544976

49554977
}, {"./language":29}],
@@ -4964,4 +4986,4 @@ module.exports = {
49644986
};
49654987

49664988
}, {}]}, {}, {"1":""})
4967-
);
4989+
);

amplitude.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/amplitude-client.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ AmplitudeClient.prototype.init = function init(apiKey, opt_userId, opt_config, o
9797
if (this.options.includeReferrer) {
9898
this._saveReferrer(this._getReferrer());
9999
}
100+
if (this.options.includeGclid) {
101+
this._saveGclid();
102+
}
100103
}
101104
this._lastEventTime = now;
102105
_saveCookieData(this);
@@ -479,6 +482,20 @@ AmplitudeClient.prototype._getReferrer = function _getReferrer() {
479482
return document.referrer;
480483
};
481484

485+
/**
486+
* Try to fetch Google Gclid from url params.
487+
* @private
488+
*/
489+
AmplitudeClient.prototype._saveGclid = function _saveGclid(queryParams) {
490+
queryParams = queryParams || location.search;
491+
var gclid = utils.getQueryParam('gclid', queryParams);
492+
if (utils.isEmptyString(gclid)) {
493+
return;
494+
}
495+
var gclidProperties = {'gclid': gclid};
496+
_sendUserPropertiesOncePerSession(this, Constants.GCLID, gclidProperties);
497+
};
498+
482499
/**
483500
* Parse the domain from referrer info
484501
* @private

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module.exports = {
1313
REFERRER: 'amplitude_referrer',
1414
SESSION_ID: 'amplitude_sessionId',
1515
UTM_PROPERTIES: 'amplitude_utm_properties',
16+
GCLID: 'amplitude_gclid',
1617

1718
// Used in cookie as well
1819
DEVICE_ID: 'amplitude_deviceId',

src/options.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ module.exports = {
2121
eventUploadThreshold: 30,
2222
eventUploadPeriodMillis: 30 * 1000, // 30s
2323
forceHttps: false,
24+
includeGclid: false,
2425
};

src/utils.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,18 @@ var validateGroupName = function validateGroupName(key, groupName) {
188188
'. Please use strings or array of strings for groupName');
189189
};
190190

191+
// parses the value of a url param (for example ?gclid=1234&...)
192+
var getQueryParam = function getQueryParam(name, query) {
193+
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
194+
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
195+
var results = regex.exec(query);
196+
return results === null ? undefined : decodeURIComponent(results[1].replace(/\+/g, " "));
197+
};
198+
191199
module.exports = {
192200
log: log,
193201
isEmptyString: isEmptyString,
202+
getQueryParam: getQueryParam,
194203
sessionStorageEnabled: sessionStorageEnabled,
195204
truncate: truncate,
196205
validateGroups: validateGroups,

src/utm.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
var utils = require('./utils');
22

3-
var getUtmParam = function getUtmParam(name, query) {
4-
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
5-
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
6-
var results = regex.exec(query);
7-
return results === null ? undefined : decodeURIComponent(results[1].replace(/\+/g, " "));
8-
};
9-
103
var getUtmData = function getUtmData(rawCookie, query) {
114
// Translate the utmz cookie format into url query string format.
125
var cookie = rawCookie ? '?' + rawCookie.split('.').slice(-1)[0].replace(/\|/g, '&') : '';
136

147
var fetchParam = function fetchParam(queryName, query, cookieName, cookie) {
15-
return getUtmParam(queryName, query) ||
16-
getUtmParam(cookieName, cookie);
8+
return utils.getQueryParam(queryName, query) ||
9+
utils.getQueryParam(cookieName, cookie);
1710
};
1811

1912
var utmSource = fetchParam('utm_source', query, 'utmcsr', cookie);

test/amplitude-client.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,6 +2482,68 @@ describe('setVersionName', function() {
24822482
});
24832483
});
24842484

2485+
describe('gatherGclid', function() {
2486+
var clock;
2487+
beforeEach(function() {
2488+
clock = sinon.useFakeTimers(100);
2489+
amplitude.init(apiKey);
2490+
});
2491+
2492+
afterEach(function() {
2493+
reset();
2494+
clock.restore();
2495+
});
2496+
2497+
it('should parse gclid', function() {
2498+
reset();
2499+
var urlParams = '?utm_source=amplitude&utm_medium=email&utm_term=terms&gclid=12345';
2500+
clock.tick(30 * 60 * 1000 + 1);
2501+
amplitude._saveGclid(urlParams);
2502+
2503+
var expectedProperties = {
2504+
gclid: '12345'
2505+
}
2506+
2507+
assert.lengthOf(server.requests, 1);
2508+
var events = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
2509+
assert.equal(events[0].event_type, '$identify');
2510+
assert.deepEqual(events[0].user_properties, {
2511+
'$setOnce': {'initial_gclid': '12345'},
2512+
'$set': expectedProperties
2513+
});
2514+
server.respondWith('success');
2515+
server.respond();
2516+
2517+
amplitude.logEvent('Gclid Test Event', {});
2518+
assert.lengthOf(server.requests, 2);
2519+
var events = JSON.parse(querystring.parse(server.requests[1].requestBody).e);
2520+
assert.deepEqual(events[0].user_properties, {});
2521+
2522+
// verify session storage set
2523+
assert.deepEqual(JSON.parse(sessionStorage.getItem('amplitude_gclid')), expectedProperties);
2524+
});
2525+
2526+
it('should not set gclid if gclid data already in session storage', function() {
2527+
reset();
2528+
var existingProperties = {gclid: '67890'};
2529+
sessionStorage.setItem('amplitude_gclid', JSON.stringify(existingProperties));
2530+
var utmParams = '?utm_source=amplitude&utm_medium=email&utm_term=terms&gclid=12345';
2531+
clock.tick(30 * 60 * 1000 + 1);
2532+
amplitude._saveGclid(utmParams);
2533+
2534+
assert.lengthOf(server.requests, 1);
2535+
var events = JSON.parse(querystring.parse(server.requests[0].requestBody).e);
2536+
assert.lengthOf(events, 1);
2537+
2538+
// first event should be identify with initial_utm properties and NO existing utm properties
2539+
assert.equal(events[0].event_type, '$identify');
2540+
assert.deepEqual(events[0].user_properties, {'$setOnce': {initial_gclid: '12345'}});
2541+
2542+
// should not override any existing gclid values in session storage
2543+
assert.equal(sessionStorage.getItem('amplitude_gclid'), JSON.stringify(existingProperties));
2544+
});
2545+
});
2546+
24852547
describe('logRevenue', function() {
24862548
beforeEach(function() {
24872549
amplitude.init(apiKey);

test/browser/amplitudejs.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
}
8888
</script>
8989
<script>
90-
amplitude.init('a2dbce0e18dfe5f8e74493843ff5c053', null, {includeReferrer: true, includeUtm: true}, function() {
90+
amplitude.init('a2dbce0e18dfe5f8e74493843ff5c053', null, {includeReferrer: true, includeUtm: true, includeGclid: true}, function() {
9191
alert(amplitude.options.deviceId);
9292
});
9393
amplitude.setVersionName('Web');

0 commit comments

Comments
 (0)