WordPress Shortcode Example: Build a Safe Output Block With Attributes
Build a safe WordPress shortcode with shortcode_atts, sanitized attributes, escaped output, controlled HTML, CSS loading, and production testing.
Published
April 16, 2026
Reading Time
5 min read
Updated
May 4, 2026

Implementation Notes
Extension points, code paths, and implementation choices that should survive contact with production.
Best For
WordPress developers, agencies, and technical teams building custom plugin or theme functionality with cleaner operational defaults.
Primary Topics
Editorial Focus
Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on May 4, 2026.
Full Report
Last reviewed: April 16, 2026
“WordPress shortcode example” is one of those searches that looks simple until the snippet reaches production. A shortcode can be a useful bridge for editors, but it can also create fragile markup, unescaped output, broken layouts, and theme-specific behavior hidden inside post content.
This guide shows how to build a small, safe shortcode with attributes, escaping, and predictable output. It also explains when a shortcode is the right tool and when a block, pattern, template part, or plugin setting would be cleaner.
WordPress shortcode example with attributes
The safest shortcode examples treat attributes as user input. Define defaults with shortcode_atts(), restrict values such as type or layout to an allowed list, sanitize each attribute according to the data it represents, and escape the final value for the exact HTML context. The shortcode callback should return a string so output lands where WordPress expects it inside post content.
Who this is for
This article is for WordPress developers and site maintainers who need to give editors a reusable content element without creating a full custom block. It is especially useful for agencies maintaining older sites where shortcodes already exist and need to be cleaned up rather than removed overnight.
When a shortcode is still useful
Shortcodes are not the newest WordPress interface, but they remain useful when the requirement is narrow and text-editor friendly. Examples include callout boxes, reusable disclosures, embed wrappers, tracked links, simple product cards, or temporary campaign components.
Use a shortcode when:
- editors need to place a small reusable output inside post content;
- the markup can be generated from a few attributes;
- the behavior is stable and not deeply visual-builder dependent; and
- the team understands that the shortcode becomes part of stored content.
Do not use a shortcode as a dumping ground for complex application logic. If the feature needs complex editing UI, nested layout controls, or long-term design evolution, a block or plugin screen is usually better.
A safe shortcode plugin example
The example below registers a [vulnwp_notice] shortcode that outputs a controlled editorial notice. It accepts title, type, and content. The output is escaped, the allowed types are restricted, and the HTML is generated in one place.
<?php
/**
* Plugin Name: VulnWP Notice Shortcode
* Description: Adds a safe editorial notice shortcode with controlled attributes.
* Version: 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_shortcode( 'vulnwp_notice', 'vulnwp_render_notice_shortcode' );
function vulnwp_render_notice_shortcode( $atts, $content = null ) {
$atts = shortcode_atts(
array(
'title' => 'Operational note',
'type' => 'info',
),
$atts,
'vulnwp_notice'
);
$allowed_types = array( 'info', 'warning', 'success' );
$type = sanitize_key( $atts['type'] );
if ( ! in_array( $type, $allowed_types, true ) ) {
$type = 'info';
}
$title = sanitize_text_field( $atts['title'] );
$body = wp_kses_post( do_shortcode( $content ?? '' ) );
if ( '' === trim( $body ) ) {
return '';
}
ob_start();
?>
<aside class="vulnwp-notice vulnwp-notice--<?php echo esc_attr( $type ); ?>">
<strong class="vulnwp-notice__title"><?php echo esc_html( $title ); ?></strong>
<div class="vulnwp-notice__body">
<?php echo $body; ?>
</div>
</aside>
<?php
return ob_get_clean();
}
How editors use it
[vulnwp_notice title="Before you deploy" type="warning"]
Test the shortcode on a staging page, then verify the rendered HTML after cache purge.
[/vulnwp_notice]
The output is intentionally constrained. Editors can change the message and the type, but they cannot inject arbitrary classes, scripts, or unreviewed markup through attributes.
What this example gets right
It uses shortcode_atts(). Shortcode attributes should have defaults and a known shape. This prevents fragile checks throughout the render function.
It sanitizes attributes separately from content. Attribute values are not the same as body HTML. The title is plain text, the type is a key, and the body allows limited post HTML through wp_kses_post().
It escapes at output time. esc_attr() and esc_html() protect the final HTML context. Sanitizing early is useful, but escaping for the exact output context is still necessary.
It returns a string. Shortcode callbacks should return output. Echoing directly often causes content to appear in the wrong place because WordPress expects the shortcode renderer to hand back a string.
It fails closed. If the body is empty, the shortcode returns an empty string instead of rendering a meaningless wrapper.
Add shortcode CSS correctly
If the shortcode needs styling, enqueue a small stylesheet from the plugin instead of relying on the active theme. The shortcode is plugin-owned, so its minimum required CSS should be plugin-owned too.
add_action( 'wp_enqueue_scripts', 'vulnwp_notice_shortcode_assets' );
function vulnwp_notice_shortcode_assets() {
wp_enqueue_style(
'vulnwp-notice-shortcode',
plugin_dir_url( __FILE__ ) . 'notice.css',
array(),
'1.0.0'
);
}
If performance matters on a large site, conditionally enqueue the stylesheet only when the shortcode is present in the current post content. Keep that optimization simple and test it with archives, previews, and cached pages.
Production checklist
- Register the shortcode in a plugin if content depends on it long term.
- Use a prefixed shortcode tag, such as
vulnwp_notice, notnotice. - Define default attributes with
shortcode_atts(). - Sanitize attributes according to their expected data type.
- Escape output according to HTML context.
- Return a string from the callback instead of echoing directly.
- Document the shortcode syntax for editors.
- Plan a migration path if the shortcode may eventually become a custom block.
Common shortcode mistakes
- Using generic shortcode names. A shortcode called
[button]can collide with a theme or plugin. - Trusting attributes. Shortcode attributes are user input and should be sanitized.
- Echoing output. It may render outside the expected content flow.
- Adding business logic to post content. Shortcodes should render content, not hide application workflows.
- Removing a shortcode without migration. Old posts may expose raw shortcode text to visitors.
How to audit existing shortcodes
On a production site, search the database or export for shortcode tags before changing code. If a shortcode exists in many old posts, removing it can break visible content. Treat it like an API contract: find usage, identify ownership, write replacements, and test output before cleanup.
If the shortcode belongs to a plugin you no longer trust, pair the audit with our inactive plugin removal checklist. If the shortcode outputs scripts or embeds, also review our asset enqueue guide, wpdb::prepare example, and WordPress nonce example so dynamic output, SQL, and state-changing actions are reviewed together.
Testing shortcode output before rollout
Test shortcodes with the same discipline you would use for a small API. The stored post content is the input, and the rendered HTML is the output contract. A safe rollout should include normal usage, missing attributes, invalid attributes, empty content, nested shortcodes if supported, and a post preview.
[vulnwp_notice]
Default notice content.
[/vulnwp_notice]
[vulnwp_notice title="Invalid type test" type="script"]
The type should fall back to info.
[/vulnwp_notice]
[vulnwp_notice title="Empty body" type="warning"][/vulnwp_notice]
View the rendered source after each test. Confirm that the wrapper class is controlled, the title is escaped, the body allows only expected post HTML, and no raw shortcode text leaks into the frontend. If the shortcode is already used across many posts, test archive pages too because excerpts and previews can process content differently from single articles.
Migration note for modern WordPress
Shortcodes are still valid, but they should not be the default answer for every reusable UI. If editors need previews, layout controls, nested elements, or design-system alignment, plan a block. If the shortcode already exists and has content history, keep it stable until a migration path exists. Removing it abruptly creates visible content debt.


