07
2014
11

Hybird APP统计前后端实现原理(Nodejs+JavaScript)

网站统计用来统计网站及网页的浏览情况,以及转换率等。一般情况下第三方统计都可以满足需求,GA,百度统计,站长统计等等,都是非常好的统计工具。手机APP也是有很多,但对于Hybird APP这个畸形的APP品种而言要统计到各个点确实比较麻烦,考虑的点比较多,具体不讨论,在路上的人都知道。

其实本文重点是讨论一下统计工具前后端实现的原理等,下面三各点都很重要,本文只记录抓取问题。


抓取数据

后端Nodejs主要分析User-Agent数据,利用开源模块ua-parser。可以得到客户端浏览器版本,设备等

npm install ua-parser

前端利用JavaScript获取一些基本信息,可从下面代码中看到。然后通过Ajax传输,最简单的方式通过一张1x1的图片传输,这样更小消耗,无缝跨域。


分析数据

分析数据是整个工具能够收获成效的关键,需要什么,展示什么,图表控件,数据整理等,一系列,需求不同展示不同,时间不同精细读不同。考验技术,考验体力。这里不本文重点


维护数据

这是工具长远发占的难点,数据库选型重要。不是本文重要。


如何抓取页面数据?请看代码,代码不是很完整,但可以做抛砖引玉。

        <script type="text/javascript" src="http://localhost:3000/analysis/track.js"></script>
        <script type="text/javascript">
            wa.init('xxxx');
            wa.send('pageview', '首页标题', '/index');
        </script>


前端JavaScript代码

var wa = {};
(function(win, doc){
	var _xhr = new XMLHttpRequest();
	var _cid = '';
	var _tid = '';
	var _uid = '';
	var _oid = '';
	var sendXhr = function(data){
		var query = '';

		for(var key in data){
			query += key + '=' + data[key] + '&';
		}

		_xhr.open("GET", 'http://localhost:3000/api/analysis/public?'+query, true);
		_xhr.onreadystatechange = function(){}
  		_xhr.send(data);
	};

	var getGuid = function () {
	    function S4() {
	      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
	    }

	    function NewGuid() {
	      return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
	    }

	    var guid = window.localStorage.GUID || '';

	    if (!guid) {
	      guid = NewGuid();
	    }

	    return guid;
	};

	var localstorage = {
		itemKey: 'WINGON_TRACKING',
		getItem: function(){
			return JSON.parse(win.localStorage.getItem(this.itemKey));
		},
		get: function(key){
			var item = this.getItem() || {};
			return item[key];
		},
		set: function(key, value){
			var item = this.getItem() || {};
			item[key] = value;
			win.localStorage.setItem(this.itemKey, JSON.stringify(item));
		}
	};

	var getClientInfo = function(){
		return {
			_tid: _tid,
			_cid: _cid,
			_uid: _uid,
			_oid: _oid,
			_t: 'pageview',

			_r: doc.referrer,
			_dm: doc.domain,
			_url: doc.host,
			_dt: doc.title,
			_sr: win.screen.width + 'x' + win.screen.height,
			_vp: win.screen.availWidth + 'x' + win.screen.availHeight,
			_cd: win.screen.colorDepth,
			_pd: win.screen.pixelDepth,
			_lang: navigator.language
		}
	};

	var setCid = function(){
		var cid = localstorage.set('_cid');

		if(!cid){
			cid = getGuid();
			localstorage.set('_cid', cid);
		}
		_cid = cid;
	};

	var setOid = function(){
		var oid = getGuid();
		
		localstorage.set('_oid', oid);
		_oid = oid;
	};

	wa.init = function(tid){
		_tid = tid;
		setCid();
		setOid();
	};

	wa.setUid = function(uid){
		_uid = uid;
	};

	wa.send = function(type, title, url){
		var info = getClientInfo();
		if(arguments.length > 0){
			info._t = 'pageview';
			info._dt = title;
			info._url = url;
		}
		sendXhr(info);
	};
}(window, document));


后端Nodejs代码

var uap = require('ua-parser');

module.exports.setTrack = function (req, res) {
    var ip = req.headers['x-forwarded-for'] || 
             req.connection.remoteAddress || 
             req.socket.remoteAddress ||
             req.connection.socket.remoteAddress,
        parser = uap.parse(req.headers['user-agent'])||{},
        query = req.query,
        datas;

    datas = {
        ip: ip || '',

        tid: query._tid || '',
        cid: query._cid || '',
        uid: query._uid || '',
        oid: query._oid || '',
        type: query._t || '',

        referrer: query._r || '',
        domain: query._dm || '',
        url: query._url || '',
        title: query._dt || '',
        screen: query._sr || '',
        viewPort: query._vp || '',
        colorDepth: query._cd || '',
        pixelDepth: query._pd || '',
        language: query._lang || '',
     
        browser: parser.ua.toString() || '',
        browserFamily: parser.ua.family || '',   
        browserVersion: parser.ua.toVersionString() || '',
        browserMajorVersion: parser.ua.major || '',

        os: parser.os.toString() || '',
        osFamily: parser.os.family || '',
        osVersion: parser.os.toVersionString() || '',
        osMajorVersion: parser.os.major || '',

        device: parser.device.family || '',

        source: parser.string || '',

        ctime: new Date()
    };

    console.log(JSON.stringify(datas));
};


« 上一篇下一篇 »

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。