RT Cunningham

Geographical Targeting with Nginx, GeoIP Country and SSI

There’s more than one way to use geographical targeting and more than one database to choose from. The most popular way is to use the country codes returned from a GeoIP country database. With the Nginx web server, it’s easier than using Apache or any other web server.

The only catch is that the GeoIP module has to be included in the Nginx package you’re using. The Debian/Ubuntu repository has the “nginx-extras” package, which includes this module and some other modules not included in the default package for Nginx.

Getting and Using the GeoLite Database

In order to use it, you have to download it and make sure Nginx loads it into its configuration. The current instructions for downloading it is on MaxMind’s GeoIP Country Database Installation Instructions page.

You may be tempted to use the package available in the Debian/Ubuntu repository, but you shouldn’t. It’s always outdated. It’s best to get it from the original source.

After you have it and its decompressed, you only need to add a line like this at the http level configuration of Nginx and reload Nginx to enable it:

geoip_country /path-to/GeoIP.dat;

Enable SSI (Server Side Includes)

SSI can be enabled at the http, server, or location (if in location) configuration levels. If you only have one website to work with, the http level would be the best place. If you have more than one, the server level would be the best place. These are the lines:

ssi on;
ssi_silent_errors on;

You can turn silent errors off while developing, but I’d recommend against it on a production server. The directives are available here: Module ngx_http_ssi_module

Geographical Targeting – A Real World Example

[Update Jun 1, 2014 – I’m no longer doing any geographical targeting. It was a nice exercise but it really didn’t make a difference in the scheme of things.]

I serve Google AdSense Ads to the countries where people actually click on them, mostly English-speaking countries. I serve Infolinks ads (in-text, tag cloud, search) to everyone else. At the server configuration level:

set $adsense "n";
if ($geoip_country_code ~ (AU|CA|GB|NZ|PH|US)) {
  set $adsense "y";

That isn’t my country list – it’s only an example.

I wrap each AdSense block with SSI. Before the block, I use:

<!--# if expr="$adsense = y" -->

After the block, I use:

<!--# endif -->

I don’t use the official Infolinks plugin for WordPress. I put their code in my footer file, just before the closing body tag. I use the same code above and below it, replacing “y” with “n”.

I’ve tested everything and I can guarantee you it works.

You have questions. I have answers.

Is this against the Google AdSense terms of service? Obviously not, because DoubleClick for Publishers (another way to serve AdSense ads) allows geographical targeting. You’re not allowed to use conditional JavaScript because it alters the JavaScript code that serves the ads, which is against the terms of service.

Wouldn’t it be easier to use PHP? Yes, if you don’t cache your pages. PHP doesn’t run on cached pages. If you include conditions in PHP, even within JavaScript code blocks, the condition will remain as is until the cached pages are refreshed.

Isn’t geographical targeting in Webmaster Tools enough to do the job? No. That just helps with the search engine results.

Are there any other uses for geographical targeting and what’s the advantage of doing it with SSI instead of PHP or JavaScript?

The are more uses than I can think of at the moment. One use would be to display a visitor message, displaying the country name or country code to them. Another would be to route visitors to the right pages, based on language.

The advantage of geographical targeting with SSI is that the server code runs before anything else, and that includes PHP (and PHP fastCGI modules). It works regardless of what scripting language you use and it can’t be permanently altered anywhere other than the server configuration code.

May 4, 2014
Web Development

You May Also Like: