
⚡ Cómo añadir tu propio shortcode en WordPress: ejemplos y código
Usted necesita mostrar la última fecha de actualización de un artículo en el pie de cada entrada. O insertar un formulario de suscripción exactamente en la mitad del texto, sin malabares con editores de código ni plantillas. En WordPress, los shortcodes son la herramienta para esto.
Un shortcode es una etiqueta corta entre corchetes: [myshortcode]. WordPress la encuentra en el contenido y la reemplaza con el resultado de una función PHP. Usted usa shortcodes estándar como [gallery] y [embed] todo el tiempo sin siquiera pensarlo. Pero su propio shortcode es una palanca: escribe la lógica una vez y el editor la inserta en cualquier lugar con tres clics.
En 10 minutos creará su primer shortcode funcional: desde una función vacía hasta una etiqueta con atributos y contenido anidado. El código es real, funciona en cualquier WordPress moderno y ha sido probado en un sitio de pruebas.
💡 Resumen rápido:
- La función
add_shortcode: qué acepta y cómo funciona internamente - Un shortcode básico
[current_year], el año actual en texto - Un shortcode con atributos
[cta text="Скачать"], un botón personalizado - Un shortcode con contenido anidado
[notice]Текст[/notice], un bloque con estilo - Añadirlo mediante un plugin o
functions.php: ventajas y desventajas de cada enfoque - Errores comunes:
echoen lugar dereturn, conflictos de nombres, atributo vacío en PHP 8+
Qué puede hacer add_shortcode y cómo funciona
La función add_shortcode es la única forma estándar de registrar un nuevo shortcode en WordPress. Acepta dos parámetros:
$tag(string), el nombre del shortcode que escribirá entre corchetes. Solo letras, números y guiones bajos. Los espacios y caracteres especiales& / < > [ ] =están prohibidos; WordPress se negará silenciosamente a registrar dicha etiqueta.$callback(callable), el nombre de la función PHP que se ejecutará cuando se encuentre el shortcode. Esta función genera el HTML que verá el visitante.
El código fuente de la función, cinco líneas de lógica y dos comprobaciones de seguridad (listado completo en developer.wordpress.org):
1 function add_shortcode( $tag, $callback ) { 2 global $shortcode_tags; 3 4 if ( '' === trim( $tag ) ) { 5 _doing_it_wrong( 6 __FUNCTION__, 7 __( 'Invalid shortcode name: Empty name given.' ), 8 '4.4.0' 9 ); 10 return; 11 } 12 13 if ( 0 !== preg_match( '@[<>&/\[\]\x00-\x20=]@', $tag ) ) { 14 _doing_it_wrong( 15 __FUNCTION__, 16 sprintf( 17 /* translators: 1: Shortcode name, 2: Space-separated list of reserved characters. */ 18 __( 'Invalid shortcode name: %1$s. Do not use spaces or reserved characters: %2$s' ), 19 $tag, 20 '& / < > [ ] =' 21 ), 22 '4.4.0' 23 ); 24 return; 25 } 26 27 $shortcode_tags[ $tag ] = $callback; 28 }
El punto clave: $shortcode_tags, un array global. WordPress almacena en él todos los shortcodes registrados. Durante el renderizado del contenido, el núcleo itera sobre este array y llama a la función asociada para cada etiqueta encontrada. De esto se derivan dos implicaciones:
- *Registrar en el hook
init.* Si llama aadd_shortcodedirectamente en un archivo de plugin, podría ejecutarse antes de que WordPress esté completamente inicializado. La forma correcta es envolverlo en un hook:
1 add_action( 'init', 'my_register_shortcodes' ); 2 3 function my_register_shortcodes() { 4 add_shortcode( 'mytag', 'my_shortcode_callback' ); 5 }
- Un prefijo es obligatorio. El array global es compartido por todos los plugins y el tema. Si nombra un shortcode
[button], su[button]sobrescribe silenciosamente el mismo shortcode de un plugin de formularios. Un prefijo comomyplugin_o una abreviatura única resuelve el problema. En los ejemplos siguientes uso el prefijomysite_; en un proyecto real, sustitúyalo por el suyo propio.
Paso 1: un shortcode simple sin parámetros
El camino más corto hacia un shortcode funcional, tres líneas en el functions.php de su tema hijo (o en el plugin Code Snippets, que es más seguro y no se perderá al actualizar el tema).
Añada este código y guarde:
1 add_shortcode( 'mysite_current_year', 'mysite_display_current_year' ); 2 3 function mysite_display_current_year() { 4 return date( 'Y' ); 5 }
Ahora escriba [mysite_current_year] en cualquier entrada o página. En el front-end, el año actual aparecerá en lugar del shortcode: «2026».
Qué sucede aquí. La función mysite_display_current_year no recibe argumentos, llama a la función PHP date('Y') y devuelve una cadena de cuatro dígitos. WordPress inserta esta cadena exactamente donde se colocó el shortcode. Sin magia.
Dónde aplicar esto en la práctica: el año en el pie de página (© [mysite_current_year]), la antigüedad del proyecto en el texto («trabajando desde [mysite_current_year]»), la actualización automática de fechas en páginas de cumplimiento legal.
Paso 2: un shortcode con atributos
Un shortcode sin parámetros es útil, pero la verdadera flexibilidad comienza con los atributos. El ejemplo clásico, un botón con texto personalizable y un enlace:
1 add_shortcode( 'mysite_cta', 'mysite_cta_button' ); 2 3 function mysite_cta_button( $atts ) { 4 $atts = shortcode_atts( 5 array( 6 'text' => 'Learn more', 7 'url' => '#', 8 ), 9 $atts, 10 'mysite_cta' 11 ); 12 13 return sprintf( 14 '<a href="%s" class="mysite-cta-button">%s</a>', 15 esc_url( $atts['url'] ), 16 esc_html( $atts['text'] ) 17 ); 18 }
En el editor, úselo así:
1 [mysite_cta text="Download plugin" url="https://example.com/myplugin/"]
La función shortcode_atts hace tres cosas a la vez: combina los atributos del usuario con los valores predeterminados, filtra solo las claves conocidas y normaliza una cadena vacía convirtiéndola en un array (sin esto, llamar a [mysite_cta] sin atributos en PHP 8+ lanzaría un TypeError, porque el primer parámetro de la función de callback recibiría una cadena vacía en lugar de un array).
*Por qué esc_url y esc_html.* Un shortcode lo inserta un editor, hoy es usted, y mañana un gestor de contenidos sin acceso al código. El escapado de salida protege contra XSS accidental si un corchete o etiqueta termina en el atributo text.
Paso 3: un shortcode con contenido incluido
Algunos shortcodes envuelven un fragmento de texto: [mysite_notice]Важное сообщение[/mysite_notice]. El contenido incluido llega al callback como segundo parámetro, $content. Un escenario típico, un bloque de advertencia con estilo:
1 add_shortcode( 'mysite_notice', 'mysite_notice_box' ); 2 3 function mysite_notice_box( $atts, $content = null ) { 4 $atts = shortcode_atts( 5 array( 6 'type' => 'info', 7 ), 8 $atts, 9 'mysite_notice' 10 ); 11 12 $class = 'notice-' . esc_attr( $atts['type'] ); 13 14 return sprintf( 15 '<div class="mysite-notice %s"><p>%s</p></div>', 16 $class, 17 do_shortcode( $content ) 18 ); 19 }
Observe el do_shortcode( $content ). Si el editor insertó otro shortcode dentro de su shortcode (por ejemplo [mysite_current_year]), esta envoltura también lo ejecutará. Sin do_shortcode, los shortcodes anidados se mostrarán como texto entre corchetes, [mysite_current_year] en bruto en lugar de «2026».
CSS para el bloque, mínimo, para empezar:
1 .mysite-notice { 2 border-left: 4px solid #2271b1; 3 background: #f0f6fc; 4 padding: 1em 1.2em; 5 margin: 1.5em 0; 6 border-radius: 4px; 7 } 8 .mysite-notice.notice-warning { 9 border-left-color: #dba617; 10 background: #fcf9e8; 11 }
Añada los estilos al style.css de su tema hijo o mediante Apariencia → Personalizar → CSS adicional.
Paso 4: un shortcode dentro de un plugin (enfoque de POO)
Cuando tiene más de tres shortcodes, functions.php se convierte en un cajón de sastre. Es momento de mover la lógica a un plugin separado, e idealmente a una clase. Aquí tiene un esqueleto de mini-plugin con un shortcode:
1 <?php 2 /** 3 * Plugin Name: MySite Shortcodes 4 * Description: Custom shortcodes for the site. 5 * Version: 1.0.0 6 * Requires PHP: 7.4 7 */ 8 9 defined( 'ABSPATH' ) || exit; 10 11 class MySite_Shortcodes { 12 13 public static function init() { 14 add_action( 'init', array( __CLASS__, 'register' ) ); 15 } 16 17 public static function register() { 18 add_shortcode( 'mysite_email', array( __CLASS__, 'email_obfuscated' ) ); 19 } 20 21 public static function email_obfuscated( $atts ) { 22 $atts = shortcode_atts( 23 array( 'address' => '' ), 24 $atts, 25 'mysite_email' 26 ); 27 28 if ( ! is_email( $atts['address'] ) ) { 29 return ''; 30 } 31 32 return sprintf( 33 '<a href="mailto:%1$s">%1$s</a>', 34 antispambot( $atts['address'], 1 ) 35 ); 36 } 37 } 38 39 MySite_Shortcodes::init();
Coloque este archivo en wp-content/plugins/mysite-shortcodes/mysite-shortcodes.php y active el plugin en el panel de administración. El shortcode [mysite_email address="hello@example.com"] generará un enlace protegido contra bots de spam; la función antispambot codifica los caracteres del correo en entidades HTML.
Por qué una clase, no un conjunto de funciones. Espacio de nombres: tres shortcodes en una clase no colisionarán con funciones de terceros. Además, autocarga y código legible si el plugin crece hasta una docena de shortcodes.
Probar un shortcode antes de publicar
Después de añadir el código, verifique tres escenarios:
- Shortcode sin atributos. Solo
[mysite_cta], debe renderizarse con los valores predeterminados (texto «Más información», enlace#). - Shortcode con atributos. Un conjunto completo de parámetros, todos los valores se recogen y se muestran correctamente.
- Error en los atributos. Un correo electrónico no válido en
[mysite_email], la función devuelve silenciosamente una cadena vacía en lugar de romper la página.
Importante: nunca use echo dentro de una función de callback. Un shortcode debe devolver una cadena mediante return. Si emite HTML con echo, aparecerá no donde está el shortcode, sino al principio de la página, porque WordPress ejecuta el renderizado del shortcode antes de la salida del contenido. La misma lógica que los filtros: la función entrega un valor y el propio motor decide dónde insertarlo.
Un segundo matiz: si el shortcode no se muestra (ve [mysite_cta] como texto, no como botón), compruebe que la función está registrada en el hook init, no directamente en el cuerpo del plugin. Sin init, el array global $shortcode_tags podría no estar aún listo para aceptar nuevas etiquetas.
Shortcode en un tema vs. un plugin: qué elegir
Criterio |
| Plugin separado |
|---|---|---|
Velocidad de arranque | Más rápido: el archivo ya está cargado | Ligeramente más lento: archivo separado |
Portabilidad | Vinculado al tema | Funciona con cualquier tema |
Supervivencia a actualizaciones | Se pierde al actualizar el tema | Vive de forma independiente |
Comodidad de edición | Apariencia → Editor de archivos del tema | Editor de plugins o FTP |
Para cuántos shortcodes | 1-3 | 4+ |
La regla: empiece con functions.php en un sitio de pruebas, construya tres shortcodes y luego muévalos a un plugin. Una actualización del tema seis meses después no enterrará su lógica y podrá transferir los shortcodes a otro proyecto en un minuto.
⁉️🤔 FAQ
¿Cuál es la diferencia entre un shortcode y un bloque de Gutenberg?
Un shortcode es una etiqueta de texto entre corchetes que se procesa en el lado del servidor. Un bloque es un componente visual del editor, un componente React con ajustes en la barra lateral. Los shortcodes aparecieron en WordPress 2.5 (2008), los bloques en 5.0 (2018). Hoy los bloques son la forma principal de insertar contenido dinámico, pero los shortcodes siguen siendo relevantes: son más sencillos de desarrollar, no requieren conocimientos de JavaScript y funcionan en cualquier editor, incluido el Editor Clásico y los maquetadores visuales.
Un shortcode es una etiqueta de texto que WordPress reemplaza con el resultado de una función PHP al renderizar la página. A diferencia de un bloque de Gutenberg, un shortcode no tiene interfaz visual en el editor: el gestor de contenido escribe
[myshortcode]como texto y ve el HTML final en el front end.
¿Puedo usar un shortcode dentro de otro shortcode?
Sí. Si la función de devolución de llamada del shortcode externo envuelve el contenido anidado en do_shortcode(), los shortcodes internos funcionarán correctamente: [notice][current_year][/notice] mostrará un bloque con estilo con el año actual. Sin do_shortcode(), el shortcode anidado permanecerá como texto entre corchetes.
Los shortcodes anidados se procesan de forma recursiva: WordPress recorre la cadena varias veces hasta que no quedan etiquetas sin procesar. Pero para que esto funcione, el shortcode externo debe llamar explícitamente a
do_shortcode($content). De lo contrario, la cadena[current_year]se mantendrá como texto en lugar de convertirse en «2026».
¿Por qué mi shortcode no funciona y se muestra como texto entre corchetes?
Tres razones comunes. Primera: add_shortcode se llama antes del hook init, mueva el registro dentro de add_action('init', ...). Segunda: un error tipográfico en el nombre de la etiqueta, [my_shortcode] en el editor pero myshortcode está registrado. Tercera: la función de devolución de llamada usa echo en lugar de return, por lo que la salida va al principio de la página y la ubicación del shortcode queda vacía.
El culpable más frecuente es
echoen lugar dereturnen la función de devolución de llamada. WordPress llama a los manejadores de shortcodes antes de mostrar el contenido principal, por lo que el resultado delechollega al búfer de salida antes que la cabecera de la página. Abra el código fuente de la página (Ctrl+U): si ve el HTML del shortcode en la parte superior, antes de<html>, ese es exactamente el problema.
¿Necesito escapar la salida del shortcode?
Absolutamente. Un shortcode acepta atributos desde el editor, lo que significa potencialmente de cualquier usuario con permisos de autor o editor. esc_html() para texto, esc_url() para enlaces, esc_attr() para atributos HTML. La excepción es cuando intencionadamente devuelve marcado HTML (como <div class="notice">). Pero incluso entonces, escape los atributos dentro del marcado.
Sí, el escapado es obligatorio para todo lo que provenga de atributos de shortcode o entrada de usuario. Incluso si hoy solo usted inserta shortcodes, mañana un gestor de contenido obtendrá acceso de editor.
esc_html()para texto,esc_url()para enlaces,esc_attr()para atributos HTML protegen contra XSS accidental o intencionado.
¿Cuántos shortcodes puedo registrar en un sitio?
No hay límite técnico: $shortcode_tags es un array PHP normal, alcanzará el límite de memoria del servidor mucho después de lo que dicta el sentido común. En la práctica, después de 15-20 shortcodes personalizados vale la pena preguntarse: ¿es momento de migrar algunos a bloques de Gutenberg? Conserve los shortcodes con lógica única (ofuscación de correo electrónico, salida condicional por rol). Para shortcodes que solo estilizan texto ([highlight]), es mejor usar un estilo de bloque o una clase CSS.
Técnicamente, tantos como quiera: el array
$shortcode_tagsno tiene límite artificial. En la práctica, más de 20-25 shortcodes en un sitio sugiere que parte de la lógica debería moverse a bloques. Cada shortcode añade sobrecarga de análisis de contenido: antes de la salida, WordPress itera sobre todo el array de etiquetas registradas y busca coincidencias en el texto de la entrada.
¿Debería escribir mis propios shortcodes o bastan los plugins ya hechos?
Un plugin ya hecho cubre la mayoría de las tareas típicas: formularios, Contact Form 7, tablas, TablePress, cuadrículas, cualquier maquetador visual. Un shortcode personalizado es necesario cuando la lógica es específica de su sitio y no existe una solución ya hecha: mostrar un campo personalizado exactamente en este punto de la página, la fecha del próximo webinar desde la base de datos, un saludo personalizado según el rol del usuario.
En resumen: para funcionalidad estándar, use un plugin y no programe. Para lógica única, add_shortcode + functions.php o un mini-plugin. El código en cualquiera de los ejemplos anteriores no llega a diez líneas. Una vez que domine estos tres patrones (simple, con atributos, con contenido anidado), cubrirá la gran mayoría de las tareas para las que se escriben shortcodes personalizados.



