我正在尝试在一个基于Backbone.js和require.js的单页面站点中使用Mixpanel事件跟踪。
看看Mixpanel提供的剪切和粘贴到常规网页的snippet,我可以看出他们已经推出了自己的异步加载机制,从独立的资源中拉入实际的Mixpanel API,做一些额外的工作来设置'people‘和其他属性,最后通过全局命名空间公开'mixpanel’对象。
我尝试为代码片段或独立API添加填充配置项,但两者都不能很好地工作。
通过我的研究,我发现了一个project on github,它做的正是我想要的,但是它已经有几年的历史了,并且是基于“旧的”mixpanel API的。在新版本中,Mixpanel对代码片段和API做了一些我无法理解的改动。
我希望有人能理解Mixpanel代码片段和/或AMD和require.js,并能帮我解决这个问题。
发布于 2013-09-24 03:05:49
有两件有趣的事情让这个问题变得奇怪:
因此,我们有两个选择:
选项1.放弃异步支持,并等待库被加载-
此方法的工作方式是创建一个预初始化模块来设置mixpanel库所需的window.mixpanel deps,然后将其指定为库本身的依赖项。然后,请求"mixpanel“将会阻塞,直到lib完全加载。
<html>
<head>
<title>Mixpanel AMD Example - Sync</title>
<script type="text/javascript" src="http://requirejs.org/docs/release/2.1.8/minified/require.js"></script>
<script type="text/javascript">
requirejs.config({
paths : { 'mixpanel': "//cdn.mxpnl.com/libs/mixpanel-2.2.min" },
shim: {
'mixpanel': {
deps: ['mixpanel-preinit'],
exports: 'mixpanel'
}
}
});
define("mixpanel-preinit", function(require) {
// this is a stripped down version of the mixpanel snippet that removes the loading of the lib via external script tag and the stubs for queuing calls
var b=window.mixpanel=window.mixpanel||[];var i,g;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";b._i.push([a,e,d])};b.__SV=1.2;
b.init("YOUR TOKEN");
});
</script>
</head>
<body>
<script type="text/javascript">
require(['mixpanel'], function(mixpanel) {
mixpanel.track("my event", {prop1: "val1"});
console.log(mixpanel.get_distinct_id());
});
</script>
</body>
</html>
选项2.提供一个“已加载”回调来更新模块的属性。- -
如果你真的想要异步支持,你需要在加载mixpanel库之后更新存根的方法。我不推荐这样做,因为(还有其他原因)它会在复制后生成window.mixpanel !==混合面板。这也意味着您必须防止在同步调用中出现竞争条件,比如get_distinct_id()。如果lib还没有装入,它将是未定义的。注意:我建议,如果你必须有异步支持,你应该通过window.mixpanel调用,而不是所有这些疯狂的调用。
<html>
<head>
<title>Mixpanel AMD Example - Async</title>
<script type="text/javascript" src="http://requirejs.org/docs/release/2.1.8/minified/require.js"></script>
<script type="text/javascript">
requirejs.config({
paths : { 'mixpanel-lib': "//cdn.mxpnl.com/libs/mixpanel-2.2.min" }
});
define("mixpanel", function(require) {
var b = window.mixpanel || [];
if (!b.__SV) { var i, g; window.mixpanel = b; b._i = []; b.init = function (a, e, d) { function f(b, h) { var a = h.split("."); 2 == a.length && (b = b[a[0]], h = a[1]); b[h] = function () { b.push([h].concat(Array.prototype.slice.call(arguments, 0))) } } var c = b; "undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel"; c.people = c.people || []; c.toString = function (b) { var a = "mixpanel"; "mixpanel" !== d && (a += "." + d); b || (a += " (stub)"); return a }; c.people.toString = function () { return c.toString(1) + ".people (stub)" }; i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" "); for (g = 0; g < i.length; g++) f(c, i[g]); b._i.push([a, e, d]) }; b.__SV = 1.2 }
// go ahead and start loading the mixpanel-lib
require(['mixpanel-lib']);
b.init("YOUR TOKEN", {loaded: function() {
// now that we know mixpanel is loaded, copy the prop references to our module def
for(var prop in window.mixpanel) {
b[prop] = window.mixpanel[prop];
}
}});
return b;
});
</script>
</head>
<body>
<script type="text/javascript">
require(['mixpanel'], function(mixpanel) {
mixpanel.track("my event", {prop1: "val1"});
console.log(mixpanel.get_distinct_id()); // probably undefined
});
</script>
</body>
</html>
发布于 2013-07-29 15:18:26
以下解决方案适用于mixpanel api 2.2
使用以下填充程序添加mixpanel -
path : {
'mixpanel' : '//cdn.mxpnl.com/libs/mixpanel-2.2.min'
}
shim : {
'mixpanel' : {
exports : 'mixpanel'
},
}
并使用以下要求模块,而不是mixpanel给出的代码片段-
define('mixpanel-snippet', [], function(){
var b = window.mixpanel || [];
if (!b.__SV) {
var i, g;
window.mixpanel = b;
b._i = [];
b.init = function (a, e, d) {
function f(b, h) {
var a = h.split(".");
2 == a.length && (b = b[a[0]], h = a[1]);
b[h] = function () {
b.push([h].concat(Array.prototype.slice.call(arguments, 0)))
}
}
var c = b;
"undefined" !==
typeof d ? c = b[d] = [] : d = "mixpanel";
c.people = c.people || [];
c.toString = function (b) {
var a = "mixpanel";
"mixpanel" !== d && (a += "." + d);
b || (a += " (stub)");
return a
};
c.people.toString = function () {
return c.toString(1) + ".people (stub)"
};
i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
for (g = 0; g < i.length; g++)
f(c, i[g]);
b._i.push([a, e, d])
};
b.__SV = 1.2
}
b.init("YOUR TOKEN");
require(['mixpanel'], function(mixpanel){});
return b;
});
我只需从mixpanel中获取代码片段,移除async mixpanel加载,并将其包装在requirejs模块定义中。
更改模块底部的"YOUR TOKEN“。
使用一个请求调用的示例--
require([
'mixpanel-snippet',
], function (mixpanel) {
mixpanel.track("Landing Page with AMD SHIM");
});
编辑:第二个是稍加修改后的正确答案。mixpanel脚本的工作方式是,它需要在代码片段中的init调用在实际的mixpanel加载之前发生。诀窍是在初始化调用后需要mixpanel。我编辑了第二个答案,并删除了第一个答案和here's the gist
编辑:对@johanandren Requirejs评论的回答遵循AMD原则,脚本加载的顺序并不固定。如果你需要在使用mixpanel-snippet之前加载mixpanel,可以使用下面的hack。
//at the end of mixpanel-snippet code mentioned above force the script to block until mixpanel is loaded
b.init("YOUR TOKEN");
var wait = true;
require(['mixpanel'], function(mixpanel){wait = false;});
while(wait){}
return b;
**它违反了AMD的异步加载功能,强制脚本阻止,即使在vanila mixpanel代码段中,加载也是异步的,无法保证初始api调用的可用性
发布于 2013-08-01 23:49:27
这对我很有效。将mixpanel片段放在名为mixpanel-snippet.js的js/lib目录中。
在您的app.js中,将以下填充程序添加到require.config:
'mixpanel-snippet': {
exports: 'mixpanel'
}
require(['jquery', 'backbone', 'app/router', 'mixpanel'], function ($, Backbone, Router) {
var router = new Router();
Backbone.history.start();
mixpanel.init(key);
mixpanel.track("Landed on Start up Page");
});
我可以提供一个完整的app.js示例,如果它会有所帮助,但这应该是你的入门。如果有效,请让我知道。
https://stackoverflow.com/questions/17729068
复制相似问题