WPCS - WordPress Currency Switcher Professional

GeoIP du sélecteur de devises WordPress ne fonctionne pas : causes et solutions

Quand les règles GeoIP du sélecteur de devises WordPress ne fonctionnent pas, les symptômes varient : tous les visiteurs reçoivent la même devise, les visiteurs d'un pays continuent de voir la devise de bienvenue, ou le shortcode de test affiche un pays vide. Dans la plupart des cas, le plugin recherche exactement l'adresse qu'on lui fournit. La vraie cause est l'adresse IP que le serveur transmet à PHP, un cache de page qui sert la page d'un visiteur à tout le monde, ou un test qui n'était pas une première visite. Voici comment fonctionne la détection, comment savoir en quelques minutes laquelle de ces causes s'applique, et la solution pour chacune.

Comment GeoIP choisit la devise

Dans l'onglet Règles GeoIP (GeoIP rules) de Réglages (Settings) → Currency Switcher, chaque devise possède une liste de pays. Lors de la première visite d'un visiteur, le plugin détermine le pays de son adresse IP et, si une devise liste ce pays, bascule sur cette devise. Les pays qui ne figurent dans aucune liste reçoivent la Devise de bienvenue (Welcome currency) de l'onglet Options. Après cette première visite, le plugin mémorise la devise dans le Stockage de la devise (Currency storage) et n'applique plus les règles, de sorte qu'une devise choisie à la main par le visiteur est conservée. La configuration complète est décrite dans définir la devise selon le pays du visiteur ; cette page explique comment trouver ce qui la fait échouer.

Deux points expliquent la plupart des problèmes ci-dessous :

  • Quelle adresse est utilisée. Le plugin lit d'abord l'en-tête de requête X-Real-IP, puis la première adresse de X-Forwarded-For, puis REMOTE_ADDR, l'adresse de la machine connectée au serveur web.
  • Quelle base de données est utilisée. L'option Position géographique (Geo position) propose Open Geo IP, la base fournie avec le plugin (lib/GeoIP.dat), et GeoIP2 (MaxMind API key is required), la base GeoLite2 de MaxMind téléchargée sur votre site avec une clé gratuite de MaxMind. Avec Open Geo IP, lorsqu'une requête porte l'en-tête CF-IPCountry de Cloudflare, le plugin prend le code pays dans cet en-tête au lieu de faire sa propre recherche.

Diagnostiquer d'abord : une page de test et une vraie première visite

Créez une page avec ces deux shortcodes et excluez son URL de tous les caches de page (plugin de cache, cache serveur, Cloudflare) :

[wpcs_check_country] [wpcs_price value=10]

[wpcs_check_country] affiche Your current country is: Germany, Code: DE. Il effectue une nouvelle recherche à chaque affichage de page et ignore la devise mémorisée : il ne répond donc qu'à une seule question, celle de savoir si le pays est le bon. Le montant de [wpcs_price] montre quelle devise est active pour vous. Sans l'exclusion du cache, la ligne du pays elle-même est mise en cache et affiche le pays de la première personne qui a chargé la page.

Pour vérifier aussi la devise, chaque test doit être une première visite, et ce qui compte comme un nouveau visiteur dépend du Stockage de la devise (Currency storage) :

Stockage de la deviseLe visiteur est mémorisé parUne vraie première visite pour tester
transient (par défaut)L'adresse IP, pendant un jourUne autre connexion (VPN, données mobiles). Une fenêtre privée sur la même connexion n'est pas nouvelle.
cookieLe cookie wpcs_guest_id, pendant un jourUne nouvelle fenêtre privée. Activer un VPN dans la même fenêtre n'est pas nouveau.
sessionLe cookie de session PHPUne nouvelle fenêtre privée. Activer un VPN dans la même fenêtre n'est pas nouveau.

Activer ou désactiver un VPN dans un navigateur qui a déjà visité le site est la fausse alerte la plus courante : la ligne du pays change, la devise non, et c'est le comportement voulu. Un service web qui charge votre page depuis plusieurs pays donne le résultat le plus réaliste. Comparez maintenant ce qu'affiche la page de test avec ce tableau :

Ce qu'affiche la page de testCause
Le même pays à chaque test, souvent celui de votre serveur ou de votre CDNLe serveur transmet une seule IP pour tous les visiteurs
États-Unis à chaque testPHP voit l'adresse de bouclage d'un proxy local
Le bon pays, mais le prix reste dans la devise de bienvenueCe n'est pas une première visite, la page vient du cache, ou aucune règle n'existe pour ce pays
Nom et code videsAucune adresse exploitable, ou un visiteur en IPv6 avec Open Geo IP
DB is empty. Please download the database. avec le code errorGeoIP2 est sélectionné mais sa base n'a jamais été téléchargée
Europe ou Asia/Pacific RegionLa base fournie ne connaît que la région pour cette adresse

Tout le monde obtient le même pays : corriger la transmission de l'IP

Lorsqu'un CDN, un proxy inverse, un répartiteur de charge ou un serveur de cache (Cloudflare, Nginx devant Apache, Varnish, un proxy d'hébergeur) se trouve devant WordPress, la connexion que voit PHP provient de cette machine et non du visiteur. Tant que le serveur n'a pas reçu l'instruction de rétablir l'adresse d'origine, chaque visiteur reçoit l'adresse du proxy, donc son pays. Variante courante : Nginx est configuré pour envoyer X-Real-IP avec son propre $remote_addr, qui derrière Cloudflare est l'adresse du serveur Cloudflare. Le plugin lit cet en-tête en premier, si bien que tout le monde est détecté dans le pays du centre de données Cloudflare.

La correction se fait sur le serveur. Avec Nginx, le module real IP remplace l'adresse du proxy par celle du visiteur avant que PHP ne la voie :

# nginx.conf, inside the http {} or server {} block.
# Add one set_real_ip_from line for every range listed at https://www.cloudflare.com/ips/
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 2400:cb00::/32;
real_ip_header CF-Connecting-IP;

Sous Apache, mod_remoteip fait la même chose avec RemoteIPHeader CF-Connecting-IP et une ligne RemoteIPTrustedProxy pour les plages Cloudflare. Le guide de Cloudflare Restoring original visitor IPs présente les deux configurations. Sans Cloudflare, l'en-tête est généralement X-Forwarded-For, et l'adresse de confiance est celle de votre propre proxy. Sur un hébergement géré, vous ne pouvez pas modifier ces fichiers : demandez à l'hébergeur de rendre l'IP réelle du visiteur disponible pour PHP dans REMOTE_ADDR ou X-Real-IP. Rechargez la page de test depuis deux réseaux différents ; elle doit afficher deux pays différents.

Cloudflare : utiliser son en-tête de pays

Si le site est derrière Cloudflare, activez Géolocalisation IP (IP Geolocation) dans la section Réseau (Network) du tableau de bord Cloudflare (voir Cloudflare IP Geolocation). Cloudflare ajoute alors un en-tête CF-IPCountry à chaque requête, et avec Position géographique (Geo position) réglé sur Open Geo IP, le plugin l'utilise automatiquement. Sur la page de test, le code provient alors de Cloudflare tandis que le nom du pays vient toujours de la recherche par IP ; si les deux divergent, ce sont les codes qu'utilisent les règles. Avec GeoIP2, l'en-tête n'est pas lu, mais vous pouvez le transmettre aux règles avec le filtre wpcs_geo_position :

/*
 * WPCS: take the visitor country from Cloudflare's CF-IPCountry header.
 * Child theme functions.php or a code snippets plugin.
 */
add_filter('wpcs_geo_position', function ($country) {
    if (!empty($_SERVER['HTTP_CF_IPCOUNTRY'])) {
        $cf = strtoupper(sanitize_text_field(wp_unslash($_SERVER['HTTP_CF_IPCOUNTRY'])));
        // two-letter country codes only; XX means unknown
        if (preg_match('/^[A-Z]{2}$/', $cf) && $cf !== 'XX') {
            return $cf;
        }
    }
    return $country;
});

Le filtre modifie le pays utilisé pour choisir la devise. [wpcs_check_country] affiche toujours la recherche propre au plugin : testez donc le résultat avec le shortcode de prix et une première visite.

Chaque visiteur est détecté aux États-Unis

Lorsque Nginx ou Varnish s'exécute sur la même machine et transmet les requêtes à Apache, PHP voit l'adresse de bouclage du serveur lui-même. Le plugin considère cette adresse comme celle d'une copie de développement exécutée sur un ordinateur et la remplace par une adresse publique de test fixe, située aux États-Unis, sans lire aucun en-tête. Apache doit rétablir l'adresse du visiteur avec mod_remoteip :

# Apache 2.4 configuration, mod_remoteip enabled.
# Use the header your front proxy sends (X-Real-IP or X-Forwarded-For).
RemoteIPHeader X-Real-IP
RemoteIPInternalProxy 127.0.0.0/8

Effet secondaire : une seule devise mémorisée pour tout le monde

Le stockage transient par défaut associe sa mémoire à l'adresse IP. Tant que tous les visiteurs arrivent avec une seule adresse, ils partagent une seule mémoire : le premier visiteur de la journée décide de la devise de tous, et un visiteur qui change de devise la change aussi pour tous les autres. Corriger la transmission règle le problème. Régler le Stockage de la devise (Currency storage) sur cookie aide aussi, car chaque navigateur est alors mémorisé séparément, quelle que soit son IP.

Le pays est le bon, mais la devise ne change pas

  • Ce n'est pas une première visite. Testez à nouveau en suivant le tableau des stockages ci-dessus.
  • Une page en cache. Un cache de page sert du HTML stocké, et l'étape GeoIP ne s'exécute jamais pour le visiteur suivant. Dans l'onglet Options, réglez J'utilise un plugin de cache sur mon site (I am using cache plugin on my site) sur Oui (Yes). Les prix affichés par [wpcs_price] sont alors redessinés après le chargement de la page par une requête AJAX (wpcs_get_prices_html) exécutée pour le visiteur courant, règles GeoIP comprises, et le sélecteur est réglé sur la devise renvoyée. Videz toutes les couches de cache après avoir modifié l'option ; si les prix ne se mettent toujours pas à jour, voir le sélecteur de devises ne fonctionne pas avec un plugin de cache.
  • Aucune règle pour ce pays. Les règles ne contiennent que des pays ; il n'existe pas d'entrée Europe, ajoutez donc chaque pays à sa devise. Un pays listé sous deux devises va à la première.
  • Les prix fixes. [wpcs_price type="fixed" value="USD:15,GBP:45"] affiche none pour une devise absente de value. Les guillemets typographiques (”) collés depuis un traitement de texte cassent aussi les attributs ; saisissez des guillemets droits.
  • Montants erronés après le changement. La devise de base de l'onglet Devises (Currencies) doit avoir le taux 1 ; les conversions sont calculées à partir d'elle.

Pays vide ou erroné pour certains visiteurs

  • Vide pour certains visiteurs. La recherche Open Geo IP ne gère que les adresses IPv4. Les visiteurs qui atteignent le serveur en IPv6, fréquent sur les réseaux mobiles, n'obtiennent aucun pays. GeoIP2 gère les deux. Vide pour tout le monde signifie que l'adresse reçue par PHP est absente ou appartient à un réseau privé (un conteneur ou un répartiteur de charge) : corrigez la transmission comme indiqué plus haut.
  • Europe ou Asia/Pacific Region. Aucune règle de pays ne peut correspondre. Passez à GeoIP2.
  • Mauvais pays. Les plages d'adresses changent de propriétaire, et les mises à jour du plugin apportent une copie plus récente de la base fournie : mettez d'abord le plugin à jour. Pour une meilleure précision, sélectionnez GeoIP2 (MaxMind API key is required) dans Position géographique (Geo position), collez une clé gratuite de votre compte MaxMind GeoLite2 dans Clé de licence MaxMind (MaxMind license key) et cliquez sur Enregistrer les options (Save options). Le bouton Mettre à jour/télécharger la base (Update/Download DB) n'apparaît qu'une fois la clé enregistrée ; cliquez dessus et attendez Database downloaded successfully. Le fichier est stocké sous wp-content/uploads/currency-switcher/GeoLite2-Country.mmdb et n'est pas actualisé automatiquement : cliquez à nouveau sur le bouton tous les quelques mois.
  • GeoIP2 moins bon qu'Open Geo IP. Le fichier de base est absent ou ancien. Téléchargez-le à nouveau, ou revenez à Open Geo IP.
  • Tests avec VPN. Le serveur de sortie d'un VPN peut être enregistré dans un autre pays que celui affiché par l'application VPN. Comparez avec une seconde source de test avant de modifier des réglages.

Si le serveur ne peut pas transmettre l'adresse du visiteur et que le site n'est pas derrière Cloudflare, GeoIP ne peut pas fonctionner. Supprimez alors les règles, réglez la Devise de bienvenue (Welcome currency) sur la devise que la plupart de vos visiteurs utilisent, et laissez-les choisir avec le sélecteur [wpcs].

Liste de contrôle

  • La page de test est exclue de tous les caches et affiche des pays différents et corrects depuis deux réseaux.
  • Le serveur transmet la vraie IP du visiteur, ou Géolocalisation IP (IP Geolocation) de Cloudflare est activée avec Open Geo IP.
  • Avec GeoIP2 : la clé est enregistrée et la base a été téléchargée.
  • Chaque test était une vraie première visite pour le Stockage de la devise (Currency storage) sélectionné.
  • J'utilise un plugin de cache sur mon site (I am using cache plugin on my site) est sur Oui (Yes) sur un site en cache, et tous les caches ont été vidés.
  • Chaque pays est listé sous sa devise, et le taux de la devise de base est 1.

Si tout cela est vérifié et que les visiteurs reçoivent encore la mauvaise devise, ouvrez un sujet sur le forum d'assistance WPCS avec le lien de votre page de test, vos réglages Position géographique (Geo position) et Stockage de la devise (Currency storage) et le cache ou CDN que vous utilisez.