Un catálogo que se filtra por atributos técnicos
pluginfinance.com presenta y distribuye plugins para el sector financiero. La implementación arrancó en 2012, incluyó también la identidad visual y la primera versión se hizo en unas seis semanas. La plataforma se ha mantenido y modernizado desde entonces, de modo que hoy funciona sobre PHP 8 y MySQL 8, con WordPress como capa de contenido y de comercio y una interfaz en React que habla con ella mediante REST y GraphQL.
El punto de partida fue la forma en que se compra este producto. Un plugin financiero se elige por parámetros y no por una fotografía. El comprador quiere saber con qué versiones de WordPress y de PHP funciona, qué dependencias externas arrastra, si opera en una instalación multilingüe, qué hace exactamente con los datos de pago y cómo es el soporte después de la compra. Nada de eso cabe en un párrafo, porque todo ello tiene que poder filtrarse y compararse.
Los productos se describen por eso con tipos de contenido propios y campos personalizados apoyados en Advanced Custom Fields. Un parámetro técnico es un campo, no una frase. La ventaja evidente es el filtrado y la ordenación. La menos evidente aparece en el mantenimiento: cuando sale una versión mayor de WordPress, actualizar la compatibilidad de todo el catálogo es una operación sobre un campo y no la lectura de varias decenas de descripciones buscando la frase que menciona una versión. Un catálogo que guarda la compatibilidad en prosa miente en la mitad de sus fichas a los dos años, y nadie se da cuenta.
Las tablas comparativas dependen de esa disciplina más que de ninguna otra cosa. Quien evalúa herramientas financieras suele reducir a dos o tres candidatos y quiere verlos uno al lado del otro, atributo contra atributo. Una comparación vale lo que valen sus campos completos: si la mitad de los productos tiene vacío el campo de compatibilidad, la tabla engaña con más eficacia de la que ayuda. Los campos que sostienen la comparación son obligatorios en la publicación y no opcionales.
En este punto suele haber una tabla de resultados. Aquí no hay ninguna: las cifras de ventas pertenecen al cliente y no a una ficha de proyecto en nuestro sitio. Lo que sí se puede mostrar con honestidad son las decisiones y sus consecuencias.
Interfaz separada del núcleo, y lo que cuesta de verdad
La interfaz es una aplicación en el navegador, con WordPress sirviendo contenido y lógica comercial por detrás. La decisión tuvo aquí una justificación concreta, y no la recomendamos por reflejo a cualquier tienda.
La justificación es el filtrado en varias dimensiones a la vez. Los compradores acotan el catálogo por tipo de integración, por compatibilidad de versión, por modelo de licencia y por otros atributos, cambiando de idea por el camino. En el modelo clásico, cada cambio de filtro es una recarga de página y una construcción completa en el servidor. En un catálogo con muchos atributos eso significa más de una docena de consultas a la base de datos por cada clic en una casilla. Una interfaz separada pide solo la lista de resultados y no la vista entera.
Los costes son reales y conviene nombrarlos. El contenido generado en el navegador puede resultar más difícil de ver para un rastreador, así que las páginas que deben traer tráfico de búsqueda, es decir las fichas de producto y el material editorial, se construyen en el servidor y se entregan como HTML terminado. Solo el manejo del catálogo es del lado del cliente. El segundo coste es la propia capa de API, que se convierte en otra frontera que mantener y proteger. GraphQL resuelve parte del problema, porque una consulta trae exactamente los campos que la vista necesita en lugar de tres llamadas REST que devuelven de más, pero exige límites cuidadosos a la complejidad de las consultas. Un endpoint público de GraphQL sin límite de profundidad es una invitación a agotar el servidor con una sola petición.
La venta es el principio de la relación
La capa comercial se apoya en WooCommerce, ampliado con suscripciones y licencias. Ahí está la parte más difícil del proyecto, porque en el momento de la compra la tienda empieza a trabajar en vez de terminar.
La clave de licencia generada tras el pago es solo el comienzo. La instalación del cliente consulta al servicio si hay actualizaciones, de modo que la tienda es al mismo tiempo un servidor de actualizaciones. Eso significa que las peticiones no llegan solo de personas con navegador, sino de cientos de instalaciones de WordPress que comprueban en segundo plano según su propio calendario, al margen del tráfico de visitas. Ese tráfico es invisible en las estadísticas de visitas y muy visible en la carga del servidor si nadie lo ha previsto.
La solución separa ambos mundos. El endpoint que comprueba licencia y versión responde lo más brevemente posible, lee de Redis y no arranca el ciclo completo de construcción de página. El archivo de actualización se entrega desde la periferia de la red, porque es un archivo estático y no el resultado de una consulta a la base de datos. Separar la comprobación de permisos de la entrega del archivo es lo esencial: la comprobación tiene que ser barata y exacta, mientras que la transferencia es cara y debe ocurrir lo más lejos posible de la aplicación.
Debajo hay una regla que suena jurídica y acaba en código. Una licencia caducada no puede desactivar un plugin instalado. El cliente pagó por un software que sigue funcionando; la caducidad retira el derecho a actualizaciones y a soporte, no el derecho de uso. El estado de la licencia y el estado de funcionamiento tienen que ser dos valores independientes. Quien los mezcla deja al cliente, en la primera renovación tardía, con un módulo desactivado en producción y una avería provocada por la tienda.
Dónde tiene que detenerse la caché de periferia
Redis se ocupa de la caché de objetos y de las sesiones, Cloudflare está delante, y además hay caché de páginas en el servidor. Tres capas suenan a exceso hasta que se escribe qué tipo de petición cae en cada una.
Una tienda divide el tráfico en dos mitades desiguales. Las páginas de catálogo y el material editorial son idénticos para todos los visitantes, así que pueden servirse desde la periferia y no tocan PHP jamás. El carrito, la cuenta de cliente, el historial de pedidos y la lista de claves de licencia son personales y no pueden guardarse en ningún sitio salvo en el navegador de su dueño. La frontera entre esos dos mundos es el origen más frecuente de fallos graves en tiendas en línea: una cabecera mal configurada y la periferia empieza a servir el carrito de un cliente a otro.
La regla es por eso absoluta y no está sujeta a optimización: la presencia de la cookie de sesión de compra excluye la petición de la caché de periferia, sin excepciones. Eso cuesta rendimiento a los clientes identificados y es un coste aceptado a conciencia, porque la alternativa es filtrar datos de pedido. Los fragmentos que dependen de la sesión, como el contador del carrito en la cabecera, se piden aparte una vez cargada la página, lo que mantiene la estructura común para todos y aún cacheable.
Redis acorta lo que queda dentro de PHP. En una tienda con muchos atributos de producto, el coste más alto proviene de las consultas de metadatos, porque la base de datos une productos con propiedades en cada filtrado. Esos resultados, junto con las listas de atributos y la estructura de categorías, viven en la caché de objetos y se invalidan cuando cambia un producto, no cuando vence un plazo.
Reglas fiscales que llegan hasta el carrito
Cualquier tienda que venda bienes digitales fuera de su frontera se topa con una exigencia que no es trabajo posterior de contabilidad sino una condición dentro del proceso de compra. Un servicio electrónico prestado a un consumidor de otro país de la Unión tributa al tipo del país del comprador, y la venta a una empresa con número de identificación fiscal válido se liquida de forma distinta a la venta a un particular. La tienda tiene que establecer el estatus del comprador antes de mostrar un precio final, validar el número en el registro y conservar pruebas de la localización del comprador.
Eso llega al carrito y a la plantilla de factura. Además toca la caché de una manera que suele pillar desprevenidos a los equipos: un importe que depende del país del visitante no puede quedar fijado en una página guardada para todo el mundo. En el catálogo los precios aparecen en una forma base definida, y el importe final dependiente del país se resuelve en el carrito, donde la petición ya está fuera de la caché de periferia de todas formas.
Seguridad en un producto cercano a las finanzas
Un sitio que vende herramientas para el sector financiero es un objetivo atractivo por dos motivos a la vez: procesa pagos y distribuye código que los clientes instalan en sus propios sitios. El segundo pesa más, porque un archivo de actualización comprometido se propaga automáticamente a todas las instalaciones.
De ahí sale el orden de las defensas. Los pagos no pasan por el sitio sino por el proveedor de pagos, así que los datos de tarjeta nunca llegan al servidor propio y la tienda guarda solo un identificador de transacción. Los archivos de publicación van firmados y se entregan únicamente tras la comprobación de licencia, y el acceso al panel de publicación está separado de la administración habitual de contenidos. La seguridad se resuelve en el código y en la configuración del servidor, no con otro plugin de protección: un plugin de ese tipo se ejecuta dentro de PHP, es decir, después de que la petición ya haya arrancado la aplicación, cobra un coste en cada petición y con frecuencia acaba siendo él mismo una vulnerabilidad.
Hay además una capa de protección de datos ineludible en una tienda con claves de licencia. Una cuenta de cliente vincula una dirección de correo con la lista de dominios donde corren sus licencias, es decir, con información sobre la infraestructura de esa empresa. No son datos sensibles en sentido legal, pero una fuga tiene consecuencias reales para el cliente, porque muestra a un atacante qué herramienta hay en qué sitio. El acceso a esa lista está restringido en la API igual que el acceso a los datos de pedido, y los registros guardan a propósito identificadores abreviados en lugar de claves completas.
Rendimiento, monitorización y mantenimiento
Las pruebas previas a cada despliegue se hacen contra una copia de producción y nunca contra una instalación vacía. Una instalación vacía no tiene ni una licencia activa, así que toda la lógica de renovación, caducidad y comprobación de versión pasa cualquier prueba por la vía de no tener nada que hacer.
Un conjunto real se comporta de otra manera. Hay licencias caducadas la semana pasada, licencias renovadas a mitad de periodo y alguna que el cliente movió de un dominio a otro sin avisar. Esa mezcla es la que enseña si las reglas coinciden con lo que prometen las condiciones de venta. Preparar esa copia cuesta tiempo en cada ciclo y es el gasto que menos discusión merece.
En una tienda de licencias la monitorización tiene una prioridad por encima del resto, y no es la portada. Es el tiempo de respuesta del endpoint de licencia. Lo consultan cientos de instalaciones de clientes según su propio calendario, de madrugada igual que a mediodía, y ese tráfico no aparece en ninguna estadística de visitas. Aparece entero en la carga del servidor. Por eso el endpoint tiene alarma propia, independiente de la monitorización general: cuando deja de responder no se pierde una conversión, se generan cientos de errores de actualización en el mismo minuto y el soporte recibe avisos de una avería que no ha ocurrido en casa del cliente.
Todo lo que está delante de ese endpoint es trabajo de interfaz corriente. Los recursos se compilan, los paquetes se dividen y el código se carga solo en las páginas que lo usan. Las imágenes se procesan una vez en la subida en lugar de en cada visualización, con lo que el coste se traslada de cada petición a un momento que el editor ni nota. Los archivos estáticos pasan por Cloudflare, que con clientela repartida por varios continentes es el mayor ahorro disponible.
El mantenimiento cubre actualizaciones de núcleo, tema y extensiones, revisión de registros, copias de seguridad cuya restauración se ensaya de verdad y los cambios funcionales que trae la evolución de la oferta. A eso una tienda de software añade una obligación que el comercio corriente no tiene: cada actualización de WordPress del lado de la tienda debe contrastarse con la compatibilidad que declaran los productos vendidos. Una tienda que corre la versión más reciente mientras vende extensiones marcadas como compatibles con una versión de hace dos años devalúa su propio catálogo antes de que nadie lea una línea.
Resumen
WordPress sostiene la distribución de software siempre que se le trate como capa de contenido y de comercio y no como la aplicación entera. Fuera de él quedan las piezas con condiciones duras de tiempo o de seguridad, que aquí son dos: la comprobación de licencia y la entrega del archivo.
El resto encaja donde un gestor de contenidos es fuerte. El catálogo, la documentación con versiones, el material editorial y el carrito viven en la misma instalación sin estorbarse. Cuatro decisiones se trasladan a cualquier proyecto del mismo tipo. La primera es describir el producto con datos estructurados en lugar de con prosa. Las otras tres son separar el derecho de uso del derecho a actualizaciones, poner una frontera explícita alrededor de lo que puede cachearse y dividir la comprobación de licencia de la entrega de ficheros.
Lo que no se traslada es el modelo de contenidos de este catálogo ni sus reglas de licencia, escritos para una oferta y unas condiciones concretas. Un proveedor que venda uso perpetuo y soporte por tiempo limitado necesita otra forma desde el primer campo. Por eso la siguiente implementación empieza por una pregunta y no por una plantilla: qué compra exactamente el cliente y por cuánto tiempo.
Preguntas frecuentes
Respuestas prácticas para aplicar el tema en la ejecución real.
¿Qué alcance tuvo el proyecto pluginfinance.com?
#¿Cómo fue la entrega de pluginfinance.com?
#¿Qué fue lo más difícil técnicamente en pluginfinance.com?
#¿Qué parte de pluginfinance.com se puede reutilizar en otro proyecto?
#¿Necesitas un FAQ adaptado a tu sector y mercado? Preparamos una versión alineada con tus objetivos de negocio.
Hablemos