Skip to content

Instantly share code, notes, and snippets.

@keithws
Last active May 27, 2024 01:25
Show Gist options
  • Save keithws/cf0c0e924e892cf1ac2524d2615a73b9 to your computer and use it in GitHub Desktop.
Save keithws/cf0c0e924e892cf1ac2524d2615a73b9 to your computer and use it in GitHub Desktop.
Google Tag Manager tag to load GeoIP data into the GTM data layer. Helps with GDPR.
<script src="//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js"></script>
<script>
/*
* get geographical location data by ip address
* uses the free ipify.org services
* and the paid Maxmind GeoIP2 Precision services
*/
(function (geoip2) {
"use strict";
// mark the start of the script loading
var start = (new Date()).getTime();
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "geoip.js",
"geoip.start": start
});
triggerDOMEvent(document, "geoipjs", { "start": start });
var isGeoIPLoaded, isWindowLoaded;
function onWindowLoadAndGeoIPLoad () {
if (isGeoIPLoaded && isWindowLoaded) {
// push location data into GTM data layer
window.dataLayer.push({
"event": "geoip.window.load"
});
triggerDOMEvent(document, "geoipwindowload");
}
}
// there is a possiblity that the document completes loading before now
if (document.readyState === "complete") {
isWindowLoaded = true;
onWindowLoadAndGeoIPLoad();
} else {
window.addEventListener("load", function onWindowLoad () {
isWindowLoaded = true;
onWindowLoadAndGeoIPLoad();
});
}
// helper function to push data to data layer
function onSuccess (data, doNotSaveData) {
// push location data into GTM data layer
window.dataLayer.push({
"event": "geoip.load",
"geoip.data": data
});
triggerDOMEvent(document, "geoipload", data);
isGeoIPLoaded = true;
onWindowLoadAndGeoIPLoad();
if (!doNotSaveData) {
// store data in local storage
if (data && data.traits && data.traits.ip_address) {
var key = "maxmind.geoip2.data." + data.traits.ip_address;
localStorage.setItem(key, JSON.stringify(data));
}
}
}
// helper function to log and throw error
function onError (err) {
throw new Error(err.code + ": " + err.error);
}
// helper function to execute once we have the IP address
function onIPLoaded (ip) {
window.dataLayer.push({
"event": "geoip.ip",
"geoip.ip": ip
});
triggerDOMEvent(document, "geoipip", { "ip": ip });
// check local storage for geoip data for that IP address
var key = "maxmind.geoip2.data." + ip;
var data = localStorage.getItem(key);
if (data) {
// GeoIP data found in local storage
try {
data = JSON.parse(data);
onSuccess(data, true);
} catch (err) {
throw err;
}
} else {
// fetch GeoIP data from Maxmind
geoip2.country(onSuccess, onError);
}
}
var ip = sessionStorage.getItem("ipify.ip");
if (ip) {
// use IP address retrived from session cache
onIPLoaded(ip);
} else {
// use ipify.org to get IP address
// listen for when the IP address has been loaded by ipfiy
window.ipifyCallback = function ipifyCallback (json) {
sessionStorage.setItem("ipify.ip", json.ip);
onIPLoaded(json.ip);
};
// inject the script from ipify.org
var newNode, referenceNode;
referenceNode = document.getElementsByTagName("script")[0];
newNode = document.createElement("script");
newNode.async = true;
newNode.src = "https://api.ipify.org?format=jsonp&callback=ipifyCallback";
referenceNode.parentNode.insertBefore(newNode, referenceNode);
}
// helper function to trigger native DOM events
function triggerDOMEvent (element, type, detail, bubbles, cancelable) {
// defaults
if (!(element instanceof EventTarget)) {
throw new Error("First argument, element, must be an instance of EventTarget.");
}
bubbles = bubbles || false;
cancelable = cancelable || false;
var event;
if (CustomEvent) {
// the modern way
event = new CustomEvent(type, {
"bubbles": bubbles,
"cancelable": cancelable,
"detail": detail
});
} else {
// the old fashioned way to support Internet Explorer
event = document.createEvent("Event");
event.initEvent(type, bubbles, cancelable, detail);
}
// be nice and set the current target
event.currentTarget = element;
// target can be any Element or other EventTarget.
element.dispatchEvent(event);
}
}(window.geoip2));
</script>
@keithws
Copy link
Author

keithws commented Jan 31, 2019

Updated with code to trigger events on the DOM as well as in GTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment