Prehistoric Browsers, conversion.js, and How I Came to Love Drupal.settings
We’ve been working on a website that all of a sudden developed a really specific and annoying problem. After going to any page in the site, the page would load, then would instantly go to a white screen and sit there forever. This only happened to certain users, and was tough to duplicate from any of my dev environments.
Digging deeper, I found that the issue was with the Google Analytics conversion.js script, but only with circa version 3 Firefox and Safari, and it appeared that this issue came up as a result of some change on Google’s side — our site used to work fine with these browsers, then something changed and broke. The “white” page was loading a 1px-by-1px tracking pixel from Google, and inexplicably timing out on some request to an Adsense server.
Our site was loading the Adsense conversion tracking script in 3 situations — general browsing, and based on two specific user-conversion actions. The general browsing instance was handled by the Google Analytics module. We added the conversion tracking code in the “post-snippet code” to automatically add a reference to Google’s conversion.js script on every page. For the pre-historic browsers, that spelled a death-knell for the site.
Since the percentage of traffic from these browsers is fairly low, we decided to simply bypass the conversion tracking for those users, instead of trying to work any kind of fancier work-around.
The only issue to tackle at that point was handling the logic to selectively omit the conversion script based on the user’s browser/version. Since the conversion scripts were included in both PHP and JavaScript, I elected to use PHP to handle the inclusion logic, and use an AJAX callback for the JavaScript.
Implementing this wound up being a bit more of a pain than I’d hoped initially as several steps threw up little roadblocks, so I wanted to share some of my experience…
PHP Browser detection
Browser detection in PHP is pretty straight-forward — you can use the get_browser function, which requires you to download and configure an additional browscap.ini file in your server settings — this file just contains a bunch of browser name definitions that the get_browser module can use against the HTTP_USER_AGENT header to determine the user’s browser version and other info. You download the browscap.ini file to the server, set it up in php.ini as instructed with the browscap directive, and you’re good to go, right?
No.
For inexplicable reasons, in my local build of PHP, the browscap file worked just fine. On the server, however, it was a different story — the file wouldn’t parse correctly despite numerous attempts to rectify the situation. This likely had to do with slightly different OS platforms and PHP builds. Rather than fight the solution, I tracked down Chris Schuld’s PHP Browser Detection script. It was extremely easy to use, and required no changes to the server’s configuration, which is a help for those of you who may be dealing with shared hosting restrictions. I did have to put a slight piece of logic in-place to simplify the version number — Chris’ script displays the whole version number which can have multiple decimal points, so I added a split function and stripped out only the major version release.
Menu Callback
I set up a menu callback to return the result, TRUE or FALSE, and print it out in a JavaScript-readable format. Since this was a single value, there was no need to leverage JSON, so I just did a simple drupal_to_js($result);
JavaScript logic && Drupal.settings
I used a jQuery post construct to handle calling the ajax callback function.
$.post('/ajax/my_callback_url',
function (msg) {
//need to pass back result or set persistant variable accessible elsewhere
});Because of variable scope, I couldn’t just set a value inside the $.post function’s success function, nor could I return a value. In order to set a flag that was accessible to other JavaScripts, I leveraged Drupal.settings and set Drupal.settings.myModule.myVariableName = msg. That meant that anywhere else I needed to check the value, I could just reference the jQuery object.
Putting It All Together
I added the logic to the requisite places in-code and was successfully able to omit the conversion scripts for prehistoric browsers. Everything worked great, except…
Varnish — the secret nemesis
Since the site is running on a Varnish/Pressflow stack, I ran into an immediate issue that the AJAX callback page was getting pulled from cache, instead of correctly reporting if conversion scripts should be displayed on a specific browser-by-browser basis. In order to avoid this, I needed to instruct Varnish not to cache this page.
To do this simply edit the yoursite.vcl file, and add the following logic to the vcl_recv() function, which dictates initial handling of requests:
if (req.url ~ "ajax/display_conversion_script") {
return (pass);
}To be even fancier and simply instruct Varnish to not cache all AJAX pages, you can use wildcards in the VCL rule. It is not necessary in this site, but can be useful. Even better might be to set flags in the URL to dictate whether items should be cached or not — e.g. ajax-cacheable vs ajax-nocache, etc.
Discussing cache strategies and approaches is out of the scope of this (longwinded) article, so let’s table further discussion for now.
Finally
I put all the pieces together and everything finally worked. Happy ending to an annoying problem. I hope you found this information useful. Please add any questions or clarifications to the comments below.
Case Studies
In-depth articles and case studies detailing real-world examples of how and why we work the way we do.
News and Articles
News and announcements, as well as articles, tutorials and white papers detailing our development philosophy and design patterns.

