7

Backbone.js と require.js に基づく単一ページ サイトで Mixpanel イベント トラッキングを利用しようとしています。

Mixpanel が通常の Web ページにカット アンド ペーストするために提供するスニペットを見ると、スタンドアロン リソースから実際のMixpanel APIを取得する独自の非同期ローディング メカニズムを開発したことがわかります。 ' およびその他の属性を追加し、最後にグローバル名前空間を介して 'mixpanel' オブジェクトを公開します。

スニペットまたはスタンドアロン API のいずれかの shim 構成エントリを追加しようとしましたが、どちらもうまく機能しません。

私の研究を通じて、私が望んでいることを正確に行うプロジェクトを githubで見つけましたが、それは数年前のものであり、「古い」 mixpanel API に基づいています。新しいバージョンでは、Mixpanel はスニペットと API にいくつかの重要な変更を加えましたが、私には理解できません。

誰かが Mixpanel スニペットおよび/または AMD と require.js を理解し、これを順を追って教えてくれることを願っています。

4

4 に答える 4

13

これを解決するのが奇妙な問題になる 2 つの面白いことがあります。

  1. mixpanel ライブラリでは、ロードする前に window.mixpanel を定義する必要があります。
  2. mixpanel lib は、init プロセスの一部として window.mixpanel を再定義します。

すぐに使用できる mixpanel スニペットは、lib がロードされるまで get_distinct_id (および定義上、同期であるすべての呼び出し) をサポートしませんが、mixpanel lib をロードする前に他のメソッド (track など) をスタブアウトします。待ち行列。したがって、次の 2 つのオプションがあります。

オプション 1. 非同期サポートをドロップし、lib がロードされるまで待ちます - Gist

この方法は、mixpanel lib に必要な window.mixpanel deps をセットアップする pre-init モジュールを作成し、それを lib 自体への依存関係として指定することによって機能します。次に、「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 !== mixpanel になるため、これはお勧めしません。これは、get_distinct_id() などの同期呼び出しで競合状態から保護する必要があることも意味します。ライブラリがまだロードされていない場合は、未定義になります。注: 非同期サポートが必要な場合は、この狂気の代わりに 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-09-23T19:05:49.187 に答える
5

次のソリューションは mixpanel api 2.2 で機能します

次のシムで mixpanel を追加します -

path : {
    'mixpanel' : '//cdn.mxpnl.com/libs/mixpanel-2.2.min'
}

shim : {
    'mixpanel' : {
        exports : 'mixpanel'
    },
}

mixpanelによって提供されたスニペットの代わりに、次のrequirejsモジュールを使用します-

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 からスニペットを取り出し、非同期の mixpanel ロードを削除して、requirejs モジュール定義でラップしました。

モジュールの下部にある「YOUR TOKEN」を変更します。

require 呼び出しでの使用例 -

require([
    'mixpanel-snippet',
], function (mixpanel) {
        mixpanel.track("Landing Page with AMD SHIM");
});

編集: 2 つ目は、少し修正した後の正しい答えです。mixpanel スクリプトが機能する方法は、実際の mixpanel ロードの前に、スニペットで init 呼び出しが発生する必要があることです。秘訣は、init 呼び出しの後に mixpanel を要求することです。2 番目の回答を編集し、最初の回答を削除しました。要点は次のとおりです。

編集: @johanandren からのコメントへの回答 Requirejs は AMD の原則に従い、スクリプトが読み込まれる順序は固定されていません。mixpanel-snippet を使用する前に mixpanel をロードする必要がある場合は、次のハックを使用できます。

//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-07-29T07:18:25.787 に答える
0

mixpanel の 2.7.x リリースの時点で、requirejs と互換性のある複数の AMD/UMD バージョンがサポートされるようになりました

requirejs(['./mixpanel.amd'], function(mixpanel) {

    mixpanel.init("FAKE_TOKEN", {
        debug: true,
        loaded: function() {
            mixpanel.track('loaded() callback works but is unnecessary');
            alert("Mixpanel loaded successfully via RequireJS/AMD");
        }
    });

    mixpanel.track('Tracking after mixpanel.init');

});
于 2016-05-06T19:41:06.387 に答える
0

これは私にとってはうまくいきました。mixpanel スニペットを mixpanel-snippet.js という名前の js/lib ディレクトリに配置します。

app.js で、次の shim を require.config に追加します。

'mixpanel-snippet': {
  exports: 'mixpanel'
}

require 関数で、必要な配列に「mixpanel-snippet」を追加し、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 の例を提供できますが、これで開始する必要があります。これがうまくいくかどうか教えてください。

于 2013-08-01T15:49:26.617 に答える