Glossary

What Are WordPress Shortcodes? A Practical Guide

May 20, 2026

WordPress shortcodes are short text snippets wrapped in square brackets (like [contact-form] or [gallery ids="1,2,3"]) that WordPress replaces with dynamic content when rendering a post or page. They were introduced in WordPress 2.5 (2008) and became the dominant way plugins added complex output to content for over a decade. Since the rollout of the Gutenberg block editor in WordPress 5.0 (2018), shortcodes have a successor: blocks. But shortcodes are not going away. They still work, millions of sites depend on them, and many plugins continue to ship them alongside or instead of blocks.

What does a WordPress shortcode look like?

The basic shortcode is a name in square brackets:

[gallery]

WordPress sees this in the post content, looks up the registered handler for gallery, runs the PHP function, and replaces the tag with whatever HTML the handler outputs. The visitor sees a gallery; the editor sees [gallery].

Shortcodes can take parameters (called attributes):

[gallery ids="42,43,44" columns="3" link="file"]

And they can wrap content (called enclosing shortcodes):

[highlight color="yellow"]Important text[/highlight]

The shortcode handler receives the attributes and the inner content, processes them in PHP, and returns the HTML to insert into the page. The visitor never sees the brackets; they see the rendered output.

What is the difference between a shortcode and a Gutenberg block?

Both produce dynamic content; they differ in where and how that content is generated.

  • Shortcodes are server-side. The square-bracket tag stays in the post content stored in the database. When the page is requested, WordPress parses the content, finds the shortcode, runs the PHP handler, and substitutes the output. The editor view always shows the raw bracket syntax.
  • Blocks are stored as rendered HTML (with metadata comments). When you save a post in the block editor, the block plugin generates the final HTML and stores it in the database. The editor shows a live preview of the rendered block, not a tag. On the frontend, no PHP runs to render most blocks; the HTML is served directly.

Practical consequences:

  • Performance. Blocks are faster on the frontend because there is no parse-and-replace step. Shortcodes trigger a regex scan of every post on every render.
  • Editing experience. Blocks show what the rendered output will look like as you edit. Shortcodes show only the tag; you preview the result.
  • Portability. If you deactivate the plugin that provides a block, the stored HTML usually remains visible (frozen at the version when last saved). If you deactivate the plugin that provides a shortcode, the bracket tag is left in the content as plain text, which usually looks broken.
  • Reusability. Shortcodes can be added anywhere PHP runs, including in widgets, templates and excerpts. Blocks are designed for the block editor area, though "Reusable Blocks" and the FSE (full-site editing) movement are closing that gap.

Which built-in WordPress shortcodes still ship in core?

WordPress core has historically shipped a handful of shortcodes. As of 2026, the surviving ones in the codebase:

  • [gallery] — Image gallery. Still used by the classic editor and as a fallback when the Gallery block is converted.
  • [caption] — Wraps an image with a caption. Mostly replaced by the Image block but still emitted in some workflows.
  • [audio] and [video] — Native HTML5 player for self-hosted media.
  • [embed] — Forces a URL to be embedded via the oEmbed handler. Rarely needed because WordPress auto-embeds most URLs.
  • [playlist] — Audio and video playlists. Niche use.

The vast majority of shortcodes in any real WordPress site come from plugins and themes, not core.

What kinds of plugins use shortcodes?

Five categories cover almost all real-world shortcode usage:

  • Contact forms. Contact Form 7 ([contact-form-7 id="123"]), WPForms, Gravity Forms and Formidable all expose forms via shortcodes. Even when these plugins also offer Gutenberg blocks, the shortcode remains supported for backward compatibility.
  • E-commerce. WooCommerce uses shortcodes for the Cart, Checkout, My Account and product listings ([products limit="4"]). The block editor now has equivalent blocks, but shortcodes still dominate because most themes were built around them.
  • Page builders (in legacy mode). Old Visual Composer, WPBakery and similar produce massive nested shortcodes when used in the classic editor. Switching off the page builder leaves a wall of [vc_row][vc_column]... tags as plain text in the post — a famous lock-in problem.
  • Pricing tables, sliders, accordions. Most "content widget" plugins (Soliloquy, Smart Slider, Easy Pricing Tables) historically shipped as shortcodes. Many are still actively maintained but have added blocks.
  • Membership and learning sites. MemberPress, LearnDash and similar restrict content with shortcode wrappers like [restrict role="member"]...[/restrict].

How does a shortcode actually work under the hood?

Three lines of plugin code create a shortcode. This minimal example registers a shortcode that outputs a yellow highlight:

add_shortcode('highlight', function ($atts, $content = null) {
    $atts = shortcode_atts([
        'color' => 'yellow',
    ], $atts, 'highlight');

    return '<mark style="background:' . esc_attr($atts['color']) . '">' . do_shortcode($content) . '</mark>';
});

What happens when WordPress renders [highlight color="pink"]Hello[/highlight]:

  1. WordPress runs the the_content filter, which includes do_shortcode().
  2. do_shortcode() uses a regex to find shortcode tags in the post content.
  3. For each match, it calls the registered handler with the attributes (['color' => 'pink']) and the inner content ('Hello').
  4. The handler returns a string, which replaces the shortcode tag in the output.
  5. The post content is then rendered to the browser with the tag substituted.

The regex parse on every post render is the performance cost. On a site with thousands of posts, no caching and shortcodes in every post, this adds up. A page cache (Redis, WP Super Cache) fixes this by storing the final rendered HTML and skipping the parse.

When should I still use shortcodes in 2026?

Three legitimate cases:

  • Backward compatibility. If your site already uses shortcodes from Contact Form 7, WooCommerce or any established plugin, keep using them. Mass-converting old posts to blocks is a multi-day project with little payoff.
  • Outside the block editor. Widgets (in classic widget areas), excerpts, custom post type loops, page-builder content, and emails sent via Mailchimp templates still accept shortcodes but not blocks. Shortcodes work in any context where do_shortcode() can be called.
  • Templates and theme code. Putting echo do_shortcode('[my-form id="3"]'); in a PHP template is a one-line way to inject plugin output. Blocks would require server-side block rendering, which is more code.

For genuinely new functionality on a new site, prefer blocks. They are the WordPress core direction, have a better editing experience, and avoid the shortcode parse overhead.

What is "shortcode bloat" and why does it matter?

Shortcode bloat happens when a site relies on dozens of shortcodes from inactive or deactivated plugins. Two failure modes follow:

  • Plugin deactivated but tags remain. You deactivate a slider plugin to test something. Every page that had [slider id="3"] now displays the literal text "[slider id="3"]" instead of a slider. The fix is reactivating the plugin or manually removing all shortcode tags from the database, which is tedious.
  • Page builder migration. A site built in Visual Composer or WPBakery contains nested shortcodes like [vc_row][vc_column width="1/2"][vc_column_text]Hello[/vc_column_text][/vc_column][/vc_row]. Switching themes or deactivating the builder reveals all this as plain text. This is the source of the "I cannot migrate my site to Gutenberg" pain point that has trapped thousands of sites.

The pragmatic prevention: choose plugins that you commit to long-term, and prefer plugins that also support blocks so you can migrate gradually. For sites built before 2018, expect a real migration project rather than a clean switch.

Can I create my own shortcode without writing a plugin?

Yes, three ways:

  1. In a child theme's functions.php. Add the add_shortcode() call. The shortcode becomes available everywhere on the site. Works but the shortcode is tied to that theme; switch themes and the shortcode disappears.
  2. In a custom mu-plugin. Create wp-content/mu-plugins/my-shortcodes.php and put your add_shortcode() calls there. Survives theme switches and most updates. The cleaner solution.
  3. Via a "Code Snippets" plugin. Plugins like Code Snippets or WPCode let you add PHP through the admin UI. Convenient if you cannot edit files, but adds an admin-level dependency for code that ideally lives in files.

What are common shortcode mistakes?

  • Forgetting do_shortcode() on inner content. If your shortcode wraps content (an enclosing shortcode), you should call do_shortcode($content) on the inner part so nested shortcodes work. Without it, [outer][inner][/outer] renders only the outer shortcode and leaves [inner] as plain text.
  • Echoing inside the handler. Shortcode handlers must return their output, not echo it. An echoed shortcode renders before the content it is embedded in, breaking page layout in subtle ways.
  • Forgetting esc_attr() on attributes. Without escaping, user-provided attribute values can break out of the HTML and create XSS vulnerabilities. Always escape what you output.
  • Shortcodes in widgets that do not run them. Some classic widget types (like the basic Text widget pre-WordPress 4.9) do not auto-execute shortcodes. Fix: add_filter('widget_text', 'do_shortcode');.
  • Tags inside other tags causing parse confusion. A shortcode attribute containing a square bracket character ([shortcode label="Click [here]"]) confuses the parser. WordPress handles many cases but not all; using HTML entities (&#91; and &#93;) is the safe workaround.
  • Adding shortcodes to do_shortcode recursively. Inside a shortcode handler, calling do_shortcode() on content that contains the same shortcode creates an infinite loop. WordPress has guards against this but the symptom is a blank page or a memory exhaustion error.

How do I find every shortcode used on my site?

Three quick approaches:

  1. Database search. Run a SQL query against wp_posts: SELECT DISTINCT REGEXP_SUBSTR(post_content, '\\[[a-z_-]+') FROM wp_posts WHERE post_status = 'publish';. Lists every shortcode tag that appears in published content.
  2. WP-CLI. wp shortcode list shows every registered shortcode handler. Compare against the database list to find shortcodes that are used but no longer have an active handler (likely from a deactivated plugin).
  3. The "Shortcode Cleaner" or "Find My Blocks" type plugins. Scan content for shortcode and block usage. Useful before deactivating a plugin to see how widely its shortcodes are used.

What about security?

Shortcodes themselves are not insecure; the question is what the handler does with attributes. Two threat models:

  • An untrusted user submits content containing shortcodes. If a contributor or subscriber can submit posts and the shortcode runs server-side code (like [exec command="..."] from a dev plugin), that is an arbitrary code execution path. WordPress core strips shortcodes from content submitted by low-privilege users by default; do not undo this protection.
  • Shortcode attributes are output unsafely. A poorly written shortcode might echo [badge text="..."] straight into the page without escaping, allowing an admin who edits a post to inject script tags. Stick to admins-only editing for posts, and always escape attribute values when writing custom shortcodes.

What InspectWP checks

Shortcodes are not directly part of an InspectWP security or performance report, but their effects show up in several places. A site with shortcodes from deactivated plugins typically has "broken layouts" findings (rendered text containing square brackets). A site with heavy shortcode use without page caching shows up as slow TTFB. And a site where Visual Composer or WPBakery shortcodes leak into the rendered HTML (because the page builder is broken or deactivated) shows up as render errors and accessibility violations. The recommended pattern in 2026 is to keep using shortcodes for legacy reasons, prefer blocks for new content, and audit your site periodically for shortcodes whose handlers are no longer registered.

Check your WordPress site now

InspectWP analyzes your WordPress site for security issues, SEO problems, GDPR compliance, and performance — for free.

Analyze your site free