Detecting Page Zoom In/Out with Adobe Launch

August 11, 2020
By John Simmons,
Senior Analytics Engineer

If you have a text-heavy site, have you wondered whether your site visitors could easily see and read your content across various device types? If so, you may want to track zoom events to determine if visitors are zooming in on text content, which may indicate you need to increase your font sizes, or maybe you want to see if users are zooming out to see all images in a gallery view, or perhaps you are just curious.

Zoom event data may help you design your mobile layout to help users better consume your content.

There is no out-of-the-box method to detect browser zoom in/zoom out events with Adobe Launch. Thankfully, it’s easy to implement with a bit of custom code that utilizes screen-sized data and session storage.

Device Pixel Ratio 

To track the zoom in/out event, we will monitor the value of window.devicePixelRatio. Based on this value and changes to it, we will determine if the window has been zoomed in or zoomed out. According to the MDN documentation, devicePixelRatio is:

“The devicePixelRatio of Window interface returns the ratio of the resolution in physical pixels to the resolution in CSS pixels for the current display device. This value could also be interpreted as the ratio of pixel sizes: the size of one CSS pixel to the size of one physical pixel. In simpler terms, this tells the browser how many of the screen's actual pixels should be used to draw a single CSS pixel.”

This value measures the size of CSS pixels. When a browser zooms in or out, the ratio between these pixels and physical screen pixels changes. This is a better measurement of zooming than say viewport size, which can be changed by zoom events, and by resizing the browser window. The devicePixelRatio value does not change if the browser window is resized.

Setup in Adobe launch

There is a small setup required before we can successfully track the zoom in or zoom out events. First, we create a custom code data element to quickly retrieve devicePixelRatio. I’ll call this data element Zoom Level for simplicity. In general, we recommend using a rigid naming convention for all elements in Launch. If you haven’t already, check out our article on Adobe Launch Naming Conventions.

Data Element Setup

image of a data element setup

Data Element Code

image of a Data Element code

Using Math.round in conjunction with multiplying the result by 100 is not technically required, but gives a nice readable number (220) instead of something like 2.20298.

Second, I need the initial devicePixelRatio of the window to compare it to the new value that exists when the window is zoomed in or out. I do this by setting this initial value in session storage when the page loads. You probably already have a global page load rule you could tack this on to, if not, make a simple one that fires on all pages.

Store Initial Device Ratio in Session Storage on Page Load

image of setting zoom level

Custom Code Setting Zoom Level in Page Load Rule

image of a custom code to set zoom level

Zoom Level Set in Session Storage

image of a zoom level set in session storage

Zoom In/Out Rule Firing

Now that I have a data element to return my devicePixelRatio when needed, and a rule storing the initial value for comparison, I can set up a rule to fire when devicePixelRatio changes. To do this, I will use Launch’s data element changed event type. 

Data Element Changed Event Will Fire My Rule When My devicePixelRatio Value Changes

image of a data element changed

When this rule fires, my custom code will execute and send a zoom out (event1) or zoom in (event2) event.

Custom Code for Firing Events

// Setup
s.linkTrackVars = "events";
s.linkTrackEvents = "event1,event2";
var linkName;

// get current zoom level
// set initially on pageload, and reset in ss when it changes
var currentZoomLevel = parseInt(sessionStorage.getItem("zoomLevel"));
// Reset to new zoom level
sessionStorage.setItem("zoomLevel", _satellite.getVar("Zoom Level"))
// Get new zoom level
var newZoomLevel = parseInt(sessionStorage.getItem("zoomLevel"));

if (currentZoomLevel >  newZoomLevel) {
	s.events = "event1"
	linkName = "Zoom Out";
} else if (currentZoomLevel < newZoomLevel) {
	s.events = "event2"
	linkName = "Zoom In"
}
// log and send beacon
_satellite.logger.log(linkName);
s.tl(this,'o',linkName)

This code should look familiar if you’ve written Adobe Analytics custom code before. After setting up a few variables, I am grabbing the current device pixel ratio (remember I’m calling this zoom level) from session storage and converting it to an integer. Then, I am resetting that same session storage value to the new value (for the next time I need to compare it) and getting it as an integer on the next line. 

Now that I have the old value and the new value as integers, I can compare them. If the current zoom level is greater than the new zoom level that means the user zoomed out on the page, and vice versa. I put all this custom code in an Adobe Analytics - Set Variables action block.

Overview of Zoom In/Out Rule

image of a overview of Zoom In/out rule

Rule Firing in Action

image of rule firing in action

Closeup of Beacons Firing on Zoom Events

image of a closeup of beacons firing on zoom event

Why Use Custom Code?

If you’re like me, you like to make your implementations more explicit by eschewing custom code in favor of the user interface (UI). In fact, I like to avoid custom code altogether, except, of course, when it is unavoidable. In this case, custom code is the best way to accomplish my goals.

Setting Zoom In and Zoom Out as separate rules are not possible using my preferred data element changed event. I need to read the current zoom level and reset it in session storage each time it changes. With two rules using the zoom level changed event, they would both trigger on a zoom change and overwrite each other. This would cause one rule to work and one to never work. Custom code is the way to go. 

Also, you may notice I am sending the beacon in my custom code (s.tl) instead of sending it in the Launch UI. I am doing it this way in order to use a dynamic link name based on the type of event detected. If I were to send the beacon in the UI, then I would not be able to set the link name dynamically.

Taking it further

This is a very basic way to measure zoom events. To further expand upon the implementation you could: 

  • Store the initial zoom level of a page and a set a rule to fire when a user returns to the initial zoom level
  • Fire events at certain page size ratios, i.e. user has zoomed the page in 2x, 3x, etc.
  • Fire an event when a user zooms out enough to see the entire page content without having to scroll.