Battling Ad Fraud - Spoofed Browsers Detection
$68bn worldwide of total ad spend will fall victim to fraudsters in 2022 alone. So what is AdTech doing to fight off fraud and what kind of technical challenges is it facing?
Detecting if ad impressions aren’t performed by bots is a massive subject in the industry. However the issue isn’t a new thing, its scale and impact has grown significantly. The problem applies to both big and small networks and is an increasingly growing concern across all of the clients.
According to the Juniper Research report, a staggering amount of $68bn has grown from $59bn in 2021, while in 2017 it was ‘only’ $8bn. Other research claims that, as of now, 25%-40% ad campaigns budgets are affected by fraudulent traffic. While the exact numbers are not certain, the costs seems to be massive and growing.
So what are the technical ways to protect against it?
One of the general approaches is scanning of the traffic and detection of various anomalies within. Suspicious impressions are then filtered out and should not affect the campaign.
The algorithms are both classic and AI based. They check technical and behavioral aspects in various perspectives in order to classify and score a given case. Typical example of checks are:
- detecting mobile devices that don’t have a touchscreen
- learn the screen resolution of a particular mobile device and cross check it
- monitor IP address ranges or ISPs
- verify browser features and if they have not been overridden
How does it look in practice?
So however, it’s also possible to detect such changes, at least in theory, as in practice it’s not that straightforward. Just have a look at recent conversation of our engineers, which has inspired me to write down this blog post!
Out of the box thinking is required!
Adam: One way to detect changes is the ‘getString()’ method. Called on a function it returns its source code and in case of native functions the response is “[native code]”.
Pawel: Great, so problem solved, isn’t it?
Adam: Well, actually no! Think about what happens when someone modifies the ‘getString()’ so it returns “[native code]” for the function he had modified!
Pawel: Tricky! But we can actually call ‘getString()’ on the modified ‘getString()’ method, this will reveal that this one has been modified, as well!
Adam: True but, what if someone modifies ‘Function.prototype.toString’ and ensures that if it’s called on itself it returns “[native code]”?
Pawel: I see, but we still can rely on the fact that all customly defined functions have a property named ‘prototype’, so we can check if ‘Function.prototype.toString’ does exist. If it does then we would know it was modified.
Adam: That is indeed correct, but what if the implementation was done through the Proxy (granting transparent virtualization)?