Title: Wonderful Geo Page Cache
Author: wonderfulplugins
Published: <strong>November 4, 2026</strong>
Last modified: November 4, 2026

---

Search plugins

![](https://ps.w.org/wonderful-geo-page-cache/assets/banner-772x250.png?rev=3783834)

![](https://ps.w.org/wonderful-geo-page-cache/assets/icon.svg?rev=3783834)

# Wonderful Geo Page Cache

 By [wonderfulplugins](https://profiles.wordpress.org/wonderfulplugins/)

[Download](https://downloads.wordpress.org/plugin/wonderful-geo-page-cache.1.0.8.zip)

 * [Details](https://wordpress.org/plugins/wonderful-geo-page-cache/#description)
 * [Reviews](https://wordpress.org/plugins/wonderful-geo-page-cache/#reviews)
 *  [Installation](https://wordpress.org/plugins/wonderful-geo-page-cache/#installation)
 * [Development](https://wordpress.org/plugins/wonderful-geo-page-cache/#developers)

 [Support](https://wordpress.org/support/plugin/wonderful-geo-page-cache/)

## Description

Most page caches store one copy of a page. That breaks every site that renders a
page differently per country: a WooCommerce shop that shows prices including the
VAT rate of the visitor’s country, or a site that sends first-time visitors from
abroad to its English version. Cache such a site and every visitor sees the prices
of whoever happened to fill the cache.

**Wonderful Geo Page Cache** keeps a separate copy per visitor country, looked up
from the GeoLite2-Country database WooCommerce already maintains, and per value 
of the cookies you name. A visitor from Germany gets the copy rendered for Germany,
a visitor from Austria the one for Austria — and bots and scanners, who hit the 
same pages over and over, cost about a millisecond instead of a full WordPress render.

#### What makes it different

 * **One copy per country** — no country lookup in JavaScript, no flash of wrong
   prices, no “geolocate with page caching” URL parameters.
 * **Cookies that vary the page** — name the cookies your site uses for a chosen
   country or language; each value gets its own copy.
 * **A country the visitor chose** — when your site keeps a chosen delivery country
   in a cookie, name it as the country cookie: a visitor who picked Austria shares
   the copy of visitors from Austria instead of getting one of their own.
 * **Cookies that count only when set** — a “first visit” marker your site only 
   checks for gives one copy with and one without it, whatever its value.
 * **Cookies that may be replayed** — a “first visit” cookie the site sets identically
   for everyone is stored with the page and sent again, so first visits are cached
   too. A response that sets any other cookie is never stored.
 * **Redirects are cached** — a language or country redirect for first-time visitors
   is stored like a page.
 * **Safe against cache poisoning** — requests whose client address is ambiguous(
   several forwarded addresses) are not cached, so a page rendered for one country
   cannot be stored for another.
 * **Pages stay cached until something changes** — the security tokens (nonces) 
   WordPress puts into a page are taken out when it is stored and computed afresh
   every time it is served, so a cached page never carries an expired token.
 * **Prewarm** — after the cache was emptied, the plugin requests again the pages
   and variants visitors used in the last 30 days and every other public page, in
   every language of WPML or Polylang, so visitors rarely meet a page that has to
   be rendered first. What people use decides what is warmed; crawlers do not.

#### How it works

 * An `advanced-cache.php` drop-in answers cached requests before WordPress loads.
 * Pages are captured with the template output buffer of WordPress 6.9 and later.
 * Visitors with a login, cart or session cookie, POST requests, URLs with unknown
   parameters, cart, checkout and account pages are never cached.
 * Visitors with a cart can be allowed to read the cache: move the WooCommerce cart
   cookies to “Cookies that only read the cache” and they get cached pages, while
   pages rendered for them are never stored. Use it only when your mini cart refreshes
   after the page has loaded (WooCommerce cart fragments).
 * The whole cache is emptied when content, menus, widgets, stock, scheduled sales,
   tax rates or plugins change, and through “Empty page cache” in the toolbar menu“
   Geo Page Cache”. Otherwise pages stay until a lifetime you set, or for good with
   lifetime 0.
 * Nonces are renewed with the keys from wp-config.php. Every nonce is checked against
   WordPress when a page is stored; if one cannot be rebuilt — or the page contains
   a nonce WordPress did not report — that page keeps its nonces and expires after
   12 hours.

## Screenshots

[⌊Settings: cached pages, lifetime, prewarming, visitor country, and which cookies
and URL parameters change a page.⌉⌊Settings: cached pages, lifetime, prewarming,
visitor country, and which cookies and URL parameters change a page.⌉[

Settings: cached pages, lifetime, prewarming, visitor country, and which cookies
and URL parameters change a page.

[⌊Toolbar menu: cached pages, last prewarm, switch the cache off, empty it.⌉⌊Toolbar
menu: cached pages, last prewarm, switch the cache off, empty it.⌉[

Toolbar menu: cached pages, last prewarm, switch the cache off, empty it.

## Installation

 1. Install and activate the plugin.
 2. Add `define( 'WP_CACHE', true );` to `wp-config.php`.
 3. Go to Settings  Geo Page Cache, name the cookies and URL parameters your site varies
    on, and enable the cache.
 4. Check a page with your browser’s developer tools: the response header `X-Wonderful-
    Geo-Page-Cache` says `MISS` on the first request and `HIT` on the next one.

## FAQ

### Where does the country come from?

From a GeoLite2-Country database on your server. If WooCommerce geolocation is enabled,
its database is used automatically; otherwise enter the path of any MaxMind DB file.
Nothing is sent to an external service.

### My server sits behind a proxy.

If the web server already puts the client address into `REMOTE_ADDR` (mod_remoteip,
as in the official WordPress Docker image), keep `REMOTE_ADDR` — mod_remoteip removes
the forwarded header it has read. Otherwise choose the header that carries the client
address (for example `HTTP_X_FORWARDED_FOR`). If the configured source is missing
on a request, that request is not cached rather than filed under an unknown country.

### How does prewarming render a page for another country?

The prewarmer requests the page from the site itself with a header signed by a key
derived from the salts in `wp-config.php`, which only the site knows and which is
never written to a file. The drop-in accepts that header only with a valid signature
and then treats the request as coming from an address in the wanted country (taken
from the GeoLite2 database), so WordPress renders exactly what a visitor from there
would get. It sends at most two requests a second.

### Where are cached pages stored?

In `wp-content/uploads/wonderful-geo-page-cache/`: the cached pages, the configuration
the drop-in reads and the prewarm state, all as plain data files, never as code.
An `.htaccess` file closes the folder to web requests on Apache and LiteSpeed. On
nginx, add a rule such as `location ^~ /wp-content/uploads/wonderful-geo-page-cache/{
deny all; }`.

### Does it work with another cache plugin?

No. Only one plugin can own `advanced-cache.php`; the plugin never overwrites another
plugin’s drop-in and tells you when one is installed.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Wonderful Geo Page Cache” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ wonderfulplugins ](https://profiles.wordpress.org/wonderfulplugins/)

[Translate “Wonderful Geo Page Cache” into your language.](https://translate.wordpress.org/projects/wp-plugins/wonderful-geo-page-cache)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/wonderful-geo-page-cache/),
check out the [SVN repository](https://plugins.svn.wordpress.org/wonderful-geo-page-cache/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/wonderful-geo-page-cache/)
by [RSS](https://plugins.trac.wordpress.org/log/wonderful-geo-page-cache/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.0.8

 * Video in the readme, new screenshots in English and German.

#### 1.0.7

 * The cache is switched on and off with a toggle in the first row of the settings
   page and in the toolbar menu, right away and without saving the form; switching
   it off ends a running prewarm.
 * The settings checkboxes are shown as toggles.

#### 1.0.6

 * New setting “Cookies that only read the cache”: visitors carrying one of these
   cookies, such as the WooCommerce cart cookies, get cached pages, but pages rendered
   for them are never stored. Pages with nonces WooCommerce ties to the session 
   are rendered fresh for them.

#### 1.0.5

 * The update to 1.0.4 no longer empties the cache when it adds the new ignored 
   parameters.

#### 1.0.4

 * Cached pages, configuration and prewarm state are stored as plain data files 
   instead of PHP files; the files of earlier versions are converted or removed 
   on the first request after the update.
 * Prewarm requests are signed with a key derived from the salts in wp-config.php
   instead of a secret stored in the database and in the configuration file.
 * Google Ads parameters (gad_source, gad_campaignid) and other click IDs (dclid,
   yclid, twclid, ttclid, li_fat_id, igshid, HubSpot, Marketo) are ignored by default,
   so ad clicks get the cached page; sites with the default list get them added 
   on update.

#### 1.0.3

 * Prewarm: only requests with a cookie set by the site’s scripts (consent banner,
   analytics, language switcher) count as people; crawlers that keep the site’s 
   own cookies no longer decide which variants are warmed.

#### 1.0.2

 * Country cookie: visitors without the cookie now share the copy of visitors who
   chose their country, as intended.
 * Prewarm: a run whose batches stopped handing over is continued by the next request
   WordPress handles, instead of waiting for the hourly cleanup; the hand-over request
   gets enough time for HTTPS.
 * The settings show when and by what the cache was last emptied.
 * The daily scheduled-sales event no longer empties the cache; products whose sale
   starts or ends still do.
 * Prewarm queries every language of WPML or Polylang on its own, so pages that 
   exist in one language only are warmed too.

#### 1.0.1

 * New “Country cookie”: a country code the visitor chose (for example in a delivery
   country banner) replaces the address lookup, so these visitors share the copy
   of their country.
 * New “Cookies that count only when set”: one copy with and one without such a 
   cookie, whatever its value.
 * Prewarm also warms the translations of every page with WPML and Polylang.
 * Prewarm follows people: requests from crawlers are no longer recorded, requests
   of returning browsers come first, and a first visit from the shop country is 
   always warmed.

#### 1.0.0

 * First stable release: page cache per visitor country and cookie, nonces renewed
   on every delivery, prewarming, toolbar menu.
 * Settings: cached pages and “Empty page cache” sit in the settings table.

#### 0.9.5

 * “Cached pages” instead of “Cached responses”; the toolbar shows a spinner and
   live progress while prewarming; “Prewarm now” removed again (runs start by themselves).

#### 0.9.4

 * Toolbar menu “Geo Page Cache”: cached pages and their size, prewarm progress 
   with a spinner that updates while a run is in progress, “Empty page cache” and
   the settings.

#### 0.9.3

 * Prewarm right after installation: before any visitor was seen, every public page
   is warmed for a first visit from the shop’s own country.

#### 0.9.2

 * Nonces are renewed on every delivery, so pages can stay cached until something
   changes (lifetime 0, the new default).
 * Prewarm: refills the cache in the background after it was emptied.
 * The visitor country is read from the “country” field only, like WooCommerce does.

#### 0.9.1

 * The settings menu entry is now called “Geo Page Cache”; the settings page keeps
   the full name.

#### 0.9.0

 * First public version: one cached copy per visitor country and per named cookie,
   cached redirects, replayed first-visit cookies, purge on content, product, stock
   and tax changes.

## Meta

 *  Version **1.0.8**
 *  Last updated **11 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.9 or higher **
 *  Tested up to **7.1.4**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [cache](https://wordpress.org/plugins/tags/cache/)[geolocation](https://wordpress.org/plugins/tags/geolocation/)
   [page cache](https://wordpress.org/plugins/tags/page-cache/)[vat](https://wordpress.org/plugins/tags/vat/)
   [woocommerce](https://wordpress.org/plugins/tags/woocommerce/)
 *  [Advanced View](https://wordpress.org/plugins/wonderful-geo-page-cache/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/wonderful-geo-page-cache/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/wonderful-geo-page-cache/reviews/)

## Contributors

 *   [ wonderfulplugins ](https://profiles.wordpress.org/wonderfulplugins/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/wonderful-geo-page-cache/)