I want a store to intelligently choose a default currency based on the customer's IP using GeoIP when they first visit (with no preselected currency cookie). The store is behind Varnish using Nexcess's excellent Turpentine extension.

The extension handles currency fine as long as the standard Magento currency cookie is set on a given request.

My thoughts at this stage are:

  1. Add VCL into the Varnish config to do the GeoIP lookup (in C) and set the cookie on the inbound request, if it's not already set, of course.
  2. Add a per-user cached block that does the lookup and sets the cookie (though this would then not apply on the first page load)

Am I missing an obvious technique - maybe some client-side JS to a non-varnish-cached URL path that makes the determination?

Does anyone know the best way to do this?

4 Answers 4


We've got something like this running in production (we're enabling or disabling add to cart and pricing depending on the customer's location).

We built and installed the "Varnish GeoIP module" from https://github.com/leed25d/geoip-vmod ... This sets a "X-GeoIP" header in each request that reaches Magento indicating the user's country. Within Magento you need to detect this header and customise the content as required.

The final problem to overcome is that Varnish will cache the generated page and serve it to all customers regardless of their country. You could "turn off" caching for that page, but performance suffers, so that's not ideal either. Our solution was to send a "Vary" header in our HTTP response, which tells Varnish to cache different objects for different values of the X-GeoIP header, so we have a different page cached for each visitor's country.

One of my colleagues at Aligent has created a Magento module which contains a helper to fetch the country code from the X-GeoIP header (with fallback to IP if it's not present, which is useful for development), and an observer to send the "Vary" header. We've open sourced the module, check out https://github.com/aligent/Aligent_GeoIP if you want the implementation detail.


You can try and set the X-Forwarded-For server variable and use this with geoip

 remove req.http.X-Forwarded-For;
 set req.http.X-Forwarded-For = client.ip;
  • But that will only help the backend correctly set the currency for the first request to say a product page. The second and subsequent views of that product page, by any user, will be cached by Varnish and so the currency code in the backend won't run right? I think the default setting of the cookie needs to happen before it hits the backend? Sep 16, 2013 at 20:30
  • AJAX or ESI include if your magento-varnish extension supports it. Sep 16, 2013 at 23:06

I haven't done this before, but what this is what crosses my mind:

Use libvmod-geoip to determine the country code (haven't used this varnish extension, be careful ;-) ) https://github.com/lampeh/libvmod-geoip

Then you extend the hash function via sub vcl_hash() to add the country code to the cache-keys. That allows you to cache everything based on the country-code.

sub vcl_hash {
    set req.hash += geoip.client_country_code();

You also add the country code as a header, like set req.http.X-GeoIP = geoip.client_country_code(); so the magento server is able to determine the correct country and deliver the correct stuff.

This is just an idea, you might need to improve it, but hopefully helps you to find a good solution :)

You can also access the customers cookies and check for a country-code/currency and, if set, go a different way and don't call the geoip function...


You suggested per user caching, which is madness. Your cache hit rates will be almost nil voiding any benefit of using Varnish in the first place. Not to mention Varnish will be working extremely hard through its LRU mechanism to be disposing of old per user cache entries to make space for new per user cache entries.

You have a few options,

  1. Keep varnish, use the varnish geoip module, use per user caching, have 0% hit rates and waste all your server resources on the varnish instance.
  2. Keep varnish, use the varnish geoip module, use an ESI for any currency related block. You'll need to cache the esi, otherwise, again, hit rates will be nil.
  3. Keep Varnish, use the varnish geoip module, and just change your URL structure. If you have a different url for each currency (eg. /usd, /can), then you'll have undiminished hit rates, and it will work almost flawlessly.
  4. Ditch Varnish, then everything will work as intended.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.