The Feed: Ingeniería de canales de datos para Google Shopping
Por qué los feeds predeterminados de Shopify fallan a escala. Una guía técnica para crear canales XML de alto rendimiento, utilizar la API de contenido y optimizar etiquetas personalizadas para ROAS.
Si eres una marca de moda, tu sitio web es tu tienda insignia. Pero su Product Feed es su cartel, su catálogo y su vendedor, distribuidos por todo Internet. Para la mayoría de los comerciantes, el Product Feed es una idea de último momento. Instala un complemento de “Google Shopping”, hace clic en “Sincronizar” y lo olvida.
Por eso pierden.
En Maison Code Paris, tratamos el feed de productos como un producto de datos. Es un artefacto de ingeniería que se correlaciona directamente con el retorno de la inversión publicitaria (ROAS). Si tu feed es lento, inexacto o genérico, estás pagando un “impuesto perezoso” a Google.
Esta guía explora cómo rediseñar el feed desde un archivo XML pasivo hasta convertirlo en un canal dinámico que genere ingresos.
Por qué Maison Code habla de esto
En Maison Code Paris, actuamos como la conciencia arquitectónica de nuestros clientes. A menudo heredamos stacks “modernos” construidos sin una comprensión fundamental de la escala.
Discutimos este tema porque representa un punto de inflexión crítico en la madurez de la ingeniería. Implementarlo correctamente diferencia un MVP frágil de una plataforma resistente de nivel empresarial.
El problema con las sincronizaciones “predeterminadas”
Las plataformas estándar (Shopify, Magento, Salesforce) ofrecen integraciones nativas. Estos fracasan a escala (GMV > 10 millones de dólares) por tres motivos:
- Latencia: normalmente se sincronizan una vez cada 24 horas. Si agota un SKU a las 10:00 a. m., continúa pagando por los clics hasta la próxima sincronización a las 2:00 a. m. Este es un gasto desperdiciado.
- Títulos genéricos: asignan el título interno de su CMS (“Crop Top”
) directamente a Google. Google quiere”Top corto de algodón para mujer - Negro - Talla M”`. - Estrategia cero: completan los campos obligatorios, pero ignoran las
etiquetas_personalizadas. No puede ofertar de manera diferente en artículos de “margen alto” y en “liquidación” porque los datos no están ahí.
Arquitectura: el oleoducto híbrido
No dependemos de aplicaciones. Construimos un pipeline personalizado en AWS/Vercel. Utilizamos un Enfoque híbrido:
- Bulk Sync (XML): una regeneración diaria del catálogo completo de datos estructurales.
- Sincronización incremental (API): actualizaciones en tiempo real de precio y disponibilidad.
gráfico TD
CMS[CMS sin cabeza / Shopify] -->|Nightly Cron| Generador[Generador XML Node.js]
Generador -->|Flujo| S3[Depósito S3: feed.xml]
T3 -->|Buscar| GMC[Centro de comerciantes de Google]
CMS -->|Webhook: PRICE_UPDATE| API[Función sin servidor]
API -->|Empujar| ContentAPI[API de contenido de Google]
ContentAPI -->|Actualización instantánea| GMC
Fase 1: Generación XML de alto rendimiento
Generar un archivo XML para 50.000 SKU es complicado. Si carga todos los productos en la memoria, su proceso Node.js fallará (montón sin memoria). Usamos Transmisiones.
El generador de transmisión
Recuperamos productos utilizando la paginación basada en cursores (GraphQL), los transformamos y canalizamos el resultado directamente al flujo de carga de S3.
importar {Transformar} desde 'flujo';
importar {createGzip} desde 'zlib';
importar {S3} desde '@aws-sdk/client-s3';
// 1. Transformar flujo: Producto JSON -> Cadena XML
const xmlTransform = nueva transformación ({
writableObjectMode: verdadero,
transformar (producto, codificación, devolución de llamada) {
const xmlNodo = `
<elemento>
<g:id>${product.sku}</g:id>
<g:título><![CDATA[${optimizeTitle(producto)}]]></g:título>
<g:precio>${producto.precio.cantidad} ${producto.precio.moneda}</g:precio>
<g:enlace>${product.onlineStoreUrl}</g:enlace>
<g:cogs>${product.cost}</g:cogs> <!-- Datos de margen personalizados -->
</elemento>
`;
devolución de llamada (nulo, xmlNode);
}
});
// 2. El oleoducto
función asíncrona generarFeed() {
const s3Stream = nuevo PassThrough();
carga constante = nueva carga ({
cliente: nuevo S3({}),
parámetros: { Depósito: 'feeds', Clave: 'google.xml.gz', Cuerpo: s3Stream }
});
const productStream = getShopifyProductStream(); // Generador personalizado
flujo de producto
.pipe(transformación xml)
.pipe(createGzip()) // Siempre comprimir
.pipe(s3Stream);
espere cargar.hecho();
}
Este canal nos permite generar distintos feeds para distintas regiones (EE. UU., UE, Reino Unido) en paralelo con una huella de memoria mínima.
Fase 2: La capa lógica (enriquecimiento de datos)
Aquí es donde la ingeniería se encuentra con el marketing. No solo pasamos datos; lo potenciamos.
Optimización de títulos (SEO para anuncios)
El algoritmo relaciona las consultas con su título.
- Malo: “Air Max 90” (Nombre interno del CMS).
- Bueno: “Zapatillas para correr Nike Air Max 90 para hombre - Blanco/Rojo - Talla 10”.
Utilizamos un motor de plantillas:
Título = [Marca] + [Género] + [Colección] + [Tipo de producto] + [Color] + [Material]
Etiquetas personalizadas para ofertar
Google permite 5 etiquetas personalizadas (custom_label_0 a 4). Esta es tu arma secreta.
Los completamos mediante programación según la lógica empresarial:
- Etiqueta 0 (Margen): Si
(Precio - Costo) > €50, establezca"Margen_alto". Oferta alta. - Etiqueta 1 (temporada): si
etiquetascontiene “Summer25”, establezca"New_Arrival". - Etiqueta 2 (Rendimiento): Sincronización con Google Analytics. Si
ConversionRate > 3%, establezca"Best_Seller". - Etiqueta 3 (Stock): Si
inventario < 5, establezca"Low_Stock". Detenga los anuncios genéricos, impulse la urgencia.
Fase 3: La API de contenido (en tiempo real)
Para Precio y Stock, XML es demasiado lento. Usamos la API de contenido de Google para compras.
Cuando se realiza una compra en la tienda, se activa un webhook.
PedidoCreado -> Nivel de Inventario: 0.
Nuestra función sin servidor llega inmediatamente a Google:
importar { content_v2_1 } desde '@googleapis/content';
función asíncrona actualizarGoogleStock(sku: cadena, cantidad: número) {
const auth = espera getGoogleAuth();
contenido constante = nuevo content_v2_1.Content({auth});
aguardar contenido.inventario.set({
ID de comerciante: '12345678',
storeCode: 'en línea', // o código de tienda local
productId: `en línea:en:US:${sku}`,
cuerpo de solicitud: {
disponibilidad: cantidad > 0 ? 'en stock': 'agotado',
// También podemos actualizar el precio de venta aquí al instante
Precio de venta: { valor: '99.00', moneda: 'USD' }
}
});
}
Latencia: < 2 minutos. Resultado: Nunca pagas por un clic en un artículo agotado.
Canales en expansión: Meta, Pinterest, TikTok
Una vez que tenga esta canalización de datos sin procesar, no estará limitado a Google.
- Meta (Facebook/Instagram): Acepta un formato CSV similar. Bifurcamos la transmisión, asignamos
g:idafb:idy la subimos al Administrador de catálogos. - TikTok: Requiere recursos de video. Podemos asignar
custom_label_4a una URL de un recurso de video generado (consulte Agentes de IA). - Anuncios de inventario local (LIA): si tiene tiendas físicas, generamos un feed secundario que vincula “store_code” (París Campos Elíseos) con “cantidad”. Cuando un usuario está cerca de París, el anuncio dice “Recoger hoy”.
Errores comunes (la pesadilla de los “rechazados”)
- GTIN no coincide: Google verifica rigurosamente los códigos de barras UPC/EAN. Si envía un GTIN falso, el producto está prohibido. Si no tiene uno, envíe
identifier_exists: no. - Superposiciones de imágenes: Google exige fondos blancos. Si su imagen principal tiene una marca de agua de “Venta”, será rechazada. Nuestro canal verifica los metadatos de las imágenes o utiliza URL transformadas por Cloudinary para eliminar las superposiciones.
- Discordancia de precios: si el XML dice €100 y la página de destino dice €101 (debido a conversión de moneda o actualizaciones), Google suspende la cuenta. Es por eso que la API de contenido es obligatoria para lograr coherencia en tiempo real.
10. Reglas de alimentación versus edición de fuente
Google Merchant Center permite “Reglas de feeds”. “Si el título contiene ‘Nike’, agregue ‘Zapatillas’”. No uses esto. La lógica oculta en GMC es invisible para sus desarrolladores. Si cambia el título en el código y GMC lo vuelve a cambiar, pasará semanas depurando. Regla: La lógica pertenece al canal de código (fuente), no a la interfaz de destino.
11. Reservas de inventario (la red de seguridad)
La sincronización de tu almacén no es instantánea. Tarda 10 minutos. En esos 10 minutos, es posible que vendas tu última unidad en Amazon. El usuario de Google hace clic en… “Agotado”. Pagaste por ese clic. La solución: si “cantidad <3”, establezca “disponibilidad: agotado”. “Ocultamos” intencionalmente las últimas unidades de las redes publicitarias para evitar picos en la “tasa de rebote” y una mala experiencia del cliente.
12. Alimentando a la bestia: Máximo rendimiento (PMax)
Al nuevo tipo de campaña “Caja Negra” (PMax) de Google le encantan los recursos. No sólo quiere un título. Quiere:
lifestyle_images: Matriz de URL que muestran el producto en uso.short_description: 150 caracteres.product_highlight: viñetas. La mayoría de los conectores los eliminan. Asignamos nuestros campos Sanity CMS a estos atributos extendidos. Cuanto más contexto tenga PMax, más barato será su CPC.
13. Títulos de feeds de pruebas A/B
¿“Nike Air Max” hace mejor clic que “Zapatillas para correr para hombre”?
No lo sabes.
Dividimos el ID del producto.
*ID-123-A -> Título A.
*ID-123-B -> Título B.
Enviamos ambas variantes a Google (como productos separados, pero compartiendo stock a través del ID de grupo de artículos).
Analizamos el CTR.
El ganador se lo lleva todo.
Esto es Experimentación de feeds.
14. Conclusión
El Product Feed es el sistema cardiovascular del comercio electrónico. Bombea productos al ecosistema de Internet. Si los datos son ricos, limpios y rápidos, los anuncios funcionan. Si los datos son deficientes, el algoritmo muere de hambre.
No nos limitamos a “sincronizar” productos. Diseñamos la visibilidad.
¿Tu feed está perdiendo dinero?
Si ve errores de “Discordancia de precios” o ROAS bajo.