Wait for Facebook Pixel Load

送分小仙女□ 提交于 2019-12-07 03:25:17

问题


I want to detect in my JavaScript code that the load of a Facebook pixel has been completed. Is this possible?

For reference here is the Facebook Pixel Tracking code:

<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','//connect.facebook.net/en_US/fbevents.js');
// Insert Your Facebook Pixel ID below. 
fbq('init', 'FB_PIXEL_ID');
fbq('track', 'PageView');
</script>
<!-- Insert Your Facebook Pixel ID below. --> 
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=FB_PIXEL_ID&amp;ev=PageView&amp;noscript=1"
/></noscript>

Breaking it down, it seems that fbq('init', ...) causes a script tag to be added with the async attribute set and src set to //connect.facebook.net/en_US/fbevents.js.

Subsequently the call to fbq('track', ...) somehow causes an HTTP GET to an image via one redirect.

How to detect that all the steps are complete, especially that the final image load is complete?


回答1:


I took a stab at this. Given a callback function named myCallback and your private id named myId, use this code:

  (function wait() {
    // check for the generic script
    // easiest check to prevent race condition
    if (fbq.version > '2.0') {
      // now check for the custom script
      // `fbq.on` is now ready (`fbq.once` would be better but has a bug)
     fbq.on('configLoaded', function (name) {
        if (name === myId) {
          myCallback();
        }
      });
    } else {
      setTimeout(wait, 10);
    }
  })();

myCallback will be called once everything is ready. This is accurate as of fbq.version="2.7.17";

Reference https://github.com/poteto/ember-metrics/pull/151




回答2:


You can use below code if you want to trigger specific FB event after successful completion of FB pixel loading, here is the code:

 <script>
        function drop_fb_pixel() {
            try {
                //Drop FB Pixel
                fbq('track', 'ViewContent', {
                    content_ids: ['12'],
                    content_type: 'product' 
                });
            }
            catch (err) {
                setTimeout(function () { drop_fb_pixel(); }, 3000);

            }
        }
        $(document).ready(function () {
            drop_fb_pixel();
        });


    </script>

The logic is pretty simple, after document load this script will try to trigger FB event, if got error then it will try to trigger event again after 3 sec, you can customize the time of event trigger as per your own application logic




回答3:


Since OP @user2297550 said his ultimate goal is to redirect a user after an event fires, I'll explain how that can be done (without timeouts or intervals). Some previous answers try to detect when the Facebook pixel <script> is done loading, but that's not the same as determining when an actual event is done firing. Presumably, OP want's to know when the PageView event is complete. This solution is not amazing for every use case, but it's pretty simple if we don't have much else happening on the page.

In order to ping their servers and track events, Facebook's code creates a new Image() and sets its src attribute to something like https://www.facebook.com/tr/?id=XXXXXX&ev=PageView&{more parameters}. I discovered this by examining the tracking library and finding this sendGET function:

this.sendGET = function(b, c, d) {
    b.replaceEntry("rqm", "GET");
    var f = b.toQueryString();
    f = i(c, d) + "?" + f;
    if (f.length < 2048) {
        var g = new Image();
        if (d != null) {
            var h = a.getShouldProxy();
            g.onerror = function() {
                a.setShouldProxy(!0), h || e.sendGET(b, c, d)
            }
        }
        g.src = f;
        return !0
    }
    return !1
};

We can hook into that image load by polyfilling a default Image.onload callback with our redirect code. The result is something like this, which could be placed immediately above the normal Facebook pixel code in your header:

OriginalImage = Image;
Image = function(){
  let oi = new OriginalImage();
  oi.onload = function() {
    // if the image that loaded was indeed a Facebook pixel
    // for a "PageView" event, redirect
    if( this.src.indexOf( 'facebook.com/tr/?id=XXXXXX&ev=PageView' ) != -1 )
      window.location = 'https://example.com/redirect-here';
  };
  return oi;
};

So a full "paint the user and redirect" page could look about like this:

<html>
<head>
<!-- Facebook Pixel Code -->
<script>
  OriginalImage = Image;
  Image = function(){
    let oi = new OriginalImage();
    oi.onload = function() {
      // if the image that loaded was indeed a Facebook pixel
      // for a "PageView" event, redirect
      if( this.src.indexOf( 'facebook.com/tr/?id=XXXXXX&ev=PageView' ) != -1 )
        window.location = 'https://example.com/redirect-here';
    };
    return oi;
  };

  !function(f,b,e,v,n,t,s)
  {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
  n.callMethod.apply(n,arguments):n.queue.push(arguments)};
  if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
  n.queue=[];t=b.createElement(e);t.async=!0;
  t.src=v;s=b.getElementsByTagName(e)[0];
  s.parentNode.insertBefore(t,s)}(window, document,'script',
  'https://connect.facebook.net/en_US/fbevents.js');
  fbq('init', 'XXXXXX');
  fbq('track', 'PageView');
</script>
<noscript>
  <img height="1" width="1" style="display:none" 
       src="https://www.facebook.com/tr?id=XXXXXX&ev=PageView&noscript=1"/>
</noscript>
<!-- End Facebook Pixel Code -->
</head>
<body></body>
</html>

Of course, you could skip the Javascript and literally just load the image from that <noscript> block and add an 'onload' attribute, like so:

<html>
<head>
<!-- Facebook Pixel Code -->
<img height="1" width="1" style="display:none" 
       src="https://www.facebook.com/tr?id=XXXXXX&ev=PageView&noscript=1"
       onload="window.location = 'https://example.com/redirect-here';"/>
<!-- End Facebook Pixel Code -->
</head>
<body></body>
</html>

But I would guess that plain image tracking degrades Facebook's ability to identify the user.

This strategy may work for more generic use cases where you want to detect when an arbitrary event is done being sent to Facebook. But it may be unwise to polyfill the onload callback for every single image on a normal page. Also know that Facebook could change their code at any time, breaking this.




回答4:


The answer of @love-chopra is sort of alright, however I think to use the setTimeout() with 3s delay is not the best solution when we are talking about a webpage. From my POV the solution could be the setInterval() to check it constantly until the fbevents.js not loaded.

  var fbLoaded = false;
  var tryFB = null;

  function drop_fb_pixel() {
    fbLoaded = true;
    try {
      fbq('track', 'ViewContent', {
        content_ids: ['12'],
        content_type: 'product' 
      });
    } catch (err) {
      fbLoaded = false;
    }

    if (fbLoaded) {
      clearInterval(tryFB);
    }
  }

  tryFB = setInterval(function () { 
    drop_fb_pixel();
  }, 100);



回答5:


<script>
  $(document).ready(function () {

    function fbqcheck() {
      if(typeof fbq === 'undefined') {
        setTimeout(fbqcheck, 5);
      } else {
        alert('Facebook pixel loaded');
      }
    }

    fbqcheck();

  });
</script>



回答6:


I know this is an old post, but how about loading in Facebook Pixel Helper as a Chrome Extension? This tells you immediately if there is a Pixel loading on your website.




来源:https://stackoverflow.com/questions/41755216/wait-for-facebook-pixel-load

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!