Basic browser/user detection can be important for providing an enhanced user experience. For example, making a best-guess detection of the user’s IP address (subject to the usual caveats about VPN use) can help in pre-selecting a user’s country of origin, enabling faster form fill-outs. The user’s preferred language, especially on first access of a site, is obviously of huge importance; detecting it early with a non-intrusive script can help avoid clunkier approaches such as passing out language-differentiated URLs to globalized versions of your site, which may be passed between users with unintended consequences.
Especially for a site which already makes use of JavaScript, an unobtrusive script can make a difference. And while there are fairly robust libraries such as platform.js, they often do not address all concerns of detecting language, geoIP, and browser. Adding extra dependencies to a site, in terms of maintenance burden and JS payload, is desirable to avoid when possible.
It’s easy enough to create a tiny script which merges freely available geoIP with basic browser/language detection, as shown below. There are many free geoIP web services available these days; a first implementation can simply rely on one, perhaps adding a fallback as necessary, though eventually a more robust solution may become necessary.
The simple demo code, with browser and OS versions not yet filled in, appears below, and may be run at JSFiddle . This could, for example, be passed as a JSON bundle in a call to a web service, or submitted with a page. While the code may be reused freely, as it essentially cobbles together multiple simple well-known methods into an easy-to-use package, the emphasis is on the approach: a lightweight script that avoids heavy dependencies and still captures useful information about a user. As always, use such information responsibly, especially keeping in mind GDPR regulations which will have taken full effect by May 2018.
function UserInfo() {
var self = this;
this.language = ((navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage)) + '').substring(0, 2);
this.browserName = '';
this.browserVersion = '';
this.osName = '';
this.osVersion = '';
this.country = '';
this.ipAddress = '';
this.city = '';
this.region = '';
this.postalCode = '';
if (navigator && navigator.userAgent) {
var ua = (navigator.userAgent + '').toLowerCase();
var platform = ua;
var i = platform.indexOf('(');
if (i > -1)
platform = platform.substring(i + 1);
i = platform.indexOf(')');
if (i > -1)
platform = platform.substring(0, i);
if (platform.indexOf('windows') > -1)
this.osName = 'Windows';
else if (platform.indexOf('android') > -1)
this.osName = 'Android';
else if (platform.indexOf('macintosh') > -1 || platform.indexOf('macos') > -1)
this.osName = 'macOS';
else if (platform.indexOf('iphone') > -1 || platform.indexOf('ipad') > -1)
this.osName = 'iOS';
}
if (!!window.chrome && !!window.chrome.webstore)
this.browserName = 'Chrome';
else if (typeof InstallTrigger !== 'undefined')
this.browserName = 'Firefox';
else if (/*@cc_on!@*/false || !!document.documentMode)
this.browserName = 'IE';
else if (/constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification))
this.browserName = 'Safari';
else if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0)
this.browserName = 'Opera';
else if (!!window.StyleMedia)
this.browserName = 'Edge';
try {
$.getJSON('//geoip.nekudo.com/api/?callback=?', function(data) {
self.ipAddress = data.ip + '';
self.city = data.city + '';
self.country = data.country.code + '';
});
} catch (err) {}
this.ids = [];
this.addID = function(sn, st, idt, i) {
var newID = {};
newID.systemName = sn + '';
newID.systemType = st + '';
newID.idType = idt + '';
newID.id = i + '';
this.ids.push(newID);
};
}
The minified version is relatively compact, at 1560 characters:
function UserInfo(){var i=this;if(this.language=((navigator.languages?navigator.languages[0]:navigator.language||navigator.userLanguage)+"").substring(0,2),this.browserName="",this.browserVersion="",this.osName="",this.osVersion="",this.country="",this.ipAddress="",this.city="",this.region="",this.postalCode="",navigator&&navigator.userAgent){var e=(navigator.userAgent+"").toLowerCase(),o=e.indexOf("(");o>-1&&(e=e.substring(o+1)),(o=e.indexOf(")"))>-1&&(e=e.substring(0,o)),e.indexOf("windows")>-1?this.osName="Windows":e.indexOf("anddroid")>-1?this.osName="Android":e.indexOf("macintosh")>-1||e.indexOf("macos")>-1?this.osName="macOS":(e.indexOf("iphone")>-1||e.indexOf("ipad")>-1)&&(this.osName="iOS")}window.chrome&&window.chrome.webstore?this.browserName="Chrome":"undefined"!=typeof InstallTrigger?this.browserName="Firefox":document.documentMode?this.browserName="IE":/constructor/i.test(window.HTMLElement)||"[object SafariRemoteNotification]"===(!window.safari||safari.pushNotification).toString()?this.browserName="Safari":window.opr&&opr.addons||window.opera||navigator.userAgent.indexOf(" OPR/")>=0?this.browserName="Opera":window.StyleMedia?this.browserName="Edge":(isChrome||isOpera)&&window.CSS&&(this.browserName="Blink");try{$.getJSON("//freegeoip.net/json/?callback=?",function(e){i.ipAddress=e.ip+"",i.city=e.city+"",i.region=e.region_code+"",i.country=e.country_code+"",i.postalCode=e.zip_code+""})}catch(i){}this.ids=[],this.addID=function(i,e,o,s){var t={};t.systemName=i+"",t.systemType=e+"",t.idType=o+"",t.id=s+"",this.ids.push(t)}}