FOX - WooCommerce Currency Switcher Professional

WooCommerce-Währungsumschalter hinter Cloudflare: APO, Cache und GeoIP

Ein WooCommerce-Währungsumschalter hinter Cloudflare hängt von zwei Dingen ab: davon, welche Seiten Cloudflare cacht und als fertiges HTML ausliefert, und davon, was es WordPress über den Besucher mitteilt. Ist eines von beiden falsch, sehen die Symptome ähnlich aus: Alle bekommen dieselbe Währung, der Umschalter scheint nichts zu tun, Cloudflare APO hört auf, den Shop zu cachen, oder GeoIP-Regeln wählen das falsche Land. Dies ist die Cloudflare-spezifische Konfiguration für FOX; den allgemeinen Konflikt zwischen Preisen und Seiten-Caches erklärt warum sich ein Währungsumschalter und ein Seiten-Cache gegenseitig bekämpfen.

Was Cloudflare mit Ihren Shop-Seiten macht

Finden Sie zuerst heraus, welche von drei Konfigurationen Sie haben, denn die Lösungen unterscheiden sich.

KonfigurationHTML-Seiten bei Cloudflare gecacht?Was für FOX zählt
Nur Proxy (orange Wolke, Standard-Caching)Nein. Cloudflare cacht HTML standardmäßig nicht, nur statische Dateien wie CSS, JavaScript und Bilder.Die IP-Adresse und das Land des Besuchers, die WordPress erreichen. Ein Cache-Plugin auf dem Server ist eine separate Frage.
Cache-Regeln, die HTML cachefähig machenJa, eine Kopie pro URL für alle.Der FOX-Cache-Modus, ein Speicher ohne Cookies und die richtigen Ausnahmen.
APO (Automatic Platform Optimization for WordPress)Ja, am Edge.Dasselbe wie bei Cache-Regeln, plus die eigenen Regeln von APO für Cookies und Query-Strings.

Um zu sehen, was mit einer Seite geschieht, öffnen Sie eine Kategorieseite zweimal in einem privaten Fenster, bei geöffnetem Tab „Netzwerk“ der Entwicklertools, und lesen die Antwort-Header der Seitenanfrage selbst:

  • cf-cache-status: HIT bedeutet, dass die Seite aus dem Cache von Cloudflare kam; MISS, EXPIRED oder BYPASS bedeuten, dass WordPress sie erzeugt hat; DYNAMIC bedeutet, dass Cloudflare sie überhaupt nicht für cachefähig hält.
  • Bei APO bedeutet cf-apo-via: cache, dass die Seite aus dem APO-Cache kam; jeder Wert, der mit origin beginnt, bedeutet, dass APO sie von Ihrem Server geholt hat.
  • Ein set-cookie-Header in der Seitenantwort ist der übliche Grund, warum eine Seite, die gecacht werden sollte, nie gecacht wird.

Im Terminal gibt curl -s -o /dev/null -D - https://example.com/product-category/shoes/ dieselben Header einer normalen GET-Anfrage aus; führen Sie den Befehl zweimal aus.

Einstellungen des Währungsumschalters für Cloudflare APO und gecachtes HTML

Wenn Cloudflare HTML cacht, erreicht dieselbe Kopie einer Seite alle, daher muss FOX die Preise im Browser korrigieren und darf nichts Persönliches in die Seitenantwort schreiben. In den FOX-Einstellungen (WooCommerce → Einstellungen → Währung), Tab Optionen (Options):

  1. Währungsspeicherung (Currency storage) = Transient. FOX-Sitzung (FOX Session) setzt bei der ersten Antwort an einen Besucher ein Sitzungs-Cookie (wp_woocs_session_…), und PHP-Sitzung (PHP Session) setzt ebenfalls eines, wobei die Sitzungsverwaltung von PHP zusätzlich die Header Cache-Control: no-store, no-cache hinzufügt. Cloudflare speichert keine Antwort, die ein Cookie setzt oder das Caching verbietet. Bei beiden Sitzungsspeichern kommen die Seiten daher weiter von Ihrem Server, und die APO-Trefferquote bricht ein: cf-apo-via: origin,resnok in den Headern. Transient setzt kein Cookie. Das Umbenennen des Sitzungs-Cookies mit dem Filter woocs_cookie ändert daran nichts: Die erste Antwort trägt weiterhin einen Set-Cookie-Header.
  2. Ich verwende ein Cache-Plugin auf meiner Website (I am using cache plugin on my site) = Ja. FOX zeichnet dann die Preise in der Währung des Besuchers neu, nachdem die gecachte Seite geladen wurde. Zusammen mit Transient aktiviert es außerdem den Browser-Schlüssel-Modus (seit FOX 2.5.0): Der Browser hält einen zufälligen Schlüssel im localStorage und sendet ihn mit jQuery-AJAX-Anfragen (Parameter woocs_sk) und mit fetch()-Anfragen derselben Herkunft wie bei der Block-Kasse und den PayPal-Buttons (Header X-WOOCS-SK). Der Schlüssel erscheint nie in einer Seiten-URL und teilt den Cache daher nicht pro Besucher auf. Halten Sie FOX aktuell: Die ersten Builds dieses Modus sendeten den Schlüssel nur mit jQuery-Anfragen, sodass über fetch() erzeugte PayPal-Bestellungen in der Basiswährung entstanden und mit CANNOT_MIX_CURRENCIES fehlschlugen.
  3. Keine GET-Daten im Link (No GET data in link) = Nein. Im Browser-Schlüssel-Modus speichert ein Wechsel zuerst die Währung für den Browser-Schlüssel und öffnet dann die Seite mit ?currency= in der Adresse. Diese Anfrage geht an Ihren Server (APO cacht sie nie, siehe unten), der die Seite in der neuen Währung rendert und sie außerdem unter der IP-Adresse des Besuchers speichert, dem Schlüssel, den FOX für Seiten ohne AJAX verwendet, etwa eine klassische Warenkorbseite.

Preis-Preloader (Prices preloader) macht hier kaum einen Unterschied: In FOX 2.5.5 wird seine Ladeanimation entfernt, sobald die Neuzeichnen-Anfrage gesendet wird, nicht erst, wenn die Antwort eintrifft. Den kurzen Moment, in dem die gecachten Preise sichtbar sind, verdeckt er daher nicht.

APO bringt eigene Regeln mit. Es umgeht den Cache für Besucher, die Cookies mit den Präfixen wp-, wordpress, woocommerce_ und einigen weiteren tragen, sodass angemeldete Benutzer und Besucher mit etwas im Warenkorb ohnehin frische Seiten erhalten. Es umgeht den Cache außerdem für jede URL mit einem Query-Parameter außerhalb seiner kurzen Erlaubnisliste von Tracking-Parametern. Für einen Shop mit mehreren Währungen folgen daraus zwei Dinge:

  • Links mit ?currency=EUR erreichen immer Ihren Server, und genau das braucht der Währungswechsel.
  • Die WooCommerce-Einstellung Standard-Kundenstandort (Default customer location) = Geolokalisieren (mit Seitencache-Unterstützung) (Geolocate (with page caching support)) fügt Shop-URLs einen ?v=-Parameter hinzu, und APO liefert keine dieser URLs aus seinem Cache aus. FOX braucht diese Einstellung nicht: Es fragt WooCommerce direkt nach dem Land, unabhängig davon, was bei Standard-Kundenstandort (Default customer location) steht, und tut das auf einer gecachten Seite in der Neuzeichnen-Anfrage (mit einer Lücke, die das Snippet weiter unten schließt). Wählen Sie bei APO Geolokalisieren (Geolocate) oder Shop-Basisadresse (Shop base address), je nachdem, wie WooCommerce Steuern und Versand schätzen soll.

Cache-Regeln: was auszuschließen ist

Mit Cache-Regeln bestimmen Sie selbst, was Cloudflare speichert, und eine zu weit gefasste Regel verursacht die schlimmsten Währungsprobleme: Ein gecachter Warenkorb oder eine gecachte Kasse zeigt die Summen eines Besuchers einem anderen. Halten Sie Folgendes mit einer Regel auf Cache umgehen (Bypass cache) aus dem Cache heraus oder nehmen Sie es aus Ihrer Caching-Regel aus:

  • die Seiten Warenkorb, Kasse und Mein Konto (mit Ihren eigenen Seiten-Slugs) und /wp-admin/;
  • /wp-json/ und Anfragen mit wc-ajax= im Query-String;
  • URLs, deren Query-String currency= enthält, damit ein Währungswechsel immer von WordPress bearbeitet wird.

Setzen Sie bei der Regel, die Shop-Seiten cacht, Edge-TTL (Edge TTL) auf eine der Optionen, die den Cache-Control-Header verwenden, falls vorhanden. WooCommerce sendet No-Cache-Header auf den Seiten, die in seinen Einstellungen als Warenkorb-, Kassen- und Mein-Konto-Seite festgelegt sind (eine Kasse, die ein Funnel-Plugin auf einer anderen Seite aufbaut, bekommt keine). Mit Cache-Control-Header ignorieren und diese TTL verwenden (Ignore cache-control header and use this TTL) würde Cloudflare sie trotzdem cachen, falls Ihre Regel sie versehentlich erfasst. Die eigenen Anfragen von FOX an admin-ajax.php sind POST-Anfragen, die Cloudflare nicht cacht.

Falsches Land oder eine Währung für alle

FOX hat keine eigene Geolokalisierungsdatenbank. Es ruft WC_Geolocation::geolocate_ip() auf, wendet seine GeoIP-Regeln auf das Land an, das WooCommerce zurückgibt, und tut dies einmal pro Besucher. Wenn WordPress eine Seite rendert, geschieht das in PHP; bei einer Seite, die aus dem Cache von Cloudflare ausgeliefert wird, kann es nur in der Neuzeichnen-Anfrage geschehen, einem POST an admin-ajax.php, der immer Ihren Server erreicht. Die Geolokalisierung hinter Cloudflare braucht also drei Dinge: das richtige Land bei jeder Anfrage, die richtige Besucheradresse und ein Neuzeichnen, das die Regeln anwendet. Um zu sehen, was WooCommerce erkennt, setzen Sie [woocs_geo_hello] auf eine ungecachte Testseite; das vollständige Vorgehen steht in Die WooCommerce-Geolokalisierung zeigt die falsche Währung.

Cloudflare das Land senden lassen

Aktivieren Sie IP-Geolokalisierung (IP Geolocation) in den Einstellungen unter Netzwerk (Network) Ihrer Cloudflare-Zone oder die Managed Transform Besucherstandort-Header hinzufügen (Add visitor location headers), die sie einschließt. Cloudflare fügt dann jeder Anfrage einen CF-IPCountry-Header hinzu, und WooCommerce liest ihn (als HTTP_CF_IPCOUNTRY, neben einigen weiteren Server-Variablen für das Land), bevor es eine IP-Abfrage versucht. Für die GeoIP-Regeln von FOX sind dann weder ein MaxMind-Schlüssel noch Code nötig. Der alte Rat, das Land von Cloudflare über den Filter woocommerce_geolocate_ip einzuspeisen, ist heute überflüssig; behalten Sie diesen Filter für Länderquellen, die WooCommerce nicht kennt. Es gibt zwei Sonderwerte: XX für Adressen ohne Länderdaten und T1 für das Tor-Netzwerk. Keiner von beiden trifft eine GeoIP-Regel, sodass diese Besucher die Willkommenswährung (Welcome currency) erhalten.

Die IP-Adresse des Besuchers wiederherstellen

WordPress braucht weiterhin die echte Besucheradresse: FOX legt den Transient-Speicher für Seiten ohne AJAX (und bei ausgeschalteter Cache-Option für alles) nach der IP ab, und WooCommerce greift auf die IP zurück, wenn kein Länder-Header eintrifft. Hinter Cloudflare kommt die Verbindung von einer Cloudflare-Adresse; die Adresse des Besuchers wird in den Headern CF-Connecting-IP und X-Forwarded-For übertragen.

  • FOX liest CF-Connecting-IP selbst, sodass sein Speicher den Besucher auch dann sieht, wenn sonst nichts konfiguriert ist.
  • WooCommerce liest zuerst X-Real-IP, dann X-Forwarded-For, dann die Verbindungsadresse. Ein häufiger Fehler ist ein nginx-Proxy vor Apache, der X-Real-IP mit der Adresse der Verbindung weitergibt, die hinter Cloudflare ein Cloudflare-Server ist. Ohne den Länder-Header schlägt WooCommerce dann die Adresse von Cloudflare nach statt die des Besuchers, und die meisten Besucher erhalten dasselbe Land, oft die Vereinigten Staaten.
  • Die Lösung liegt auf Serverebene: das Real-IP-Modul von nginx mit set_real_ip_from für jeden Cloudflare-Bereich und real_ip_header CF-Connecting-IP; oder mod_remoteip von Apache mit RemoteIPHeader CF-Connecting-IP und RemoteIPTrustedProxy-Zeilen. Cloudflare veröffentlicht seine Bereiche und die vollständige Anleitung unter Wiederherstellung der ursprünglichen Besucher-IPs; bei Managed Hosting bitten Sie den Hoster, es einzurichten.
  • Lassen Sie die Managed Transform Besucher-IP-Header entfernen (Remove visitor IP headers) ausgeschaltet. Sie entfernt CF-Connecting-IP, und FOX greift dann auf dieselben Header zurück wie WooCommerce: Auf einem Server wie dem eben beschriebenen teilen sich Besucher, die über dieselbe Cloudflare-Adresse kommen, auf serverseitig gerenderten Seiten eine gespeicherte Währung.

GeoIP-Regeln auf gecachten Seiten

In FOX 2.5.5 vergleicht die Neuzeichnen-Anfrage zuerst die Währung der gecachten Kopie mit der aktuellen Währung des Besuchers, und wenn sie gleich sind, antwortet sie „nichts zu ändern“, ohne den GeoIP-Schritt zu erreichen. Ein neuer Besucher startet in der Willkommenswährung (Welcome currency), daher werden auf jeder in der Willkommenswährung (Welcome currency) gecachten Seite die GeoIP-Regeln übersprungen: Bei einer Regel Deutschland → EUR behält ein deutscher Besucher die Willkommenswährung (Welcome currency) und bekommt Euro erst auf der ersten Seite, die zufällig in einer anderen Währung gecacht ist. Das ist das Muster „GeoIP funktioniert nur auf manchen Seiten“ hinter einem Full-Page-Cache. Das folgende Snippet führt den GeoIP-Schritt vor dem Vergleich aus, einmal pro Besucher, und lässt eine im Umschalter gewählte Währung gewinnen:

<?php
/**
 * FOX behind a full-page cache (Cloudflare APO or Cache Rules):
 * apply the GeoIP rules in a new visitor's first price redraw,
 * also when the cached copy is already in the Welcome currency.
 * Add to the child theme's functions.php or a code snippets plugin.
 */
function my_fox_geoip_in_redraw() {
    global $WOOCS;
    if ( ! is_object( $WOOCS ) || empty( $WOOCS->storage ) ) {
        return;
    }
    // Once per visitor: FOX sets this flag when it has applied the GeoIP rules.
    if ( ! intval( $WOOCS->storage->get_val( 'woocs_first_unique_geoip' ) ) ) {
        $WOOCS->init_geo_currency();
    }
}

function my_fox_geoip_after_manual_choice() {
    global $WOOCS;
    // A currency chosen in the switcher before the first redraw must win.
    if ( is_object( $WOOCS ) && ! empty( $WOOCS->storage ) ) {
        $WOOCS->storage->set_val( 'woocs_first_unique_geoip', 1 );
    }
}

foreach ( array( 'woocs_get_products_price_html', 'woocs_get_variation_products_price_html', 'woocs_get_custom_price_html' ) as $my_fox_action ) {
    add_action( 'wp_ajax_' . $my_fox_action, 'my_fox_geoip_in_redraw', 1 );
    add_action( 'wp_ajax_nopriv_' . $my_fox_action, 'my_fox_geoip_in_redraw', 1 );
}
add_action( 'wp_ajax_woocs_set_currency_ajax', 'my_fox_geoip_after_manual_choice', 1 );
add_action( 'wp_ajax_nopriv_woocs_set_currency_ajax', 'my_fox_geoip_after_manual_choice', 1 );

Lassen Sie die einleitende Zeile <?php weg, wenn Ihre Datei bereits eine hat. Die eigenen Neuzeichnen-Handler von FOX laufen mit der Standardpriorität 10, dieser Code läuft also zuerst, und der Vergleich sieht dann die Währung der GeoIP-Regel des Besuchers. Das Neuzeichnen läuft nur auf Seiten mit Produktpreisen, ein Besucher, der auf einem Blogbeitrag landet, erhält die GeoIP-Währung also auf der ersten Shop-Seite. Zum Testen leeren Sie den Cloudflare-Cache, laden eine Kategorieseite aus einem Land ohne GeoIP-Regel, bis sie in der Willkommenswährung (Welcome currency) gecacht ist (ein HIT), und öffnen sie dann über ein VPN aus einem Land mit einer Regel in einem Browserprofil, das den Shop noch nie besucht hat: Die Preise müssen in die Währung dieses Landes wechseln. Mit den obigen Einstellungen entscheidet der Browser-Schlüssel, nicht die IP-Adresse, wer ein neuer Besucher ist.

Nach jeder Änderung leeren und testen

Eine gecachte Seite behält die Preise, mit denen sie erzeugt wurde, und das Neuzeichnen von FOX ersetzt sie nur, wenn sich die Währung des Besuchers von der der gecachten Kopie unterscheidet. Wenn Sie in FOX Währungen, Kurse, Dezimalstellen oder Symbole ändern, sehen Besucher, deren Währung zu einer gecachten Kopie passt, die alten Beträge, bis diese Kopie abläuft. Das Cloudflare-WordPress-Plugin leert APO-Seiten, wenn Sie Inhalte bearbeiten, nicht aber, wenn sich FOX-Einstellungen oder Kurse ändern. Verwenden Sie nach solchen Änderungen daher Alles bereinigen (Purge Everything) in der Caching-Konfiguration von Cloudflare und leeren Sie den Cache des Cache-Plugins auf Ihrem Server. Bei automatischen Kursaktualisierungen und Cache-Regeln hält eine Edge-TTL (Edge TTL), die nicht länger als das Aktualisierungsintervall ist, die umgerechneten Preise aktuell; bei APO leeren Sie den Cache nach großen Kursbewegungen.

Testen Sie dann in dieser Reihenfolge:

  1. Führen Sie den obigen curl-Befehl für eine Kategorieseite zweimal aus: Die zweite Antwort zeigt cf-cache-status: HIT (bei APO zusätzlich cf-apo-via: cache) und keinen set-cookie-Header.
  2. Öffnen Sie die Seite in zwei Browsern, die den Shop noch nie besucht haben. Wechseln Sie in einem die Währung: Sie ändert sich dort, und der andere behält nach einem Neuladen seine eigene Währung.
  3. Legen Sie in der zweiten Währung ein Produkt in den Warenkorb und gehen Sie zur Kasse: Die Summen bleiben in dieser Währung.
  4. Wenn etwas fehlschlägt, nehmen Sie den Cache von Cloudflare aus dem Test: Schalten Sie APO oder Ihre Cache-Regel kurz aus oder aktivieren Sie den Entwicklungsmodus (Development Mode) in der Caching-Konfiguration, der das Edge-Caching für drei Stunden aussetzt, leeren Sie dann den Cache und wiederholen Sie den Test. Bleibt das Problem bestehen, liegt die Ursache auf Ihrem Server, etwa bei einem Cache-Plugin, einem Server-Cache oder einem JavaScript-Optimierer, nicht bei Cloudflare. Die eigene Skriptoptimierung von Cloudflare, Rocket Loader, verzögert Skripte wie diese Optimierer; wenn sich die Preise weiter drehen, testen Sie mit ausgeschaltetem Rocket Loader und lesen Sie Währungsumschalter hängt nach JS-Optimierung beim Laden.

Checkliste

  • Sie wissen anhand der Antwort-Header, ob Cloudflare Ihr HTML cacht (nur Proxy, Cache-Regeln oder APO).
  • Bei gecachtem HTML: Währungsspeicherung (Currency storage) = Transient, Ich verwende ein Cache-Plugin auf meiner Website (I am using cache plugin on my site) = Ja, Keine GET-Daten im Link (No GET data in link) = Nein, FOX auf dem aktuellen Stand.
  • Warenkorb, Kasse, Konto, /wp-json/, wc-ajax und currency=-URLs werden nie gecacht; Edge-TTL (Edge TTL) respektiert Cache-Control.
  • Bei APO: Standard-Kundenstandort (Default customer location) nicht auf die Variante mit Seitencache-Unterstützung gesetzt.
  • IP-Geolokalisierung (IP Geolocation) an; echte Besucher-IP auf dem Server wiederhergestellt; Besucher-IP-Header entfernen (Remove visitor IP headers) aus.
  • Bei GeoIP-Regeln und gecachten Seiten: das Neuzeichnen-Snippet eingesetzt.
  • Cloudflare- und Server-Caches nach Änderungen an FOX-Einstellungen oder Kursen geleert.

Ist die Währung trotz allem weiterhin falsch, eröffnen Sie im FOX-Support-Forum ein Thema mit einem Seitenlink, den Antwort-Headern dieser Seite und Ihren FOX-Einstellungen für Speicher und Cache, und wir sehen es uns an.