Although data layers are becoming more and more mainstream, quite often we still run into sites that do not have any kind of data layer available, forcing us to execute some funky tricks to get to the data we need for our web analytics and DCO projects. And these funky tricks are pretty fun to perform, actually.

Recently I had to do some research on the website of one of our clients, Nespresso. They hadn’t implemented a proper data layer, so I needed to find another way to get the data I was interested in. In this specific case I was looking for the images of all the possible colours of a coffee machine. The first place to look in case there is no data layer available, is the DOM/HTML, but in this case I could only find the initial product image there. I needed to dig deeper.


Nespresso.nl product page

While looking at the HTML structure of the page, I recognised the website uses Angular – a JavaScript framework for building websites and web apps. You can easily recognise this because Angular uses ng- in all sorts of HTML attributes. One other way to find out is by checking if the global variable angular exists in the Window scope of the website, using your browser’s console.

The images of the other colour variations should be available in the Angular app, so let’s see how to find that data. Using Chrome, right-click the colour options element in the middle of the page and chose ‘Inspect’. Chrome’s Developers Tools opens and shows the HTML of the selected element. Go to the console tab. When you have a selected element in the DOM, you can refer to this element using the variable $0. Good stuff!

Using angular.element(element), you can read the Angular data for a specific DOM element, so let’s give it a shot with angular.element($0). When you run this code, nothing fancy happens, you just get the same DOM element, but now in an Array. Things get interesting when we ask for the current scope op the element. With Angular, at least version 1.x, $scope refers to a concept of a application object, which is the owner of application variables and functions. This application model holds the data of the application, and thus also our image data. To get the scope for an Angular element, you execute the scope method: angular.element($0).scope(). Now you get a far more interesting result:

Voilá, quite some inner details of the Angular app! Here starts the best part of the expedition. I usually start clicking open some of the objects until I find what I’m looking for. It’s a good idea to start looking at the $parent properties until you find something interesting. When you can’t find what you’re looking for, try inspecting the scope of other DOM elements. In the case of Nespresso, I had to go up two levels ’till I found a object called splash that holds a colors array. Bingo!

You can only use $0 for debugging and exploring, so after you’ve found the data you need, you can rewrite the code with the correct DOM selector. In our case to find the colours of the variations, we ended up with this code:

const colors = angular.element('.machineDetailsInfo').scope().splash.colors;
  

Note on Angular 2+

The above example only works with websites that use Angular 1.x. Although there are still tons of sites that use this version, it’s already pretty old. Luckily, you can also read the application data in new versions of Angular, but instead of using angular.element($0), you need to use ng.probe($0).

Leave a Reply