Geo Targeted Caching extension for W3 Total Cache


Caching not working due to bug in W3TC

If you find that the W3TC page cache isn’t working (even with this extension disabled and the default W3TC rules in your server config), it could be down to this error: Warning: Parameter 1 to W3_Plugin_TotalCache::ob_callback() expected to be a reference, value given in /wp-includes/functions.php on line 3269.

Cookies preventing caching

Another issue that can prevent W3TC from caching files, even without this extension, is if your browser is sending cookies with the request. I have experienced a situation where when testing this extension, even though I was logged out of WordPress (and had not been logged into it for quite some time), the browser was sending cookies.

So, if you need test that caching is working, make sure you are logged out of WordPress, and clear the cookies in your browser.

Geolocation not working due to Apache prefixing vars with REDIRECT_

Another possible problem you may come across, is the country code not being added to the page key by the extension correctly. While there could be numerous reasons for this (the most obvious culprit would be if you don’t have the GeoIP extension for Nginx / Apache installed correctly, or not passing the parameter to PHP with Nginx), one possible reason could be due to Apache prefixing of variables with REDIRECT after passing through a rewrite rule.

The extension uses the PHP variable $_SERVER['GEOIP_COUNTRY_CODE'] to get the country code to add to the page key. If PHP doesn’t have this variable, instead having the variable as $_SERVER['REDIRECT_GEOIP_COUNTRY_CODE'], the extension won’t be able to get the country code. A solution to this problem can be found here: When setting environment variables in Apache RewriteRule directives, what causes the variable name to be prefixed with “REDIRECT_”?

Gzipped cache files not being created

If you inspect the wp-content/cache/page_enhanced/ folder (or subfolders depending on your site structure) you should see two versions of each cached page per country – a plain .html cached file, and a gzipped .html_gzip file. If you find that the gzipped files are not being created, there can be a few reasons for this.

One reason is if you have debug turned on in the W3TC General settings. Having debug turned on for page cache prevents W3TC from using / creating a gzipped cache file. (Note the debug setting in W3TC is separate to the WP_DEBUG constant setting, having WP_DEBUG set to true causes no problems).

Related to this, if you previously have had debug turned on in the W3TC General settings, then turn it off, you need to purge the cache. Otherwise, where a non-gzipped cache file exists but no gzipped file exists, W3TC will serve up the uncompressed file (and compress it on the fly).

Possibly if a browser that doesn’t support gzip requests an uncached page, then only the uncompressed version would be cached, and create the same issue. However, I haven’t tested this.

Use with plugins that use other GeoIP methods

This extension should ideally only be used to geo-cache files where the geo-content is determined based on the $_SERVER['GEOIP_COUNTRY_CODE'] PHP variable (which is normally set by a server with the GeoIP extension installed). There are two reasons for this, which I’ll give by example:

  1. Let’s say that you have a plugin that prints a greeting to the user in their local language, and this plugin uses the ip2nation method of geoIP lookup. You configure the Geotarget W3TC extension to only cache separate pages for countries in Europe, and all other countries get a page cached for the US.

    If a user from China hits an uncached page, the page will get generated with a greeting in Mandarin Chinese by the plugin, which looks up the user’s country using ip2nation. This page will then get cached as the US page by the Geotarget W3TC extension, because CN is not in the list of countries pages should be separately cached for, and so is assigned to the default country code.

    And so when a US user (or anyone in a country that is not in the list of countries pages should be separately cached for) visits that page, they’ll see the cached page with the greeting in Chinese.

  2. Let’s say that you have a plugin that prints a greeting to the user in their local language, and this plugin uses the ip2nation method of geoIP lookup. This plugin only supports countries in Europe, and prints a greeting in American English for users from all other countries. You configure the Geotarget W3TC extension to only cache separate pages for countries in Europe, and all other countries get a page cached for the US.

    A user visits an uncached page. The server (or PHP) GeoIP extension identifies this user as being from France. However, the ip2nation method has this user’s IP down as being in Germany. (Maybe the user lives on the border between Germany and France). So the page is generated with a greeting in German, but cached under France. Then any subsequent French users visiting this page will see the cached page with the greeting in German.

The extension force-sets the $_SERVER['GEOIP_COUNTRY_CODE'] variable to the country code that the page will be cached under. So any plugins that use this variable to determine what country the user is from will be sure to generate localised content that is correct for the country it will be cached for.

Both my Geo Text and Currency Conversion plugins can use this variable for determing the country code (amongst other GeoIP lookup methods). But not all plugins do.

Cache isn’t being cleared / flushed

The original version of the extension didn’t support cache flushing at all, which meant you had the clear the complete cache with W3TC to clear the cache for a single page. The second version (2015-09-01) supports clearing the cache of a single post. Since pages and posts are both stored the same way, I think this is all that is needed.

The cache for a page should be automatically flushed whenever you update it. (And flushing the cache for a page should also flush the cache for all pages where the page is included, such as tag, category, index, and archive pages). If you have a situation where the cache is not being cleared, please let me know.

Note that to minimise the number of pages that require the cache clearing when a new post is added or an old post updated, you should use reverse page numbering. No, I don’t currently use reverse page numbering myself, but it is something I intend to implement.

The extension only tries to modify the cache key of pages with a .html or .html_gzip extension. It is possible that certain permalink structures may cause W3TC to generate a cache key with a different extension, which would lead to the page not being geo-cached.

I need to do more testing on this. If you have any problems with this, please let me know your permalink structure so I can recreate the problem and find a solution.

Does PHP cache retrieval kick in before full processing?

If you have been using Disk: basic caching with late init checked, then switch to Disk: enhanced caching, the late init option is disabled in the W3TC admin panel, but the actual setting stays as it was previously. So you must ensure that you do not have late init set before switching to Disk: Enhanced page cache.

When late init is not enabled, then yes, W3TC retrieves the cached page and exits (serves the page) before plugins etc. are loaded. This makes it much faster than WordPress without caching, but still slower than having the web server serve the cached files directly.

Being served page for a different country

If you are served a page for a country other than the one you are in (and you have added your country to the list of countries to cache pages separately for), then it likely means that the GeoIP detection method has your IP address registered incorrectly. There’s not much you can do about this, other than contacting the data provider (most likely MaxMind) for whatever GeoIP method you’re using, and asking them to update their database.

Depending on your GeoIP provider, testing with a proxy may also give unreliable results. Proxies may be assigned a fake country code (such as A1) by the GeoIP lookup. The fake value will then be mapped to the default country. So if you use a French (for example) proxy to check that a French visitor is being served a French page, you may actually see a US (or whatever your default country is set to) page due to the proxy’s country being identified as A1 rather than FR.

Debugging any other problem

If you have any other problems with it not working, I suggest first trying without the extension enabled (and with the default W3TC rewrite rules), to make sure W3TC is working correctly.

If that works okay, activate the extension (and modify the rewrite rules appropriately) and do some further debugging. Visit a page on your site (while not logged into WordPress) so that W3TC generates the cache. Now, locate the cache files, and make sure they are there and named correctly.

If the cache files appear to have been generated correctly, edit the .html cache file (as opposed to the .html_gzip file) and add some extra text to it. This allows you to check whether you’re being served the Gzipped or plain HTML cache file. Now edit the main WordPress index.php file, and change it so that it exit();s straight after the opening PHP tag. This lets you be sure that the cached file is being served by the server, and PHP is not being hit at all.

Clear your browser’s cache (but not W3TC’s), and request the same page again. If you get a blank page it indicates that there is a problem with your server rewrite rules, as the request is being passed to PHP rather than the cached page being served. If you get the page that you had added extra text to, it indicates that the server has served you the non-gzipped version of the cached file. Unless your broswer does not send headers to indicate it accepts gzipped content, then it is likely that the gzip W3TC rule in your server config is missing or incorrect. If you get the page without the extra content, then it indicates everything is working correctly, and you are being served the gzipped version of the cached page.

Check that the $_SERVER['GEOIP_COUNTRY_CODE'] variable is being set correctly (temporarily uploading a phpinfo(); page is a good way to check what server variables are set).

If everything looks okay in terms of config, but it’s still not working, you can send me a message / email and I’ll look into it to see if I can determine the problem. Please include a description of the problem, your permalink structure, whether you’re using Apache or Nginx, and the W3TC rules from your Nginx / Apache config.

Posted on by xoogu, last updated