One reaction to last weeks article on the ACDL was from @AnalyticsNinja, and it was about the 500ms wait time I mentioned:
500ms setTimeout() in click handlers…. Isn’t navigator.sendBeacon sufficient?
— Analytics Sith (@AnalyticsNinja) October 23, 2020
So very right he is, and the only excuse I have is that … no, I don’t have an excuse. I simply didn’t think of that. Typical case of “but I always did it like that!”
That is bad and it must stop.
What is this about?
For Analytics, we track when pages load, and we track when people do things. “Do things” includes clicking, and sometimes the thing clicked is a link, meaning the browser’s natural reaction is to go and load some other page.
For us in Analytics, that posed a slight problem: we wanted the tracking call to actually happen, but the browser would simply dump the current page as quickly as possible.
Our fix for that, in the past, was to introduce a 500ms delay so the tracking call could go out before the page was destroyed.
Pre-tag management, the
s.tl() method did it for us, if you passed in the clickable DOM element as the first parameter. That why you see a lot of
s.tl(this, ...) out there. And if you didn’t need those 500ms, you would simply pass
Then came DTM, then Launch, and now you can add the delay on the “Click” Event Type provided by the Core Extension.
To summarise: we are delaying the browser response to the click, because we need the browser to send tracking.
That’s because it is.
And that’s why, at some point, the
navigator.sendBeacon() method was introduced, as a way to send data even in a “dump this page” situation.
The big caveat first: Internet Explorer is not playing. No big surprise, here, I guess, given that even Microsoft is working very hard on digging a deep grave for it.
But it sounds like IE is now down to single digit percentages on most sites, so maybe that can be tolerated in exchange for a better experience for everyone else.
According to the sendBeacon documentation on MDN, all other browsers have been supporting
sendBeacon for some time, now.
Browsers supporting it is just one part of the picture, the other is support in Adobe Analytics.
That was added in AppMeasurement 2.17.0, in August 2019. You can find the documentation here.
sendBeacon, you set
s.useBeacon = true;, and then the next tracking call will go out via
sendBeacon, easy enough.
Btw: the automatic exit link tracking uses
sendBeacon, by default, which makes a lot of sense.
The Analytics Extension for Launch does not yet have any means built-in for sending a beacon using
sendBeacon, at this time, though.
How to use it with Launch?
The Extension does so far not support
sendBeacon in the “Send Beacon” Action Type (I’m sure I’m the only one finding that funny, on a “when Launch has launched” sort of level), and so the obvious question is: how can I use it?
I have three options for you, all workarounds.
Option 1 — Write an Extension that has a ‘Use
sendBeacon for next “Send Beacon” Action’ Action Type,
Option 2 — Use a “Custom Code” Action to set
s.useBeacon = true before the “Send Beacon” Action, or
Option 3 — Use a “Custom Code” Action to set
s.useBeacon = true after each call to “Send Beacon”.
The least “workaround-y” workaround IMHO would be to build an Extension that provides a ‘Use
sendBeacon for next “Send Beacon” Action’ Action Type. You would use that Action Type in your Rules just before the “Send Beacon” Action that sends data to Analytics.
If you’re not into writing Extensions, you can achieve the same with a “Custom Code” Action, of course. Just put that Action before the “Send Beacon” Action, and voilà!
There is one issue, though, and it kills this idea: because the Action is a “Custom Code” Action, Launch only loads the code when it is needed, i.e. when the Rule fires. The browser, at this point, is still trying to get rid of the page as quickly as possible, and so loading the code, executing it, then moving on to the “Send Beacon” Action and actually sending the tracking call is likely going to take too long.
On subsequent occasions, the code will have been cached, but you’ll likely lose the first one. Given that often, that first time may also be the last, this option is not brilliant.
That’s where the third option comes into play: use a “Custom Code” Action Type to set
s.useBeacon = true after each “Send Beacon” call.
The reasoning is this: we can track the initial page load as usual. The next tracking call may well be a link click, so let’s set
s.useBeacon = true right now. That way, the reaction to the click can be faster when it happens.
Options 1 & 3 are practicable, option 2 is not. All of the options will hopefully no longer be necessary once the Analytics Extension allows us to chose in the UI.
I have a short reading list for you, about
sendBeacon, and about the different events in the lifecycle of a web page.
First, the aforementioned documentation for
sendBeacon on MDN — concise, simple, good for refreshing your memory on how to use it.
Second, Don’t lose user and app state, use Page Visibility by Ilya Grigorik, in which he explains how the Page Visibility API works, and why using the
onunload event is not a great idea at all.
Third, Google’s developer documentation on the Page Lifecycle API, which has a metric ton of stuff, probably too much for most people on here.
Update 2021/02/19: there are a lot of reasons not to use sendBeacon.
If you are worried, check out what Simo Ahava has to say on Twitter, the discussion on the MDN article, and the numbers shown by Paul Boocock on Twitter.
This is no silver bullett.
7 thoughts on “Why not use sendBeacon?”
How did I miss this s.sendBeacon setting when we upgraded to 2.17?? We cannot use the click delay because it breaks many of our “links” (a separate story), so this just might be the solution for us.
Thanks for highlighting! This is the main reason I try to read blogs like yours. At this point in my job role I simply don’t have the time anymore to comb through all of the documentation, and internalize them, when Adobe makes updates. I rely on people like you to help me with that, and you always come through with hidden nuggets.
LikeLiked by 1 person
Thank you, Cleve!
Incidentally, that is precisely the reason why I write, too 🙂
I have been using option 2, but was thinking about moving s.useBeacon = true to doPlugins. Just wondering about your thoughts, any reason you can think of not to do that?
That should work, sure.
I would test a lot, though. After I posted the article, there was a discussion on the #measure slack. Not everyone thinks that the Beacons are ready for production use.
How did you go moving s.useBeacon = true to doPlugins? Any issues? Did you call it conditionality or just placed s.useBeacon = true in there?
I would currently not set it for _all_ hits, there is no need.
After I wrote this article, some people told me about their less than perfect experiences with sendBeacon, so I think a) use it when necessary and b) test, test, test