Selector de moneda de WooCommerce con Cloudflare: APO, caché y GeoIP
Un selector de moneda de WooCommerce detrás de Cloudflare depende de dos cosas: qué páginas guarda Cloudflare en caché y entrega como HTML terminado, y qué le dice a WordPress sobre el visitante. Cuando una de las dos falla, los síntomas se parecen: todos reciben la misma moneda, el selector parece no hacer nada, Cloudflare APO deja de guardar la tienda en caché o las reglas GeoIP eligen el país equivocado. Esta es la configuración de FOX específica para Cloudflare; el conflicto general entre precios y cachés de páginas se explica en por qué un selector de moneda y una caché de páginas se enfrentan.
Qué hace Cloudflare con las páginas de tu tienda
Empieza por averiguar cuál de las tres configuraciones tienes, porque las soluciones difieren.
| Configuración | ¿Páginas HTML en caché en Cloudflare? | Qué importa para FOX |
|---|---|---|
| Solo proxy (nube naranja, caché por defecto) | No. Cloudflare no guarda HTML en caché por defecto, solo archivos estáticos como CSS, JavaScript e imágenes. | Que la dirección IP y el país del visitante lleguen a WordPress. Un plugin de caché en el servidor es otra cuestión. |
| Cache Rules que hacen el HTML apto para caché | Sí, una copia por URL para todos. | El modo de caché de FOX, un almacenamiento sin cookies y las exclusiones correctas. |
| APO (Automatic Platform Optimization for WordPress) | Sí, en el borde. | Lo mismo que con Cache Rules, más las reglas propias de APO para cookies y cadenas de consulta. |
Para ver qué ocurre con una página, abre una página de categoría dos veces en una ventana privada, con la pestaña Network de las herramientas de desarrollo abierta, y lee las cabeceras de respuesta de la propia solicitud de la página:
cf-cache-status: HITsignifica que la página vino de la caché de Cloudflare;MISS,EXPIREDoBYPASSsignifican que la construyó WordPress;DYNAMICsignifica que Cloudflare no la considera almacenable en absoluto.- Con APO,
cf-apo-via: cachesignifica que la página vino de la caché de APO; cualquier valor que empiece pororiginsignifica que APO la obtuvo de tu servidor. - Una cabecera
set-cookieen la respuesta de la página es el motivo habitual por el que una página que debería estar en caché nunca lo está.
Desde una terminal, curl -s -o /dev/null -D - https://example.com/product-category/shoes/ imprime las mismas cabeceras de una solicitud GET normal; ejecútalo dos veces.
Ajustes del selector de moneda para Cloudflare APO y HTML en caché
Cuando Cloudflare guarda HTML en caché, la misma copia de una página llega a todos, así que FOX tiene que corregir los precios en el navegador y no debe poner nada personal en la respuesta de la página. En los ajustes de FOX (WooCommerce → Ajustes → Currency), pestaña Opciones (Options):
- Almacenamiento de moneda (Currency storage) = Transitorio (Transient). Sesión FOX (FOX Session) establece una cookie de sesión (
wp_woocs_session_…) en la primera respuesta a un visitante, y Sesión PHP (PHP Session) también establece una, mientras que la gestión de sesiones de PHP además añade las cabecerasCache-Control: no-store, no-cache. Cloudflare no guarda una respuesta que establece una cookie o que prohíbe el almacenamiento en caché, así que con cualquiera de los dos almacenamientos de sesión las páginas siguen viniendo de tu servidor y la tasa de aciertos de APO se hunde:cf-apo-via: origin,resnoken las cabeceras. Transitorio (Transient) no establece ninguna cookie. Renombrar la cookie de sesión con el filtrowoocs_cookieno cambia esto: la primera respuesta sigue llevando una cabeceraSet-Cookie. - Estoy usando un complemento de caché en mi sitio (I am using cache plugin on my site) = Sí. FOX redibuja entonces los precios en la moneda del visitante después de que se cargue la página en caché. Junto con Transitorio (Transient), también activa el modo de clave de navegador (desde FOX 2.5.0): el navegador guarda una clave aleatoria en localStorage y la envía con las solicitudes AJAX de jQuery (el parámetro
woocs_sk) y con las solicitudesfetch()del mismo origen, como el checkout por bloques y los botones de PayPal (la cabeceraX-WOOCS-SK). La clave nunca aparece en la URL de una página, así que no divide la caché por visitante. Mantén FOX actualizado: las primeras versiones de este modo enviaban la clave solo con las solicitudes de jQuery, de modo que los pedidos de PayPal creados mediantefetch()salían en la moneda base y fallaban conCANNOT_MIX_CURRENCIES. - No hay datos GET en el enlace (No GET data in link) = No. En el modo de clave de navegador, un cambio primero guarda la moneda para la clave del navegador y después abre la página con
?currency=en la dirección. Esa solicitud va a tu servidor (APO nunca la guarda en caché, ver más abajo), que renderiza la página en la nueva moneda y además la guarda con la dirección IP del visitante, la clave que FOX usa para las páginas renderizadas sin AJAX, como una página de carrito clásica.
Precargador de precios (Prices preloader) apenas influye aquí: en FOX 2.5.5 su animación de carga se elimina en cuanto se envía la solicitud de redibujo, no cuando llega la respuesta, así que no oculta el breve momento en que se ven los precios en caché.
APO añade reglas propias. Omite la caché para los visitantes que llevan cookies que empiezan por wp-, wordpress, woocommerce_ y algunos prefijos más, de modo que los usuarios con sesión iniciada y los visitantes con algo en el carrito reciben páginas actualizadas de todos modos. También omite la caché para cualquier URL con un parámetro de consulta fuera de su breve lista de parámetros de seguimiento permitidos. Dos consecuencias para una tienda con varias monedas:
- Los enlaces con
?currency=EURsiempre llegan a tu servidor, que es lo que necesita el cambio de moneda. - La opción de WooCommerce Ubicación predeterminada del cliente (Default customer location) = Geolocalizar (con soporte de caché de páginas) (Geolocate (with page caching support)) añade un parámetro
?v=a las URL de la tienda, y APO no sirve ninguna de esas URL desde su caché. FOX no necesita este ajuste: pide a WooCommerce el país directamente, diga lo que diga Ubicación predeterminada del cliente (Default customer location), y en una página en caché lo hace en la solicitud de redibujo (con un hueco, que cierra el fragmento más abajo). Con APO, elige Geolocalizar (Geolocate) o Dirección base de la tienda (Shop base address) según cómo quieras que WooCommerce estime los impuestos y el envío.
Cache Rules: qué excluir
Con Cache Rules decides tú qué guarda Cloudflare, y una regla demasiado amplia causa los peores problemas de moneda: un carrito o un checkout en caché muestra los totales de un visitante a otro. Mantén esto fuera de la caché con una regla configurada como Omitir caché (Bypass cache), o exclúyelo de tu regla de caché:
- las páginas de carrito, finalizar compra y mi cuenta (usa los slugs de tus propias páginas) y
/wp-admin/; /wp-json/y las solicitudes conwc-ajax=en la cadena de consulta;- las URL cuya cadena de consulta contiene
currency=, para que un cambio de moneda lo gestione siempre WordPress.
En la regla que guarda en caché las páginas de la tienda, configura TTL de borde (Edge TTL) en una de las opciones que usan la cabecera Cache-Control si está presente. WooCommerce envía cabeceras no-cache en las páginas definidas como carrito, finalizar compra y mi cuenta en sus ajustes (un checkout construido en otra página por un plugin de embudos no recibe ninguna), y con Ignorar el encabezado cache-control y usar este TTL (Ignore cache-control header and use this TTL) Cloudflare las guardaría en caché de todos modos si tu regla las incluye por error. Las solicitudes propias de FOX a admin-ajax.php son solicitudes POST, que Cloudflare no guarda en caché.
País equivocado o una sola moneda para todos
FOX no tiene una base de datos de geolocalización propia. Llama a WC_Geolocation::geolocate_ip(), aplica sus reglas GeoIP al país que devuelve WooCommerce y lo hace una vez por visitante. Cuando WordPress renderiza una página, eso ocurre en PHP; en una página servida desde la caché de Cloudflare solo puede ocurrir en la solicitud de redibujo, un POST a admin-ajax.php que siempre llega a tu servidor. Por eso la geolocalización detrás de Cloudflare necesita tres cosas: el país correcto en cada solicitud, la dirección correcta del visitante y un redibujo que aplique las reglas. Para ver lo que detecta WooCommerce, coloca [woocs_geo_hello] en una página de prueba sin caché; el procedimiento completo está en la geolocalización de WooCommerce muestra la moneda equivocada.
Deja que Cloudflare envíe el país
Activa Geolocalización de IP (IP Geolocation) en los ajustes de Red (Network) de tu zona de Cloudflare, o la Managed Transform Añadir encabezados de ubicación del visitante (Add visitor location headers), que la incluye. Cloudflare añade entonces una cabecera CF-IPCountry a cada solicitud, y WooCommerce la lee (como HTTP_CF_IPCOUNTRY, entre algunas variables de servidor de país) antes de intentar cualquier búsqueda por IP. Entonces no hacen falta ni clave de MaxMind ni código para las reglas GeoIP de FOX. El antiguo consejo de pasar el país de Cloudflare mediante el filtro woocommerce_geolocate_ip hoy es innecesario; conserva ese filtro para fuentes de país que WooCommerce no conoce. Existen dos valores especiales: XX para direcciones sin datos de país y T1 para la red Tor. Ninguno coincide con una regla GeoIP, así que esos visitantes reciben la Moneda de bienvenida (Welcome currency).
Restaura la dirección IP del visitante
WordPress sigue necesitando la dirección real del visitante: FOX indexa el almacenamiento Transitorio (Transient) por IP para las páginas renderizadas sin AJAX (y para todo cuando la opción de caché está desactivada), y WooCommerce recurre a la IP cuando no llega ninguna cabecera de país. Detrás de Cloudflare, la conexión viene de una dirección de Cloudflare; la dirección del visitante viaja en las cabeceras CF-Connecting-IP y X-Forwarded-For.
- FOX lee
CF-Connecting-IPpor sí mismo, así que su almacenamiento ve al visitante aunque no se haya configurado nada más. - WooCommerce lee primero
X-Real-IP, despuésX-Forwarded-Fory por último la dirección de la conexión. Un fallo frecuente es un proxy nginx delante de Apache que pasaX-Real-IPcon la dirección de la conexión, que detrás de Cloudflare es un servidor de Cloudflare. Sin la cabecera de país, WooCommerce busca entonces la dirección de Cloudflare en lugar de la del visitante, y la mayoría de los visitantes reciben el mismo país, a menudo Estados Unidos. - La solución está a nivel de servidor: el módulo real IP de nginx con
set_real_ip_frompara cada rango de Cloudflare yreal_ip_header CF-Connecting-IP;, omod_remoteipde Apache conRemoteIPHeader CF-Connecting-IPy líneasRemoteIPTrustedProxy. Cloudflare publica sus rangos y las instrucciones completas en restaurar las IP originales de los visitantes; en un alojamiento gestionado, pide al proveedor que lo configure. - Deja desactivada la Managed Transform Eliminar encabezados de IP del visitante (Remove visitor IP headers). Elimina
CF-Connecting-IP, y FOX recurre entonces a las mismas cabeceras que WooCommerce: en un servidor como el que se acaba de describir, los visitantes que llegan por la misma dirección de Cloudflare comparten una moneda guardada en las páginas renderizadas por el servidor.
Reglas GeoIP en páginas en caché
En FOX 2.5.5, la solicitud de redibujo compara primero la moneda de la copia en caché con la moneda actual del visitante, y cuando son iguales responde "nada que cambiar" sin llegar al paso GeoIP. Un visitante nuevo empieza en la Moneda de bienvenida (Welcome currency), así que en cada página guardada en caché en la Moneda de bienvenida (Welcome currency) se omiten las reglas GeoIP: con una regla Alemania → EUR, un visitante alemán se queda con la Moneda de bienvenida (Welcome currency) y recibe euros solo en la primera página que casualmente esté guardada en otra moneda. Ese es el patrón de "GeoIP funciona solo en algunas páginas" detrás de una caché de página completa. El fragmento siguiente ejecuta el paso GeoIP antes de la comparación, una vez por visitante, y deja que una moneda elegida en el selector prevalezca:
<?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 );
Omite la línea de apertura <?php si tu archivo ya tiene una. Los manejadores de redibujo propios de FOX se ejecutan con la prioridad por defecto 10, así que este código se ejecuta primero, y la comparación ve entonces la moneda de la regla GeoIP del visitante. El redibujo solo se ejecuta en páginas con precios de producto, de modo que un visitante que aterriza en una entrada del blog recibe la moneda GeoIP en la primera página de la tienda. Para probarlo, purga la caché de Cloudflare, carga una página de categoría desde un país sin regla GeoIP hasta que esté en caché (un HIT) en la Moneda de bienvenida (Welcome currency), y luego ábrela mediante una VPN desde un país con regla, en un perfil de navegador que nunca haya visitado la tienda: los precios deben cambiar a la moneda de ese país. Con los ajustes anteriores, quien decide quién es un visitante nuevo es la clave del navegador, no la dirección IP.
Purga y prueba después de cada cambio
Una página en caché conserva los precios con los que se construyó, y el redibujo de FOX los sustituye solo cuando la moneda del visitante difiere de la de la copia en caché. Después de cambiar monedas, tasas, decimales o símbolos en FOX, los visitantes cuya moneda coincide con una copia en caché ven los importes antiguos hasta que esa copia caduca. El plugin de Cloudflare para WordPress purga las páginas de APO cuando editas contenido, no cuando cambian los ajustes o las tasas de FOX, así que usa Purgar todo (Purge Everything) en la configuración de caché de Cloudflare, y purga el plugin de caché de tu servidor, después de esos cambios. Con actualizaciones automáticas de tasas y Cache Rules, un TTL de borde (Edge TTL) no mayor que el intervalo de actualización mantiene al día los precios convertidos; con APO, purga después de grandes movimientos de tasas.
Después prueba en este orden:
- Ejecuta dos veces el comando curl anterior para una página de categoría: la segunda respuesta muestra
cf-cache-status: HIT(ycf-apo-via: cachecon APO) y ninguna cabeceraset-cookie. - Abre la página en dos navegadores que nunca hayan visitado la tienda. Cambia la moneda en uno: cambia allí, y el otro conserva su propia moneda tras recargar.
- Añade un producto al carrito en la segunda moneda y ve al checkout: los totales se mantienen en esa moneda.
- Si algo falla, saca la caché de Cloudflare de la prueba: desactiva un momento APO o tu Cache Rule, o activa el Modo de desarrollo (Development Mode) en la configuración de caché, que suspende la caché de borde durante tres horas, luego purga y repite. Si el problema persiste, la causa está en tu servidor, como un plugin de caché, una caché del servidor o un optimizador de JavaScript, no en Cloudflare. La optimización de scripts propia de Cloudflare, Rocket Loader, retrasa los scripts como lo hacen esos optimizadores; si los precios siguen girando, prueba con él desactivado y consulta el selector de moneda se queda cargando tras la optimización de JS.
Lista de verificación
- Sabes si Cloudflare guarda tu HTML en caché (solo proxy, Cache Rules o APO), a partir de las cabeceras de respuesta.
- Con HTML en caché: Almacenamiento de moneda (Currency storage) = Transitorio (Transient), Estoy usando un complemento de caché en mi sitio (I am using cache plugin on my site) = Sí, No hay datos GET en el enlace (No GET data in link) = No, FOX actualizado.
- Carrito, checkout, cuenta,
/wp-json/,wc-ajaxy URL concurrency=nunca en caché; TTL de borde (Edge TTL) respetaCache-Control. - Con APO: Ubicación predeterminada del cliente (Default customer location) no configurada en la variante con soporte de caché de páginas.
- Geolocalización de IP (IP Geolocation) activada; IP real del visitante restaurada en el servidor; Eliminar encabezados de IP del visitante (Remove visitor IP headers) desactivada.
- Con reglas GeoIP y páginas en caché: el fragmento de redibujo en su sitio.
- Cachés de Cloudflare y del servidor purgadas tras cambiar los ajustes o las tasas de FOX.
Si la moneda sigue siendo incorrecta con todo esto en su sitio, abre un tema en el foro de soporte de FOX con el enlace de una página, las cabeceras de respuesta de esa página y tus ajustes de almacenamiento y caché de FOX, y lo revisaremos.