← Blog/
Shopify · Tracking
Código copy-paste

Cómo crear un Custom Pixel en Shopify

Guía práctica 2026 con código completo, listo para copiar y pegar. Implementa Meta Pixel, Google Ads, GA4 y TikTok en tu Shopify con deduplicación y protección contra duplicados.

WP

José Moreno

Especialistas en Shopify Tracking

Actualizado: Abril 2026·18 min de lectura·Nivel Intermedio

4 pixels

código listo para copiar

12 eventos

del ciclo completo

0$

vs $100-300/mes apps

Todos los planes

no necesitas Plus

En esta guia

Por qué necesitas un Custom Pixel

Si todavía estás usando el método antiguo (scripts en theme.liquid o "Additional Scripts"), necesitas saber esto: Shopify deprecó los pixels legacy.

⚠️ Importante

Desde 2024, el método oficial es Customer Events con Custom Pixels. Los scripts en theme.liquid ya no reciben datos del checkout en tiendas nuevas y van a dejar de funcionar progresivamente.

Antes vs Ahora

Característica
❌ Antes (Legacy)
✅ Ahora (Custom Pixels)
Ubicación del código
theme.liquid
Customer Events
Acceso al DOM
Directo a la página
Sandbox aislado (iframe)
Eventos del checkout
Solo Shopify Plus
TODOS los planes
Estabilidad
Se rompe con cambios de tema
Independiente del tema
API de eventos
Sin estándar
API estandarizada

4 razones por las que importa

🚫

Los scripts legacy van a morir

Shopify está migrando todo a Custom Pixels. Los pixels viejos ya no reciben datos del checkout en tiendas nuevas.

🌐

Funcionan en TODOS los planes

Antes solo Shopify Plus podía trackear el checkout. Ahora cualquier tienda puede.

🛒

Acceso al checkout completo

Eventos como checkout_started, checkout_completed, payment_info_submitted disponibles para todos.

🛡️

No se rompen con cambios de tema

Son independientes del tema. Cambias tu diseño y el tracking sigue funcionando.

¿Qué es un Custom Pixel?

Un Custom Pixel es un bloque de código JavaScript que Shopify ejecuta en un sandbox aislado (iframe) y que puede escuchar eventos estándar de la tienda. Tú escribes el código que reacciona a cada evento y envía los datos donde quieras.

Eventos disponibles en Shopify

page_viewedCada carga de página
product_viewedUsuario ve la página de un producto
collection_viewedUsuario ve una colección
product_added_to_cartAgrega producto al carrito
cart_viewedVe el carrito
checkout_startedInicia el checkout
checkout_address_info_submittedLlena dirección
checkout_contact_info_submittedLlena email/teléfono
checkout_shipping_info_submittedSelecciona envío
payment_info_submittedIngresa datos de pago
checkout_completedCompra completada
search_submittedBusca en el sitio

Cómo crear tu primer Custom Pixel

1

Ir a Customer Events

Shopify Admin → Settings (abajo izquierda) → Customer Events

2

Add custom pixel

Verás 'App pixels' (instalados por apps) y 'Custom pixels'. Click en 'Add custom pixel'.

3

Nombre descriptivo

Dale un nombre claro: 'Meta Pixel - Browser', 'Google Ads - Conversion Tag', etc.

4

Pega tu código y guarda

Pega el código del pixel (ver más abajo) → Save → Connect → activo.

Estructura básica de todo Custom Pixel

Estructura mínima

javascript
// 1. INICIALIZACIÓN  -  carga el SDK (Meta, Google, etc.)

// 2. SUSCRIPCIÓN A EVENTOS
analytics.subscribe('nombre_del_evento', (event) => {
  // 3. PROCESAMIENTO
  // Extraes los datos del evento
  // Los envías a la plataforma que quieras
});

La variable analytics está disponible globalmente dentro del Custom Pixel - es la API de Shopify que te da acceso a los eventos.

El objeto event: qué datos contiene

Cada evento que recibes tiene datos diferentes. Aquí los dos más importantes:

📦 product_viewed

event.data del producto

javascript
analytics.subscribe('product_viewed', (event) => {
  const product = event.data.productVariant;
  
  product.id;                   // "44325678901234"
  product.title;                // "Vestido Largo Negro - M"
  product.price.amount;         // "59.99"
  product.price.currencyCode;   // "USD"
  product.product.title;        // "Vestido Largo Negro"
  product.product.type;         // "Dress"
  product.product.vendor;       // "Tu Marca"
  product.sku;                  // "DRESS-BLK-M"
  product.image?.src;           // URL de la imagen
});

💳 checkout_completed

event.data del checkout completado

javascript
analytics.subscribe('checkout_completed', (event) => {
  const checkout = event.data.checkout;
  
  checkout.order?.id;             // "gid://shopify/OrderIdentity/1234"
  checkout.token;                 // Token único del checkout
  checkout.totalPrice.amount;     // "89.99" (total pagado)
  checkout.subtotalPrice.amount;  // Subtotal
  checkout.totalTax.amount;       // Impuestos
  checkout.shippingLine?.price.amount; // Envío
  checkout.discountApplications;  // Descuentos
  checkout.email;                 // "usuario@email.com"
  checkout.phone;                 // "+1234567890"
});
f

Pixel completo: Meta (Facebook)

Custom Pixel listo para copiar y pegar que implementa el Pixel de Meta con todos los eventos clave: PageView, ViewContent, AddToCart, InitiateCheckout, Purchase y Search. Incluye dedup contra reload del thank-you.

meta-pixel.js - Custom Pixel completo

javascript
// =============================================
// META PIXEL - CUSTOM PIXEL PARA SHOPIFY
// =============================================
const PIXEL_ID = 'TU_PIXEL_ID';

// Cargar SDK de Meta Pixel
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){
n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window,document,'script',
'https://connect.facebook.net/en_US/fbevents.js');

fbq('init', PIXEL_ID);

// Helpers
function generateEventId(prefix, id) {
  return prefix + '_' + id + '_' + Date.now();
}
function cleanOrderId(gid) {
  if (!gid) return '';
  return gid.split('/').pop();
}

// 1. PAGE VIEW
analytics.subscribe('page_viewed', () => fbq('track', 'PageView'));

// 2. VIEW CONTENT
analytics.subscribe('product_viewed', (event) => {
  const p = event.data.productVariant;
  fbq('track', 'ViewContent', {
    content_ids: [p.id.toString()],
    content_type: 'product',
    content_name: p.product.title,
    content_category: p.product.type || '',
    value: parseFloat(p.price.amount),
    currency: p.price.currencyCode
  }, { eventID: generateEventId('vc', p.id) });
});

// 3. ADD TO CART
analytics.subscribe('product_added_to_cart', (event) => {
  const line = event.data.cartLine;
  const v = line.merchandise;
  fbq('track', 'AddToCart', {
    content_ids: [v.id.toString()],
    content_type: 'product',
    content_name: v.title,
    value: parseFloat(line.cost.totalAmount.amount),
    currency: line.cost.totalAmount.currencyCode,
    contents: [{ id: v.id.toString(), quantity: line.quantity }]
  }, { eventID: generateEventId('atc', v.id) });
});

// 4. INITIATE CHECKOUT
analytics.subscribe('checkout_started', (event) => {
  const c = event.data.checkout;
  fbq('track', 'InitiateCheckout', {
    content_ids: c.lineItems.map(i => i.variant.id.toString()),
    content_type: 'product',
    contents: c.lineItems.map(i => ({ id: i.variant.id.toString(), quantity: i.quantity })),
    value: parseFloat(c.totalPrice.amount),
    currency: c.totalPrice.currencyCode,
    num_items: c.lineItems.length
  }, { eventID: generateEventId('ic', c.token) });
});

// 5. PURCHASE (con dedup contra reload)
analytics.subscribe('checkout_completed', (event) => {
  const c = event.data.checkout;
  const orderId = cleanOrderId(c.order?.id) || c.token;
  
  const last = sessionStorage.getItem('_fb_last_purchase');
  if (last === orderId) return;
  sessionStorage.setItem('_fb_last_purchase', orderId);
  
  fbq('track', 'Purchase', {
    content_ids: c.lineItems.map(i => i.variant.id.toString()),
    content_type: 'product',
    contents: c.lineItems.map(i => ({
      id: i.variant.id.toString(),
      quantity: i.quantity,
      item_price: parseFloat(i.variant.price.amount)
    })),
    value: parseFloat(c.totalPrice.amount),
    currency: c.totalPrice.currencyCode,
    order_id: orderId
  }, { eventID: orderId });
  
  if (c.email) {
    fbq('init', PIXEL_ID, { em: c.email, ph: c.phone || '' });
  }
});

// 6. SEARCH
analytics.subscribe('search_submitted', (event) => {
  fbq('track', 'Search', { search_string: event.data.searchResult?.query || '' });
});

📌 Después de pegarlo

  1. Reemplaza TU_PIXEL_ID con tu ID real (Meta Events Manager → Data Sources)
  2. Click SaveConnect → el pixel está activo
  3. Si vas a usar también CAPI, los eventID ya están listos para deduplicación
GA

Pixel completo: GA4 Ecommerce

Tracking ecommerce completo para GA4 con todos los eventos del funnel: view_item, add_to_cart, begin_checkout, purchase.

ga4-pixel.js

javascript
// =============================================
// GA4 ECOMMERCE TRACKING - CUSTOM PIXEL
// =============================================
const GA4_ID = 'G-XXXXXXXXXX';

const script = document.createElement('script');
script.src = 'https://www.googletagmanager.com/gtag/js?id=' + GA4_ID;
script.async = true;
document.head.appendChild(script);

window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', GA4_ID);

// Si usas GTM Server-Side, descomenta:
// gtag('config', GA4_ID, { 'server_container_url': 'https://tracking.tutienda.com' });

function cleanOrderId(gid) {
  if (!gid) return '';
  return gid.split('/').pop();
}

// VIEW ITEM
analytics.subscribe('product_viewed', (event) => {
  const p = event.data.productVariant;
  gtag('event', 'view_item', {
    currency: p.price.currencyCode,
    value: parseFloat(p.price.amount),
    items: [{
      item_id: p.sku || p.id.toString(),
      item_name: p.product.title,
      item_category: p.product.type || '',
      item_variant: p.title,
      price: parseFloat(p.price.amount),
      quantity: 1
    }]
  });
});

// ADD TO CART
analytics.subscribe('product_added_to_cart', (event) => {
  const line = event.data.cartLine;
  const v = line.merchandise;
  gtag('event', 'add_to_cart', {
    currency: line.cost.totalAmount.currencyCode,
    value: parseFloat(line.cost.totalAmount.amount),
    items: [{
      item_id: v.sku || v.id.toString(),
      item_name: v.title,
      price: parseFloat(v.price.amount),
      quantity: line.quantity
    }]
  });
});

// BEGIN CHECKOUT
analytics.subscribe('checkout_started', (event) => {
  const c = event.data.checkout;
  gtag('event', 'begin_checkout', {
    currency: c.totalPrice.currencyCode,
    value: parseFloat(c.totalPrice.amount),
    items: c.lineItems.map(i => ({
      item_id: i.variant.sku || i.variant.id.toString(),
      item_name: i.title,
      item_variant: i.variant.title,
      price: parseFloat(i.variant.price.amount),
      quantity: i.quantity
    }))
  });
});

// PURCHASE
analytics.subscribe('checkout_completed', (event) => {
  const c = event.data.checkout;
  const orderId = cleanOrderId(c.order?.id) || c.token;
  
  const last = sessionStorage.getItem('_ga4_last_purchase');
  if (last === orderId) return;
  sessionStorage.setItem('_ga4_last_purchase', orderId);
  
  gtag('event', 'purchase', {
    transaction_id: orderId,
    currency: c.totalPrice.currencyCode,
    value: parseFloat(c.totalPrice.amount),
    tax: parseFloat(c.totalTax?.amount || 0),
    shipping: parseFloat(c.shippingLine?.price?.amount || 0),
    items: c.lineItems.map(i => ({
      item_id: i.variant.sku || i.variant.id.toString(),
      item_name: i.title,
      item_variant: i.variant.title,
      price: parseFloat(i.variant.price.amount),
      quantity: i.quantity
    }))
  });
});

// SEARCH
analytics.subscribe('search_submitted', (event) => {
  gtag('event', 'search', { search_term: event.data.searchResult?.query || '' });
});

💡 Tip Server-Side

Si usas GTM Server-Side, descomenta la línea con server_container_url y apunta a tu dominio Stape (ej: tracking.tutienda.com). Los datos pasarán por tu servidor en vez de ir directo a Google.

TT

Pixel completo: TikTok

tiktok-pixel.js

javascript
// =============================================
// TIKTOK PIXEL - CUSTOM PIXEL
// =============================================
const TT_PIXEL_ID = 'TU_TIKTOK_PIXEL_ID';

!function(w,d,t){
  w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];
  ttq.methods=["page","track","identify","instances","debug","on","off",
  "once","ready","alias","group","enableCookie","disableCookie"];
  ttq.setAndDefer=function(t,e){t[e]=function(){
  t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};
  for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);
  ttq.load=function(e){var r="https://analytics.tiktok.com/i18n/pixel/events.js";
  ttq._i=ttq._i||{};ttq._i[e]=[];ttq._i[e]._u=r;ttq._t=ttq._t||{};
  ttq._t[e]=+new Date;ttq._o=ttq._o||{};
  var s=d.createElement("script");s.async=!0;s.src=r+"?sdkid="+e+"&lib="+t;
  var f=d.getElementsByTagName("script")[0];f.parentNode.insertBefore(s,f)};
  ttq.load(TT_PIXEL_ID); ttq.page();
}(window,document,'ttq');

function cleanOrderId(gid) {
  if (!gid) return '';
  return gid.split('/').pop();
}

// VIEW CONTENT
analytics.subscribe('product_viewed', (event) => {
  const p = event.data.productVariant;
  ttq.track('ViewContent', {
    content_id: p.id.toString(),
    content_type: 'product',
    content_name: p.product.title,
    value: parseFloat(p.price.amount),
    currency: p.price.currencyCode
  });
});

// ADD TO CART
analytics.subscribe('product_added_to_cart', (event) => {
  const line = event.data.cartLine;
  ttq.track('AddToCart', {
    content_id: line.merchandise.id.toString(),
    content_type: 'product',
    value: parseFloat(line.cost.totalAmount.amount),
    currency: line.cost.totalAmount.currencyCode,
    quantity: line.quantity
  });
});

// INITIATE CHECKOUT
analytics.subscribe('checkout_started', (event) => {
  const c = event.data.checkout;
  ttq.track('InitiateCheckout', {
    value: parseFloat(c.totalPrice.amount),
    currency: c.totalPrice.currencyCode
  });
});

// COMPLETE PAYMENT
analytics.subscribe('checkout_completed', (event) => {
  const c = event.data.checkout;
  const orderId = cleanOrderId(c.order?.id) || c.token;
  
  const last = sessionStorage.getItem('_tt_last_purchase');
  if (last === orderId) return;
  sessionStorage.setItem('_tt_last_purchase', orderId);
  
  ttq.track('CompletePayment', {
    content_type: 'product',
    value: parseFloat(c.totalPrice.amount),
    currency: c.totalPrice.currencyCode,
    quantity: c.lineItems.length
  });
});

Customer Privacy y settings

Después de crear tu pixel, Shopify te muestra una pantalla de configuración. La parte clave es Customer Privacy:

Opción
¿Cuándo se dispara?
Para quién
Not required
Siempre se dispara
Tiendas USA/LATAM sin GDPR
Required before tracking
Solo después de consentimiento
Tiendas en EU/UK
Required before analytics
Consentimiento para analytics
Tiendas con consent banner

Recomendación rápida

Si vendes solo en USA/LATAM: usa "Not required". Si vendes a Europa: usa "Required before tracking" y configura un consent banner que pase el estado a Shopify vía Customer Privacy API.

Debugging: cómo verificar que funciona

1

Shopify Customer Events Log

Customer Events → tu pixel → Preview. Se abre tu tienda. Navega y vuelve - verás los eventos disparados con sus datos.

2

Meta Events Manager (Test Events)

Events Manager → tu Pixel → Test Events. Navega tu tienda y verifica eventos con badge 'Browser'.

3

Google Tag Assistant

Instala la extensión Tag Assistant de Chrome. Activa y navega - verás cada evento enviado a GA4 o Google Ads.

4

Console del navegador

Agrega console.log() temporales en tu pixel para debug. F12 → Console. Quítalos antes de producción.

Snippet rápido de debug

Debug en la console

javascript
analytics.subscribe('checkout_completed', (event) => {
  console.log('=== PURCHASE EVENT ===');
  console.log('Order ID:', event.data.checkout.order?.id);
  console.log('Total:', event.data.checkout.totalPrice.amount);
  console.log('Items:', event.data.checkout.lineItems);
  // ... tu código de tracking
});

Errores comunes y soluciones

Error #1 - El pixel no dispara en el checkout

Causa: Custom Pixel desconectado o privacy bloquea el disparo.

Solución: Verifica estado 'Connected' (no 'Disconnected'). Revisa Customer Privacy.

Error #2 - event.data.checkout.order.id es undefined

Causa: El order.id puede no estar disponible inmediatamente en todos los casos.

Solución: Usa fallback: const orderId = event.data.checkout.order?.id || event.data.checkout.token. El token siempre está.

Error #3 - Precio viene como string en vez de number

Causa: Shopify devuelve precios como strings ("59.99").

Solución: Siempre usa parseFloat(price.amount) antes de enviarlo a Meta o Google.

Error #4 - Eventos duplicados en page reloads

Causa: El usuario recarga el thank-you y el Purchase se dispara de nuevo.

Solución: Usa sessionStorage para guardar el último order ID enviado (incluido en los ejemplos).

Error #5 - El pixel no tiene acceso al DOM

Causa: Los Custom Pixels corren en un iframe sandbox. No puedes usar document.querySelector().

Solución: Usa solo los datos del objeto event. No necesitas el DOM - toda la info está en los eventos.

Error #6 - fbq/gtag no está definido

Causa: El SDK no terminó de cargar cuando intentas disparar un evento.

Solución: Los SDKs encolan eventos automáticamente. Asegúrate de inicializar el SDK ANTES de las suscripciones.

¿Un pixel por plataforma o todo junto?

Recomendación general

Un Custom Pixel por plataforma para tiendas medianas. Para tiendas con mucho tráfico y múltiples plataformas, usa GTM + un único Custom Pixel que envía al servidor.

Opción A: Pixeles individuales

Un Custom Pixel por plataforma (Meta, GA4, Google Ads, TikTok). Simple, independiente, fácil de debuggear.

SimpleSeguroTodos los planes

Opción B: GTM Server-Side

Un solo Custom Pixel que envía datos a un contenedor GTM Server-Side. Máximo control y velocidad de carga.

EscalableRápidoPrivacidad

Checklist final

  • Custom Pixel creado en Settings → Customer Events
  • Pixel ID / Measurement ID correcto en el código
  • Eventos suscritos: page_viewed, product_viewed, product_added_to_cart, checkout_started, checkout_completed
  • Protección contra duplicados de Purchase con sessionStorage
  • parseFloat() en todos los valores de precio
  • Fallback para order ID: order?.id || token
  • Pixel en estado 'Connected'
  • Customer Privacy configurado según tu mercado
  • Verificado en Events Manager / Tag Assistant / Console
  • console.log() de debug removidos antes de producción

Compartir este articulo

WhatsAppX
José Moreno, Fundador de Web Premiere

José Moreno

Fundador · Web Premiere

Fundador de Web Premiere y Signal Lab. Especialista en publicidad digital con 13 años de experiencia en Google Ads, Meta Ads y marketing de resultados para empresas en LATAM y USA. Invitado al programa Google Partners LEAD en Silicon Valley.

Más sobre Shopify Tracking

Tracking12 min

Meta CAPI en Shopify sin Apps

Guía definitiva para implementar la API de Conversiones y evitar el bloqueo de cookies.

Leer guía →
Server-Side15 min

GTM Server-Side con Stape

Centraliza el tracking de Google Ads, Meta, GA4 y más en un solo servidor.

Leer guía →
Tracking8 min

¿Qué es un UTM y cómo usarlo?

La herramienta más subestimada del marketing - con ejemplos reales.

Leer guía →
Shopify Tracking

¿No querés pelearte con código?

Configuramos Custom Pixels + Meta CAPI + Google Enhanced Conversions + GA4 con deduplicación completa. Auditoría inicial gratuita, todo listo en 5-7 días.

Solicitar Auditoría Gratuita →Ver Tracking Server-Side
WhatsApp