Reputation: 1000
I have run into a bit a frustrating problem with duplicating the "PageView" event for my pixel in my Nuxt.js (Vue) project with my Facebook Conversion API.
I initially stripped out this packages code, so that I could modify to include a eventID for every "PageView" event: https://github.com/WilliamDASILVA/nuxt-facebook-pixel-module#readme
My "PageView" event workflow is like this:
Initial load works fine:
However, subsequent calls after a route change does not work. Both the server level event and the browser level event are being tracked, but not duplicated.
First thing I noticed was there was no eventID being set for the browser call. I spent hours ensuring that the correct function was being called to the facebook pixel in the browser with the eventID, it is.
I found https://gist.github.com/sunderls/dfd5293a8b8f24a4ef37189a1d8c1b46 online, and began to try to figure out what was happening. It looks like an event handler is automatically added to the pixel when the replacestate/pushstate of the browsers history is called. This would explain why no eventID is being passed along, it's firing automatically.
Looking through Facebooks documentation I found that I could set:
fbq.disablePushState = true
Which would then stop the pixel from adding those event listeners. However, when I add this line of code above, I do not receive any subsequent "PageView" events after the initial page load, only server events are coming through.
Here is my plugin source code:
import { Minimatch } from "minimatch"
import axios from "axios"
import cookie from "js-cookie"
/**
* @class Fb
*/
class Fb {
constructor (fbq, options, eventUrl) {
this.options = options
this.fbq = fbq
this.eventUrl = eventUrl
this.isEnabled = !options.disabled
}
setPixelId (pixelId) {
this.options.pixelId = pixelId
this.init()
}
/**
* @method enable
*/
enable () {
this.isEnabled = true
this.init()
this.track()
}
/**
* @method disable
*/
disable () {
this.isEnabled = false
}
/**
* @method init
*/
init () {
this.query('init', this.options.pixelId)
}
/**
* @method track
*/
async track (event = null, parameters = null, eventId = null) {
if (!event) {
event = this.options.track
}
if (this.eventUrl && !eventId) {
if (cookie.get("auth._token.cookie")) {
axios.defaults.headers.common["Authorization"] = cookie.get("auth._token.cookie");
}
try {
let url = this.eventUrl
const queryString = []
if (event === "PageView") {
queryString.push("url=" + window.location.href.split('?')[0])
queryString.push("view=true")
}
if (cookie.get("_fbp")) {
queryString.push(`_fbp=${cookie.get("_fbp")}`)
}
if (cookie.get("_fbc")) {
queryString.push(`_fbc=${cookie.get("_fbc")}`)
}
if (queryString.length !== 0) {
url += "?" + queryString.join("&")
}
const {data: {data}} = await axios.get(url)
eventId = data.event_id
} catch (err) {
console.error(err)
}
}
this.query('track', event, parameters, eventId)
}
/**
* @method query
* @param {string} cmd
* @param {object} option
* @param {object} parameters
*/
query (cmd, option, parameters = null, eventId = null) {
if (this.options.debug) log('Command:', cmd, 'Option:', option, 'Additional parameters:', parameters, 'Event Id:', eventId)
if (!this.isEnabled) return
if (!parameters && !eventId) {
this.fbq(cmd, option)
} else if (parameters && !eventId) {
this.fbq(cmd, option, parameters)
} else {
this.fbq(cmd, option, {}, {eventID: eventId})
}
}
}
function getMatchingPixel (options, path) {
return options.pixels.find(pixel => {
const routeIndex = pixel.routes.findIndex(route => {
const minimatch = new Minimatch(route)
return minimatch.match(path)
})
return routeIndex !== -1
})
}
function log (...messages) {
console.info.apply(this, ['[nuxt-facebook-pixel-module]', ...messages])
}
export default (ctx, inject) => {
let _fbq
const parsedOptions = <%= JSON.stringify(options) %>
const isDev = parsedOptions.dev && !parsedOptions.debug
if (isDev) log('You are running in development mode. Set "debug: true" in your nuxt.config.js if you would like to trigger tracking events in local.')
const { path } = ctx.route
const matchingPixel = getMatchingPixel(parsedOptions, path)
const pixelOptions = Object.assign({}, matchingPixel || parsedOptions)
/* eslint-disable */
if (typeof window !== 'undefined') {
((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 = pixelOptions.version;
n.queue = [];
t = b.createElement(e);
t.async = true;
t.defer = true;
t.src = v;
s = b.getElementsByTagName('body')[0];
s.parentNode.appendChild(t, s);
_fbq = fbq;
if (!isDev && !pixelOptions.disabled) {
if (pixelOptions.manualMode) {
fbq('set', 'autoConfig', false, pixelOptions.pixelId)
}
// fbq.disablePushState = true
fbq('init', pixelOptions.pixelId)
// fbq('track', pixelOptions.track)
}
})(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
}
/* eslint-enable */
const instance = new Fb(_fbq, pixelOptions, parsedOptions.eventUrl)
if (ctx.app && ctx.app.router) {
const router = ctx.app.router
router.afterEach(({ path }) => {
/**
* Change the current pixelId according to the route.
*/
const matchingPixel = getMatchingPixel(parsedOptions, path)
const pixelOptions = Object.assign({}, matchingPixel || parsedOptions)
if (pixelOptions.pixelId !== instance.options.pixelId) {
instance.setPixelId(pixelOptions.pixelId)
}
/**
* Automatically track PageView
*/
if (parsedOptions.autoPageView) {
instance.track('PageView')
}
})
}
/* eslint-enable */
ctx.$fb = instance
inject('fb', instance)
}
All settings are correctly set for the plugin to work. I am not using multiple Facebook Pixels.
I would greatly appreciate help in figuring this out.
Upvotes: 2
Views: 3901
Reputation: 1000
I got it working by setting:
fbq.disablePushState = true
fbq.allowDuplicatePageViews = true
Looking at the prettified Pixel code from: https://gist.github.com/sunderls/dfd5293a8b8f24a4ef37189a1d8c1b46
I found that within the track function there is this:
if (isPageview && wa.allowDuplicatePageViews === false && ca[methodCall.id] === true) continue;
So for some reason, allowing duplicate page views worked.
Upvotes: 5