最近接到一个需求,需要精准的统计通过邀请活动下载APP及注册的转化率。

单统计邀请活动点击下载的用户数这个比较容易,统计下载按钮就可以了,但是要精准的统计出进入邀请活动到下载app及注册的转化率,这个就需要邀请活动页面跟APP端都要改动才能实现,怎么实现呢,经过多方讨论,大家决定在活动页面点击下载时上传关键信息到服务器,然后APP注册的时候也获取同样类型的信息,这样后台就可以统计出转化率了。

JS能获取到系统版本及分辨率等,接口那边可以获取到公网IP,仅有这些信息能粗略的统计出一个转化率,为了提高数据精准度,我们还需要更多的有效信息,但是javascript由于限制,无法获取更多信息。查询资料了解到有一个webRTC,我们可以通过这个来获取客户端局域网IP,加入这个信息,数据的准确度进一步提高。

DEMO:

你的IP:

代码:

//get the IP addresses associated with an account
function getIPs(callback) {
    var ip_dups = {};
    //compatibility for firefox and chrome
    var RTCPeerConnection = window.RTCPeerConnection ||
        window.mozRTCPeerConnection ||
        window.webkitRTCPeerConnection;
    var useWebKit = !!window.webkitRTCPeerConnection;
    //bypass naive webrtc blocking using an iframe
    if (!RTCPeerConnection) {
        //NOTE: you need to have an iframe in the page right above the script tag
        //
        //<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
        //<script>...getIPs called in here...
        //
        var win = iframe.contentWindow;
        RTCPeerConnection = win.RTCPeerConnection ||
            win.mozRTCPeerConnection ||
            win.webkitRTCPeerConnection;
        useWebKit = !!win.webkitRTCPeerConnection;
    }
    //minimal requirements for data connection
    var mediaConstraints = {
        optional: [{ RtpDataChannels: true }]
    };
    var servers = { iceServers: [{ urls: "stun:stun.services.mozilla.com" }] };
    //construct a new RTCPeerConnection
    var pc = new RTCPeerConnection(servers, mediaConstraints);
    function handleCandidate(candidate) {
        //match just the IP address
        var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
        var ip_addr = ip_regex.exec(candidate)[1];
        //remove duplicates
        if (ip_dups[ip_addr] === undefined)
            callback(ip_addr);
        ip_dups[ip_addr] = true;
    }
    //listen for candidate events
    pc.onicecandidate = function(ice) {
        //skip non-candidate events
        if (ice.candidate)
            handleCandidate(ice.candidate.candidate);
    };
    //create a bogus data channel
    pc.createDataChannel("");
    //create an offer sdp
    pc.createOffer(function(result) {
        //trigger the stun server request
        pc.setLocalDescription(result, function() {}, function() {});
    }, function() {});
    //wait for a while to let everything done
    setTimeout(function() {
        //read candidate info from local description
        var lines = pc.localDescription.sdp.split('\n');
        lines.forEach(function(line) {
            if (line.indexOf('c=IN') === 0)
                handleCandidate(line);
        });
    }, 1000);
}