In our work at Krux, especially with our Data Sentry and Inspector products, we see many different approaches for firing pixels, some good, some not as good. We’d like to see the industry adopt better practices for delivering pixels to end users.
First – when I say “pixel”, I mean an http request issued on a web page that downloads invisible content to create an http transaction. The pixel does not provide any visual effect to the web page, but instead is there to provide analytics for the website owner, improved ad targeting, cookie synching across domains for data collection, or other web personalization.
Fire It Only When Necessary
An often overlooked element of responsible pixel delivery is that you usually don’t need to fire it for every user, nor for every page view. Instead of the fire-hose approach, it’s best to be intentional and precise; only fire the pixel when necessary to the users where it is needed. Here are some examples of ways that you can throttle the firing of the pixel for specific situations.
Frequency caps – If the purpose of the pixel is to synchronize unique identifiers across domains (aka cookie synching), or if the pixel is for brag-about-my-audience-size analytics like Comscore where you only care about Unique Visitors (and not page views), a frequency cap will reduce latency for your end users.
Segment targeting – If you have a targeted ad campaign for which you need pixels fired, target only those users that correspond to the campaign. If you need males 18-34, serve only to them; don’t fire the pixel for females over 40.
Start/End Date – If the campaign you need the pixel for is for the next 30 days, stop firing the pixel when the campaign is over.
Follow Privacy Best Practices
At Krux, one of our sayings is “It’s your data,” and that applies to end users just as much as it does to publishers and advertisers. This topic both wide and deep, and as such could be a few blog posts by itself, but here are the quick highlights with links to additional reading.
Allow for User to Opt-Out
Users should be able to opt out of tracking. Our friends at Privacy Choice have put together a great post that outlines best practices for handling opt-outs. Read every word, but the Cookie Details section is particularly applicable to pixel delivery best practices.
Opt-out cookies should always be non-unique (the exact same cookie should be written on every computer opting out). Because unique cookies can allow continued identification of a unique computer, they undermine confidence in the opt-out process.
The name and values of opt-out cookies should clearly indicate their purpose.
Example (cookie name): OPT-OUT
Example (cookie value): YES
Set the cookie expiration date/time as 12:00:00 January 1, for a year that is at least five years in the future. Do not set the expiration date based on the moment that the opt-in is selected, since that would result in the cookie being uniquely identifiable.
Do not use multiple opt-out cookies unless you have multiple ad serving domains, in order to avoid confusion.
To the extent that you continue to write any cookies other than the opt-out cookie for users who have opted out, those should be session-cookies only. If you have any reason to maintain persistent cookies other than the opt-out cookie itself, clearly explain those purposes in your privacy policy.
Include a P3P Header
In order for cookies to be set across domains with Internet Explorer 6+, you need to have a P3P header set in the http response. This header tells the browser what the website intends to do with the data. For example, the P3P header for Krux’s pixel:
P3P: policyref=”http://cdn.krxd.net/kruxcontent/p3p.xml”, CP=”NON DSP COR NID OUR DEL SAM OTR UNR COM NAV INT DEM CNT STA PRE LOC OTC”
For help in setting up your own P3P policy, try using one of the many P3P policy generators, which will ask you a series of questions about how you will use the data and then it generates the policy for you.
Respect Do Not Track
Do Not Track (DNT) is a collaborative effort between the Advertising Industry and browsers to respect users choices on privacy. For a thorough perspective on DNT, check out Jos Boumans excellent blog post, where he not only explains what DNT is, but what you need to do on the server side to properly support it.
In addition to server side support of DNT, you can avoid firing the pixel altogether by checking the window.navigator.doNotTrack property with javascript — if the browser supports it.
Shave Bytes – Use HTTP 204 No Content
What’s the smallest image you can send back? Don’t send one at all!
The main purpose of the pixel is to send data – the return value is irrelevant. Sending a blank pixel that will never be shown to the user wastes bandwidth and increases latency for the end user. Thankfully, the HTTP specification allows for this situation perfectly with a special OK status called HTTP 204 No Content.
To see this in action, check out Krux’s pixel via redbot.org, which will return HTTP 204 no content, and no image, shaving 42 bytes. 42 bytes may not sound like much, but for the billions of pixels per day we see here at Krux, it adds up. Perhaps 42 isn’t the answer to everything.
Pro Tip: To check a servers http headers, we usually use curl on the command line, but redbot.org is a great web based tool for viewing http headers that will also validate your response and provide caching information.
Important Note About 204
Some folks get confused when they first see http 204, because they have been trained to look for HTTP 200 as the OK status. All HTTP statuses in the 200 range are considered valid – It’s all good.
Use Image() and Don’t Clutter the DOM
Instead of using document.write or injecting an tag into the DOM, we’ve found that the best approach is to use the Image object in javascript:
(new Image()).src = “http://beacon.krxd.net/pixel.gif”;
Advantages:
When you set the src attribute of the Image object is set, it begins downloading the image immediately, asynchronously.
You don’t have to attach it to the DOM, which keeps things tidy.
Support HTTPS
You need to make sure that your pixel will work if the page is on http or https. If you try to download an http pixel on an HTTPS page, browsers will throw security warnings. To make your pixel work with either http or https, one often used trick is to omit the protocol from the url:
(new Image()).src = “//beacon.krxd.net/pixel.gif”;
This makes the protocol inherit the protocol of the page, so it will use http or https depending on what the page is. However, one issue with this is that if you send someone a tag in a file, if they open it up from their local computer, it will try to use the file:// protocol, which won’t work. To avoid this issue, you can test for the protocol when constructing the url. Here’s an example of how to do that:
(new Image()).src = (location.protocol == “https:” ? “https:” : “http:”) + “//beacon.krxd.net/pixel.gif”;
This will work with http, https, or file protocols.
Deliver the Pixel Asynchronously
Make sure that you issue the http transaction asynchronously. If you use the Image() approach outlined above, you are fine. We’ve seen some vendors use <script> tags to deliver pixels, which halt the rendering of the page and block users from seeing content! For more information on why this is important, check out a previous blog post on sync vs async delivery where we discuss this in detail.
Deliver the Pixel After the Page has Loaded
Don’t introduce latency or constrain bandwidth for the user by firing the pixel when the rest of the content is loading – be polite and wait until everything else is done, so there is no tangible affect for the end user. This is best handled by listening for the window.onload event.
Deliver the Pixel to Geographically Distributed Servers
To keep response times low for end users, use a geographically distributed set of servers and DNS load balancing to have the user serviced by a server that is close to them. FWIW, that’s certainly how the Krux ‘Big Data Whisperers’ have managed to work thier magic on this end.
Pay Attention to the Maximum Length of the Url
GET requests are not designed for a lot of data. While the HTTP spec does not define a specific maximum, browsers and servers have limitations. If you are sending too much, various transport mechanisms along the way may have problems, some failing less gracefully than others. Here are some limitations that we have found:
Internet Explorer <= 8 has a limit of 2083 characters. Apparently IE 9+ increased the limit to 5195.
Apache has a default limit of 8190 characters.
In practice, we’ve found 2000 characters to be a good limit that works for every combination of browser/server that we’ve tested. For more information, see Dan Rigsby’s thorough guide on max url size.
Need to do more than 2000 characters? Consider a POST request.
As we continue to work on this issue, please participate in the AdMonsters Forum to share your solutions and concerns. Also, please feel free to contact Nick at [email protected] to call BS or to go a level deeper.