How to Use Multiple Facebook Pixels on One Site

Can you use multiple Facebook pixels on one site? The short answer is: yes!

This was a frustrating problem! Facebook doesn’t provide any documentation about using more than one pixel on a single site. This is hard to believe, as I imagine many businesses work with multiple digital marketing vendors who provide Facebook ad services. From the looks of the many unanswered questions in Facebook’s help forum about this, it’s obvious many are frustrated along with me.

Doing a Google search for “facebook multiple pixels on one site” found results from Facebook’s help forums and StackOverflow, but none had a full discussion of the possible options and what works or doesn’t. That’s what I would like to provide here.

Discussion

I highly recommend you install the Facebook Pixel Helper. It helps diagnose problems and allows you to see what’s going on under the hood.

I had two important objectives for this project:

  1. Include multiple Facebook pixels on one website and be able to track activity, engagement, and conversions on that site to all of them.
  2. Ability to fire some events only to one specific pixel ID.

The first thing you might try is simply adding the two full Facebook Pixel code snippets to the site. Don’t do that! Only include one full snippet, then add additional fbq('init', '[your-pixel-id]') calls for each additional pixel ID you want to install. It would look something like this:

<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');
    fbq('init', '[first-pixel-id]');
    fbq('init', '[second-pixel-id]');
    fbq('track', 'PageView'); //tracks a PageView to both initialized pixels
</script>
<noscript>
    <img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=[first-pixel-id]&ev=PageView&noscript=1" />
    <img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=[second-pixel-id]&ev=PageView&noscript=1" />
</noscript>

If you do this, the first objective will be met, because each time you call fbq('init', '[your-pixel-id]'), any future calls like fbq('track', 'PageView') will send an event for each initialized pixel ID (see screenshot below). If that’s your only objective, you can stop here. You’ve found your solution!

A view of the Facebook Pixel Helper on a site with multiple pixels

But for me, the second objective was not met, as events would be sent with exactly the same data for each.

The company I work for provides a service for Facebook Dynamic Ads, so we have our own Product IDs in our Product Catalog that need to match the Product IDs on our clients’ websites. But our Product ID may not be the same as other companies’, so we need to be able to specify our own and send those along with only our pixel events.

For instance, let’s say you land on a client’s product page for a t-shirt, and that client works with two different digital marketing companies for Facebook Dynamic Ads. The first company identifies products by their own unique product ID (e.g. “tshirt_1022”). The second company identifies products by the UPC (e.g. “892185001003”). If both their pixels are initiated, the first company may include a call like this:

fbq('track', 'ViewContent', {
    content_type: 'product',
    content_ids: ['tshirt_1022']
});

The obvious problem is that the Facebook pixel will send the track event to both Pixel IDs, but only the first will match a product ID, because my company’s product ID is “892185001003”, not “tshirt_1022”. You will see something like this in the Pixel Helper:

The Facebook Pixel Helper can help you find mismatched product IDs and other similar problems.

Progress

We’ve now identified the problem, so how do we go about solving it?

After searching for hours and doing some testing on the Facebook pixel’s fbq object, I couldn’t find any way to send a pixel event to only one pixel. The ideal way to solve the problem would be the ability to specify a pixel ID when calling a track event. Something like this:

fbq('track', '[your-pixel-id]', 'ViewContent', { content_type: 'product', content_ids: ['892185001003'] });

It seems silly they don’t support that already.

The first part of my eventual solution came from the recognition that Facebook’s pixel code includes two methods to initiate your pixel and track events on a site: JavaScript and non-JavaScript. Facebook’s example pixel code looks like this:

<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');
fbq('init', 'FB_PIXEL_ID');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=FB_PIXEL_ID&ev=PageView&noscript=1" /></noscript>

Note the <img> tag in the <noscript> section. If the user doesn’t have JavaScript enabled, the browser will send the event data via an image request to Facebook. Using this method, you can pass a single pixel ID. Hazah! So what we need to do is dynamically create an <img> tag like we see in that example code.

Solution

In my Googling, I came across an answer on StackOverflow that employed this idea of dynamically creating an <img> tag to send the event data, so I used it as a foundation. Credit goes to the user Flavio Wuensche for the basis of my function below!

I’ll include my code, then we can discuss what it does:

(function (window, document) {
    if (window.myfbq) return;
    window.myfbq = (function () {
        if (arguments.length > 0) {
            var pixelId, trackType, contentObj;

            if (typeof arguments[0] == 'string') pixelId = arguments[0];
            if (typeof arguments[1] == 'string') trackType = arguments[1];
            if (typeof arguments[2] == 'object') contentObj = arguments[2];

            var params = [];
            if (typeof pixelId === 'string' && pixelId.replace(/\s+/gi, '') != '' &&
            typeof trackType === 'string' && trackType.replace(/\s+/gi, '')) {
                params.push('id=' + encodeURIComponent(pixelId));
                switch (trackType) {
                    case 'PageView':
                    case 'ViewContent':
                    case 'Search':
                    case 'AddToCart':
                    case 'InitiateCheckout':
                    case 'AddPaymentInfo':
                    case 'Lead':
                    case 'CompleteRegistration':
                    case 'Purchase':
                    case 'AddToWishlist':
                        params.push('ev=' + encodeURIComponent(trackType));
                        break;
                    default:
                        return;
                }

                params.push('dl=' + encodeURIComponent(document.location.href));
                if (document.referrer) params.push('rl=' + encodeURIComponent(document.referrer));
                params.push('if=false');
                params.push('ts=' + new Date().getTime());

                if (typeof contentObj == 'object') {
                    for (var u in contentObj) {
                        if (typeof contentObj[u] == 'object' && contentObj[u] instanceof Array) {
                            if (contentObj[u].length > 0) {
                                for (var y = 0; y < contentObj[u].length; y++) { contentObj[u][y] = (contentObj[u][y] + '').replace(/^\s+|\s+$/gi, '').replace(/\s+/gi, ' ').replace(/,/gi, '§'); }
                                params.push('cd[' + u + ']=' + encodeURIComponent(contentObj[u].join(',').replace(/^/gi, '[\'').replace(/$/gi, '\']').replace(/,/gi, '\',\'').replace(/§/gi, '\,')));
                            }
                        }
                        else if (typeof contentObj[u] == 'string')
                            params.push('cd[' + u + ']=' + encodeURIComponent(contentObj[u]));
                    }
                }

                params.push('v=' + encodeURIComponent('2.7.19'));

                var imgId = new Date().getTime();
                var img = document.createElement('img');
                img.id = 'fb_' + imgId, img.src = 'https://www.facebook.com/tr/?' + params.join('&'), img.width = 1, img.height = 1, img.style = 'display:none;';
                document.body.appendChild(img);
                window.setTimeout(function () { var t = document.getElementById('fb_' + imgId); t.parentElement.removeChild(t); }, 1000);
            }
        }
    });
})(window, document);

This attaches a new function called myfbq to the global window object, so you can use it from anywhere in your JavaScript code. Note that this function has no association with and makes no calls to Facebook’s fbq object.

Near the top of the function, there are some checks to make sure there is a pixel ID and event type specified. If those exist, and the event type is valid, it begins building an array of parameters that need to be appended to the image request URL. Flavio included code to build the custom parameters, if you need to define those.

Lastly, the function creates an image element, defines its attributes, then appends it to the body. After one second, the image element will be removed from the page (that’s not necessary, but just a matter of housekeeping).

Usage

The function accepts 2-3 arguments, the first of which is your pixel ID:

myfbq("[your-pixel-id]", "PageView");
myfbq("[your-pixel-id]", "ViewContent");
myfbq("[your-pixel-id]", "ViewContent", { content_type: "product", content_ids: ['892185001003'] });

Wrapping It Up

That’s it! When you browse to your site, open up the Facebook Pixel Helper and confirm that the pixel event is being sent to Facebook with the correct data.

One final note is that if you use this function, you won’t need to include your Facebook’s pixel code snippet on your site. If you call fbq('init', '[your-pixel-id]') on the site, remember that all events tracked will be also be sent for your pixel ID, and that’s what we want to avoid. So just include the myfbq function and make calls to it with your pixel ID.

Your Turn!

Have you run into this problem before? What solution did you come to? I’d love to hear your questions or experiences, so let’s discuss in the comments below!

  • Christopher Araya Hidalgo

    Hi! Really good post. You have a solution for custom event??
    Please email me to christopher.araya@hulilabs.com. I need to ask you a few more question

    • johndubya

      Christopher,

      Thanks for the comment! If you don’t mind, I like to keep conversation here in the comments, so others can be informed as well, in case we touch on anything others may be dealing with. What can I help with?

      (if your issue is sensitive or something, feel free to reach out through my contact form!)

  • Prabhakar G

    Hi! I am really confused a bit with facebook help forum, by not providing any information about multiple facebook pixels in a single page.

    So please help me. My Requirement: I need to have two fb pixels for my website, so that i can have one pixel as my backup.

    Help me out, please.. iam not a Techie.. but learning things from google, to solve my problems..

    • johndubya

      Prabhakar,

      Yes, it can be quite confusing! I found the Facebook Help Forum to be very unhelpful on this topic.

      As far as your requirement, the code snippet near the top of my post is likely what you need. Something like this:


      !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');
      fbq('init', '[first-pixel-id]');
      fbq('init', '[second-pixel-id]');
      fbq('track', 'PageView'); //tracks a PageView to both initialized pixels

      Just include multiple fbq(‘init’, ‘[your-pixel-id]’) calls, and that will initialize any additional pixels you need to track to. Hope that helps!