
Automatiza tu Feed de Productos en Google Merchant Center con Node.js
Aprende a sincronizar tu eCommerce directamente con Google Merchant Center usando la Content API, sin plugins y de manera escalable.
En eCommerce, tener un feed actualizado en Google Merchant Center no es opcional.
Es crucial para que tus campañas de Shopping funcionen, tus productos se aprueben rápidamente y tu rendimiento publicitario sea consistente.
Muchos CMS ofrecen plugins para esta tarea, pero suelen ser:
❌ Limitados
❌ Difíciles de personalizar
❌ Poco eficientes para proyectos con necesidades reales de negocio
Como desarrollador especializado en eCommerce, me he enfrentado muchas veces a esta necesidad.
Y la mejor solución que encontré fue ir directo a la fuente: Google Content API for Shopping.
En este artículo te explico cómo automatizar tu feed con Node.js, sin plugins innecesarios, de forma escalable y totalmente controlada.
🧱 Paso 1: Autenticación con una cuenta de servicio
Google ofrece una librería oficial para trabajar con sus APIs desde Node.js: 👉 googleapis
Dentro de ella, el cliente que nos interesa es @googleapis/content
, que conecta directamente con el Merchant Center.
🔑 ¿Qué es una cuenta de servicio?
Una cuenta de servicio es una identidad técnica dentro de Google Cloud que te permite acceder a sus APIs sin necesidad de intervención humana. Ideal para procesos automáticos y backend.
✅ Cómo crearla
- Ve a console.cloud.google.com y entra en tu proyecto.
- Dirígete a “IAM y administración” → “Cuentas de servicio”
- Crea una nueva cuenta y asigna el rol Editor o uno personalizado con permisos de Content API.
- Descarga el archivo .json con tus credenciales.
🔐 Guárdalo de forma segura
¡Nunca subas estas credenciales a Git!
Usa variables de entorno:
GOOGLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----...
GOOGLE_CLIENT_EMAIL=nombre-cuenta@proyecto.iam.gserviceaccount.com
MERCHANT_CENTER_ACCOUNT_ID=123456789
📌 Para obtener el MERCHANT_CENTER_ACCOUNT_ID: Entra en Google Merchant Center y, en la parte superior derecha (junto a tu foto de perfil), verás tu ID de cuenta. Ese número es tu merchantId
.
🔒 Autenticación con GoogleAuth
import * as content from '@googleapis/content'
const authClient = new content.auth.GoogleAuth({
credentials: {
private_key: process.env.GOOGLE_PRIVATE_KEY,
client_email: process.env.GOOGLE_CLIENT_EMAIL
},
scopes: [
'https://www.googleapis.com/auth/content', // Acceso completo a la Content API
'https://www.googleapis.com/auth/cloud-platform' // Recomendado por Google
]
})
const contentClient = content.content({
version: 'v2.1',
auth: authClient
})
Los scopes definen los permisos:
content
: crear, actualizar y eliminar productos.cloud-platform
: interoperabilidad con otras APIs.
🧩 Paso 2: Insertar o actualizar productos
La API ofrece dos métodos clave:
products.insert()
→ Crear un producto nuevo (solo 1 vez porofferId
)products.update()
→ Actualizar un producto existente
⚠️ Usar insert
sobre un producto ya existente dará error. Maneja esta lógica consultando si el producto ya existe antes de llamarlo.
🛠️ Función de ejemplo
import { content_v2_1 } from '@googleapis/content'
const updateProduct = async (
product: any,
contentClient: content_v2_1.Content,
isNewProduct: boolean
) => {
try {
const method = isNewProduct ? 'insert' : 'update'
const updatedProduct = await contentClient.products[method]({
merchantId: process.env.MERCHANT_CENTER_ACCOUNT_ID,
requestBody: {
offerId: product.id,
title: product.title,
description: product.description,
price: {
value: product.price.toFixed(2),
currency: 'EUR'
},
salePrice: product.salePrice
? {
value: product.salePrice.toFixed(2),
currency: 'EUR'
}
: undefined,
link: `https://tusitio.com/producto/${product.slug}`,
imageLink: product.imageUrl,
additionalImageLinks: product.additionalImages || [],
availability: product.stock > 0 ? 'in stock' : 'out of stock',
condition: 'new',
brand: product.brand,
contentLanguage: 'es',
targetCountry: 'ES',
channel: 'online',
gtin: product.gtin || null,
mpn: product.mpn || null,
identifierExists: !!product.gtin,
googleProductCategory: product.googleCategory || null,
productTypes: product.categories || [],
salePriceEffectiveDate: product.salePrice
? '2025-03-01T23:00:00Z/2025-06-15T22:00:00Z'
: null,
pickupMethod: 'buy',
canonicalLink: `https://tusitio.com/producto/${product.slug}`
}
})
return { success: true, product: updatedProduct }
} catch (error: any) {
console.error(`Error al procesar producto ${product.id}:`, error)
return {
success: false,
error: error.message,
productId: product.id
}
}
}
📘 Lista completa de campos disponibles en la documentación oficial.
🔁 Paso 3: Ejecutar la sincronización controlada
Actualizar muchos productos de golpe puede causar throttling o errores de red. Para evitarlo, usamos p-limit
, que limita el número de promesas concurrentes.
npm install p-limit
⚙️ Ejemplo
import pLimit from 'p-limit'
const limit = pLimit(5)
const updateResults = await Promise.all(
products.map((product) =>
limit(() => updateProduct(product, contentClient, product.isNew))
)
)
Esto asegura que solo se ejecuten 5 procesos a la vez.
🎁 Bonus: Automatiza con un cron job diario
Puedes programar la sincronización con node-cron o un servicio externo (EasyCron, GitHub Actions).
Ejemplo con node-cron:
import cron from 'node-cron'
cron.schedule('0 3 * * *', async () => {
console.log('⏰ Actualizando productos en Merchant Center...')
await syncAllProducts()
})
Esto correrá todos los días a las 3:00 AM.
🚀 Conclusión
Al usar la Content API directamente desde Node.js, desbloqueas una integración de primer nivel:
✅ 100% personalizable ✅ Sin plugins limitantes ✅ Optimizado para escala y rendimiento ✅ Compatible con cualquier CMS o backend ✅ A prueba de crecimiento futuro
En un entorno donde la automatización marca la diferencia entre vender o no, este tipo de integración puede ser la clave que eleve tus campañas de Shopping a otro nivel.`