DevToolBoxGRATIS
Blog

Open Graph y Twitter Card Meta Tags: Referencia completa

10 min de lecturapor DevToolBox

Cuando compartes un enlace en Facebook, Twitter, LinkedIn, Discord o Slack, la tarjeta de vista previa enriquecida que aparece está impulsada por las meta tags Open Graph (OG) y las tags Twitter Card. Configurarlas correctamente significa más clics y una apariencia más profesional. Esta referencia completa cubre cada tag, cada requisito de plataforma y cada error común.

Genera meta tags perfectas con nuestro generador gratuito →

Tags Open Graph Esenciales

El protocolo Open Graph fue creado por Facebook en 2010 y ahora es adoptado por casi todas las plataformas sociales.

og:title

El título de tu página en la tarjeta de compartir. Mantenlo bajo 60 caracteres.

<meta property="og:title" content="How to Build a REST API with Node.js in 2026" />

og:description

Un resumen del contenido mostrado bajo el título. Apunta a 120-160 caracteres.

<meta property="og:description" content="Step-by-step guide to building a production-ready REST API with Node.js, Express, and TypeScript. Includes auth, validation, and deployment." />

og:image

La imagen en la tarjeta de compartir. El tag más impactante — las publicaciones con imagen obtienen 2-3x más engagement. Debe ser una URL absoluta.

<meta property="og:image" content="https://example.com/images/rest-api-guide-og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="REST API with Node.js — Complete Guide" />
<meta property="og:image:type" content="image/png" />

og:url

La URL canónica de la página.

<meta property="og:url" content="https://example.com/blog/rest-api-nodejs" />

og:type

El tipo de contenido. Valores comunes: website, article, product, profile.

<!-- For a general page -->
<meta property="og:type" content="website" />

<!-- For a blog post / article -->
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2026-02-10T08:00:00Z" />
<meta property="article:author" content="https://example.com/about" />
<meta property="article:section" content="Technology" />
<meta property="article:tag" content="Node.js" />
<meta property="article:tag" content="REST API" />

Tags Open Graph Adicionales

Más allá de lo básico, estos tags ofrecen control más fino sobre cómo se muestra tu contenido:

<!-- Site name — shown above the title on Facebook -->
<meta property="og:site_name" content="DevToolBox" />

<!-- Locale — language_TERRITORY format -->
<meta property="og:locale" content="en_US" />
<meta property="og:locale:alternate" content="fr_FR" />
<meta property="og:locale:alternate" content="de_DE" />
<meta property="og:locale:alternate" content="es_ES" />
<meta property="og:locale:alternate" content="ja_JP" />

<!-- Video (for og:type = video.*) -->
<meta property="og:video" content="https://example.com/video.mp4" />
<meta property="og:video:width" content="1280" />
<meta property="og:video:height" content="720" />
<meta property="og:video:type" content="video/mp4" />

<!-- Audio -->
<meta property="og:audio" content="https://example.com/podcast-ep1.mp3" />
<meta property="og:audio:type" content="audio/mpeg" />

Tags Twitter Card

Twitter (ahora X) soporta su propio sistema de tarjetas con cuatro tipos. Twitter recurre a las tags OG si faltan las tags específicas de Twitter.

Tipos de Twitter Card

Tipo de tarjetaDescripciónCaso de uso
summaryImagen cuadrada pequeña con título y descripciónPosts de blog, páginas generales
summary_large_imageImagen grande sobre título y descripciónContenido visual
playerReproductor de video/audio integrado en el tweetHosting de video, podcasts
appTarjeta de descarga directa de aplicaciónPromoción App Store / Google Play
<!-- Summary Card (small image) -->
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@yourusername" />
<meta name="twitter:creator" content="@authorname" />
<meta name="twitter:title" content="How to Build a REST API with Node.js" />
<meta name="twitter:description" content="Complete guide with auth, validation, and deployment." />
<meta name="twitter:image" content="https://example.com/images/rest-api-square.png" />
<meta name="twitter:image:alt" content="REST API Guide illustration" />

<!-- Summary Card with Large Image -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@yourusername" />
<meta name="twitter:title" content="How to Build a REST API with Node.js" />
<meta name="twitter:description" content="Complete guide with auth, validation, and deployment." />
<meta name="twitter:image" content="https://example.com/images/rest-api-wide.png" />

<!-- Player Card (video/audio) -->
<meta name="twitter:card" content="player" />
<meta name="twitter:player" content="https://example.com/embed/video123" />
<meta name="twitter:player:width" content="1280" />
<meta name="twitter:player:height" content="720" />

<!-- App Card -->
<meta name="twitter:card" content="app" />
<meta name="twitter:app:id:iphone" content="123456789" />
<meta name="twitter:app:id:googleplay" content="com.example.app" />
<meta name="twitter:app:name:iphone" content="My App" />
<meta name="twitter:app:name:googleplay" content="My App" />

Requisitos de Imagen por Plataforma

Cada plataforma tiene diferentes requisitos de tamaño de imagen:

PlataformaTamaño recomendadoTamaño mínimoTamaño máx.Relación aspectoFormatos
Facebook1200 x 630600 x 3158 MB1.91:1JPG, PNG, GIF, WebP
Twitter (summary)144 x 144144 x 1445 MB1:1JPG, PNG, GIF, WebP
Twitter (large image)1200 x 675300 x 1575 MB2:1 / 16:9JPG, PNG, GIF, WebP
LinkedIn1200 x 627200 x 2005 MB1.91:1JPG, PNG
Discord1200 x 630256 x 2568 MB1.91:1JPG, PNG, GIF
WhatsApp1200 x 630300 x 2005 MB1.91:1JPG, PNG
Slack1200 x 630250 x 2505 MB1.91:1JPG, PNG, GIF
Telegram1200 x 630200 x 2005 MB1.91:1JPG, PNG
Pinterest1000 x 1500600 x 60010 MB2:3JPG, PNG
iMessage1200 x 630300 x 3005 MB1.91:1JPG, PNG

Ejemplo Completo de Marcado HTML

Aquí hay un head HTML listo para producción con todas las tags OG y Twitter Card:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <!-- Primary Meta Tags -->
  <title>How to Build a REST API with Node.js in 2026</title>
  <meta name="description" content="Step-by-step guide to building a production-ready REST API with Node.js, Express, and TypeScript." />
  <link rel="canonical" href="https://example.com/blog/rest-api-nodejs" />

  <!-- Open Graph / Facebook -->
  <meta property="og:type" content="article" />
  <meta property="og:url" content="https://example.com/blog/rest-api-nodejs" />
  <meta property="og:title" content="How to Build a REST API with Node.js in 2026" />
  <meta property="og:description" content="Step-by-step guide to building a production-ready REST API with Node.js, Express, and TypeScript." />
  <meta property="og:image" content="https://example.com/images/rest-api-og.png" />
  <meta property="og:image:width" content="1200" />
  <meta property="og:image:height" content="630" />
  <meta property="og:image:alt" content="REST API with Node.js guide banner" />
  <meta property="og:site_name" content="My Dev Blog" />
  <meta property="og:locale" content="en_US" />

  <!-- Article-specific OG tags -->
  <meta property="article:published_time" content="2026-02-10T08:00:00Z" />
  <meta property="article:modified_time" content="2026-02-10T12:00:00Z" />
  <meta property="article:author" content="https://example.com/about" />
  <meta property="article:section" content="Web Development" />
  <meta property="article:tag" content="Node.js" />
  <meta property="article:tag" content="REST API" />
  <meta property="article:tag" content="TypeScript" />

  <!-- Twitter Card -->
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:site" content="@yourusername" />
  <meta name="twitter:creator" content="@authorname" />
  <meta name="twitter:title" content="How to Build a REST API with Node.js in 2026" />
  <meta name="twitter:description" content="Step-by-step guide to building a production-ready REST API." />
  <meta name="twitter:image" content="https://example.com/images/rest-api-twitter.png" />
  <meta name="twitter:image:alt" content="REST API with Node.js guide banner" />
</head>
<body>
  <!-- Page content -->
</body>
</html>

Ejemplos por Framework

Los frameworks modernos proporcionan APIs integradas para gestionar meta tags:

Next.js (App Router — Metadata API)

// app/blog/[slug]/page.tsx
import { Metadata } from 'next';

type Props = { params: { slug: string } };

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const post = await getPost(params.slug);

  return {
    title: post.title,
    description: post.excerpt,
    alternates: {
      canonical: `https://example.com/blog/${params.slug}`,
    },
    openGraph: {
      type: 'article',
      title: post.title,
      description: post.excerpt,
      url: `https://example.com/blog/${params.slug}`,
      siteName: 'My Dev Blog',
      locale: 'en_US',
      images: [
        {
          url: post.ogImage,      // Must be absolute URL
          width: 1200,
          height: 630,
          alt: post.title,
        },
      ],
      publishedTime: post.date,
      authors: [post.author],
      tags: post.tags,
    },
    twitter: {
      card: 'summary_large_image',
      site: '@yourusername',
      creator: '@authorname',
      title: post.title,
      description: post.excerpt,
      images: [
        {
          url: post.twitterImage,  // Can differ from OG image
          alt: post.title,
        },
      ],
    },
  };
}

export default function BlogPost({ params }: Props) {
  // Page component...
}

Nuxt 3 (useSeoMeta)

<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute();
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`);

useSeoMeta({
  title: post.value.title,
  description: post.value.excerpt,
  ogType: 'article',
  ogTitle: post.value.title,
  ogDescription: post.value.excerpt,
  ogUrl: `https://example.com/blog/${route.params.slug}`,
  ogImage: post.value.ogImage,
  ogImageWidth: 1200,
  ogImageHeight: 630,
  ogImageAlt: post.value.title,
  ogSiteName: 'My Dev Blog',
  ogLocale: 'en_US',
  articlePublishedTime: post.value.date,
  articleAuthor: post.value.author,
  articleTag: post.value.tags,
  twitterCard: 'summary_large_image',
  twitterSite: '@yourusername',
  twitterCreator: '@authorname',
  twitterTitle: post.value.title,
  twitterDescription: post.value.excerpt,
  twitterImage: post.value.twitterImage,
  twitterImageAlt: post.value.title,
});
</script>

<template>
  <article>
    <!-- Page content -->
  </article>
</template>

HTML Estático

<!-- For static HTML sites, simply add meta tags in <head> -->
<!-- You can automate this with a build tool or templating engine -->

<!-- Example with Eleventy (11ty) Nunjucks template -->
<head>
  <title>{{ title }}</title>
  <meta name="description" content="{{ description }}" />
  <meta property="og:type" content="{% if layout == 'post' %}article{% else %}website{% endif %}" />
  <meta property="og:title" content="{{ title }}" />
  <meta property="og:description" content="{{ description }}" />
  <meta property="og:image" content="{{ site.url }}{{ ogImage }}" />
  <meta property="og:url" content="{{ site.url }}{{ page.url }}" />
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content="{{ title }}" />
  <meta name="twitter:description" content="{{ description }}" />
  <meta name="twitter:image" content="{{ site.url }}{{ ogImage }}" />
</head>

<!-- Example with Hugo -->
<!-- layouts/partials/head.html -->
<meta property="og:title" content="{{ .Title }}" />
<meta property="og:description" content="{{ .Description }}" />
<meta property="og:image" content="{{ .Params.ogImage | absURL }}" />
<meta property="og:url" content="{{ .Permalink }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{{ .Title }}" />
<meta name="twitter:image" content="{{ .Params.ogImage | absURL }}" />

Errores Comunes y Soluciones

Los problemas más frecuentes con las meta tags sociales:

#ErrorProblemaSolución
1Relative image URLsog:image="/images/og.png" — platforms cannot resolve relative pathsAlways use absolute URLs: og:image="https://example.com/images/og.png"
2Missing image dimensionsFacebook may not display the image on first share without width/heightAlways include og:image:width and og:image:height tags
3HTTP instead of HTTPSMany platforms reject or warn about non-HTTPS image URLsServe all OG images over HTTPS. Use protocol-relative URLs as last resort
4Not handling cachePlatforms cache previews for hours/days; updating tags has no immediate effectUse platform debug tools to force refresh. Append ?v=2 for cache-busting
5Same tags on every pageEvery page shows the same preview card — confusing and poor CTRGenerate unique og:title, og:description, og:image per page
6Missing twitter:card tagTwitter will not render any card at all without this tagAlways include <meta name="twitter:card" content="summary_large_image" />
7Image too large (>8MB)Facebook silently fails; Twitter shows no imageOptimize images: compress to <1MB, use JPEG for photos, PNG for graphics
8Wrong image aspect ratioImage gets cropped awkwardly — text cut off, faces croppedUse 1200x630 (1.91:1) for OG, 1200x675 (16:9) for Twitter large image
9Duplicate og:image tagsUnpredictable behavior — platform may pick the wrong imageUse only one og:image tag per page (or intentionally provide multiple with primary first)
10Forgetting og:urlShares from different URLs (www vs non-www, query params) counted separatelySet og:url to the canonical URL to consolidate share counts

Herramientas de Prueba y Depuración

Siempre valida tus meta tags antes de publicar. Cada plataforma cachea las vistas previas agresivamente.

HerramientaPlataformaURLNotas
Facebook Sharing DebuggerFacebook / Metadevelopers.facebook.com/tools/debug/Shows all OG tags, image preview, and errors. Click "Scrape Again" to refresh cache.
Twitter Card ValidatorTwitter / Xcards-dev.twitter.com/validatorPreview your Twitter Card. Validates tag structure. Requires Twitter login.
LinkedIn Post InspectorLinkedInlinkedin.com/post-inspector/Validates OG tags for LinkedIn. Click "Inspect" to refresh cached preview.
OpenGraph.xyzUniversalopengraph.xyzPreview how your URL appears on Facebook, Twitter, LinkedIn, Discord simultaneously.
Metatags.ioUniversalmetatags.ioReal-time preview editor. Edit tags and see Facebook/Twitter/Google previews instantly.
Social Share Preview (VS Code)DevelopmentVS Code ExtensionPreview OG tags directly in your IDE without deploying.
Ngrok / Cloudflare TunnelDevelopmentngrok.comExpose localhost to test with real platform validators during development.

Imágenes OG Dinámicas

Generar imágenes sociales únicas por página aumenta dramáticamente la tasa de clics.

Por Qué Importan las Imágenes OG Dinámicas

Sitios como GitHub, Vercel y DEV.to generan imágenes OG por página.

<!-- Instead of this (same image for every page): -->
<meta property="og:image" content="https://example.com/default-og.png" />

<!-- Generate this (unique per page): -->
<meta property="og:image" content="https://example.com/api/og?title=How+to+Build+a+REST+API" />

Generación con @vercel/og

// app/api/og/route.tsx — Next.js Edge Route Handler
import { ImageResponse } from 'next/og';
import { NextRequest } from 'next/server';

export const runtime = 'edge';

export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const title = searchParams.get('title') || 'Default Title';
  const description = searchParams.get('desc') || '';

  return new ImageResponse(
    (
      <div
        style={{
          width: '100%',
          height: '100%',
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'center',
          padding: '60px 80px',
          background: 'linear-gradient(135deg, #0f172a 0%, #1e293b 100%)',
          fontFamily: 'Inter, sans-serif',
        }}
      >
        <div style={{
          fontSize: 56,
          fontWeight: 800,
          color: '#f8fafc',
          lineHeight: 1.2,
          marginBottom: 20,
        }}>
          {title}
        </div>
        {description && (
          <div style={{
            fontSize: 24,
            color: '#94a3b8',
            lineHeight: 1.5,
          }}>
            {description}
          </div>
        )}
        <div style={{
          display: 'flex',
          alignItems: 'center',
          marginTop: 'auto',
          fontSize: 20,
          color: '#64748b',
        }}>
          example.com
        </div>
      </div>
    ),
    {
      width: 1200,
      height: 630,
    }
  );
}

// Usage in metadata:
// openGraph: { images: [`/api/og?title=${encodeURIComponent(post.title)}`] }

Generación con Node Canvas

// scripts/generate-og-images.ts — Build-time generation
import { createCanvas, registerFont } from 'canvas';
import fs from 'fs';
import path from 'path';

registerFont('fonts/Inter-Bold.ttf', { family: 'Inter', weight: 'bold' });

interface OGConfig {
  title: string;
  slug: string;
  theme?: string;
}

function generateOGImage(config: OGConfig): Buffer {
  const { title, theme = '#0f172a' } = config;
  const width = 1200;
  const height = 630;
  const canvas = createCanvas(width, height);
  const ctx = canvas.getContext('2d');

  // Background gradient
  const gradient = ctx.createLinearGradient(0, 0, width, height);
  gradient.addColorStop(0, theme);
  gradient.addColorStop(1, '#1e293b');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, width, height);

  // Title text
  ctx.fillStyle = '#f8fafc';
  ctx.font = 'bold 52px Inter';
  const words = title.split(' ');
  let line = '';
  let y = 240;
  for (const word of words) {
    const test = line + word + ' ';
    if (ctx.measureText(test).width > 1040) {
      ctx.fillText(line.trim(), 80, y);
      line = word + ' ';
      y += 70;
    } else {
      line = test;
    }
  }
  ctx.fillText(line.trim(), 80, y);

  // Site name
  ctx.fillStyle = '#64748b';
  ctx.font = 'bold 24px Inter';
  ctx.fillText('example.com', 80, 560);

  return canvas.toBuffer('image/png');
}

// Generate for all posts
const posts: OGConfig[] = [
  { title: 'How to Build a REST API with Node.js', slug: 'rest-api-nodejs' },
  { title: 'TypeScript Generics Explained', slug: 'typescript-generics' },
];

for (const post of posts) {
  const buffer = generateOGImage(post);
  const outPath = path.join('public', 'og', `${post.slug}.png`);
  fs.mkdirSync(path.dirname(outPath), { recursive: true });
  fs.writeFileSync(outPath, buffer);
  console.log(`Generated: ${outPath}`);
}

Usando Transformaciones URL de Cloudinary

// Using Cloudinary URL-based image transformations
// No server-side code needed — just construct the URL

function getCloudinaryOGImage(title: string): string {
  const cloudName = 'your-cloud-name';
  const baseImage = 'og-template.png';  // Upload a background template first

  // URL-encode the title
  const encodedTitle = encodeURIComponent(title);

  // Cloudinary text overlay transformation
  return [
    `https://res.cloudinary.com/${cloudName}/image/upload`,
    // Resize to OG dimensions
    'w_1200,h_630,c_fill',
    // Add text overlay
    `l_text:Inter_52_bold:${encodedTitle}`,
    'co_rgb:f8fafc',       // Text color
    'g_west',              // Left-align
    'x_80,y_-40',          // Position
    'w_1040,c_fit',        // Max text width
    // Base image
    baseImage,
  ].join('/');
}

// Usage:
// <meta property="og:image"
//   content={getCloudinaryOGImage('How to Build a REST API with Node.js')} />

// Result URL looks like:
// https://res.cloudinary.com/your-cloud-name/image/upload/
//   w_1200,h_630,c_fill/
//   l_text:Inter_52_bold:How%20to%20Build%20a%20REST%20API/
//   co_rgb:f8fafc,g_west,x_80,y_-40,w_1040,c_fit/
//   og-template.png

Preguntas Frecuentes

¿Cuál es la diferencia entre Open Graph y Twitter Card?

Open Graph fue creado por Facebook y es el estándar universal usado por Facebook, LinkedIn, Discord, Slack, WhatsApp, etc. Twitter Cards es el sistema propietario de Twitter/X. Twitter recurre a tags OG si faltan las tags de Twitter.

¿Necesito ambos tipos de tags?

Técnicamente no — Twitter lee las tags OG como respaldo. Pero la mejor práctica es incluir ambos ya que twitter:card no tiene equivalente OG y es necesario para que Twitter muestre una tarjeta.

¿Por qué no aparece mi imagen OG al compartir?

Causas más comunes: URL relativa en lugar de absoluta, URL de imagen devuelve 404, archivo demasiado grande, plataforma ha cacheado versión anterior, tags og:image:width y og:image:height faltantes.

¿Cuál es el tamaño ideal de imagen OG?

El tamaño recomendado es 1200 x 630 píxeles con relación de aspecto 1.91:1.

¿Cómo forzar la actualización de la vista previa OG?

Cada plataforma tiene su propia herramienta: Facebook Sharing Debugger, Twitter Card Validator, LinkedIn Post Inspector.

¿Puedo usar imágenes diferentes para Facebook y Twitter?

Sí. Configura la imagen de Facebook con og:image y la de Twitter con twitter:image. Twitter prefiere twitter:image cuando ambas están presentes.

Crea tags OG y Twitter Card perfectas con nuestro generador de meta tags →

𝕏 Twitterin LinkedIn
¿Fue útil?

Mantente actualizado

Recibe consejos de desarrollo y nuevas herramientas.

Sin spam. Cancela cuando quieras.

Prueba estas herramientas relacionadas

🏷️Meta Tag Generator👁️Open Graph Image Preview📐Schema Markup GeneratorFavicon Generator

Artículos relacionados

Guía Favicon 2026: Todos los tamaños, formatos y cómo generarlos

Referencia completa de favicon 2026. ICO vs PNG vs SVG, todos los tamaños.

Meta Tags esenciales para todo sitio web: Guía completa de meta tags HTML

Meta tags HTML esenciales para SEO, Open Graph, Twitter Cards, seguridad y rendimiento. Plantilla completa lista para copiar.