Shortcode Generator

Typed attributes, shortcode_atts() defaults and the right escaping function for every value — without you having to remember which is which.

team-grid.php
Saved just now
The shortcode
[]
Lowercase, underscores rather than dashes, and prefixed so no other plugin claims it first.
Attributes
The type decides the sanitiser and the escaping.
titletext
sanitize_text_field() → esc_html()
columnsnumber
absint()
layoutselect
in_array() against the choices → esc_attr()
Output markup
Write HTML. Drop an attribute in with {name}.
Insert:
Behaviour
Enclosing shortcode
Accepts wrapped content as {content}
Run in classic text widgets
Run in excerpts
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io).
/**
 * [team_grid] shortcode.
 *
 * @param array $atts {
 *     Shortcode attributes.
 *
 *     @type string $title   Heading shown above the grid. Default 'Our team'.
 *     @type int $columns How many columns to render. Default '3'.
 *     @type string $layout  Grid or single-column list. Default 'grid'.
 * }
 * @return string Rendered HTML.
 */
function mytheme_team_grid_shortcode( $atts ) {
	$atts = shortcode_atts(
		array(
			'title'   => 'Our team',
			'columns' => '3',
			'layout'  => 'grid',
		),
		$atts,
		'team_grid'
	);

	$title = sanitize_text_field( $atts['title'] );
	$columns = absint( $atts['columns'] );
	$layout = in_array( $atts['layout'], array( 'grid', 'list' ), true ) ? $atts['layout'] : 'grid';

	return sprintf(
		'<section class="team-grid team-grid--%s" style="--columns: %s">' . "\n" .
		'	<h2 class="team-grid__title">%s</h2>' . "\n" .
		'</section>',
		esc_attr( $layout ),
		$columns,
		esc_html( $title )
	);
}
add_shortcode( 'team_grid', 'mytheme_team_grid_shortcode' );

About this generator

Shortcode Generator Online

Declare the attributes your shortcode takes, paste the HTML it should return, and this WordPress shortcode generator writes the whole add_shortcode() registration: a shortcode_atts() defaults array, a typed sanitiser per attribute, an escaped sprintf() for the markup, and a full docblock. Placeholders in your markup written as {attribute} become the sprintf() arguments.

A Usage tab shows exactly what an editor types into a post, in both the self-closing and enclosing forms, so you can hand it to a client without writing separate documentation. Free, no account, and every keystroke stays in the browser.

Reviewed Output tested on WordPress 6.8 · PHP 8.3

Why the shortcode generator beats writing add_shortcode() by hand

A shortcode is user input arriving inside post content. The two mistakes that cost the most time are echoing instead of returning — which teleports your markup to the top of the page — and interpolating an attribute straight into HTML without escaping it. This generator writes the return, picks the escaping function from the attribute type, and audits the markup against the tokens you actually declared.

A sanitiser chosen per attribute type

Text uses sanitize_text_field() then esc_html(), numbers and post IDs use absint(), URLs esc_url(), colours sanitize_hex_color(), booleans filter_var() with FILTER_VALIDATE_BOOLEAN, and a choice list becomes an in_array() whitelist that falls back to the first option.

Uppercase attributes caught early

WordPress lowercases attribute keys while parsing the shortcode, so a declared Columns can never match what the editor typed. That is raised as an error with a Lowercase attributes fix, alongside checks for duplicate names and choice lists with no choices.

Placeholder auditing in both directions

Markup that references {caption} when no such attribute exists is flagged, because it renders as literal text. Attributes declared but never placed in the markup are listed too, so you do not ship dead parameters.

Enclosing mode wired up properly

Turn on enclosing content and the signature becomes ( $atts = array(), $content = '' ), the body runs wp_kses_post( do_shortcode( $content ) ) so nested shortcodes still work, and the generator warns if you never place {content} in the markup.

Core tag collisions refused

gallery, caption, embed, audio, video, playlist and the rest of core cannot be registered without overriding WordPress itself. That is an error with a Prefix the tag fix; unprefixed tags get a gentler prefix recommendation.

The two filters people forget

Shortcodes do not run inside classic text widgets or excerpts unless you say so. Two toggles append add_filter( 'widget_text', 'do_shortcode' ) and add_filter( 'the_excerpt', 'do_shortcode' ) — only when you ask for them.

How does the shortcode generator work?

Name the tag, declare what it accepts, write what it returns, then export.

  1. 01

    Name the tag

    Pick the tag an editor will type between square brackets, plus a function prefix and text domain. Lowercase with underscores is the convention the generator nudges you toward.

  2. 02

    Declare the attributes

    Add each attribute with a name, a type — text, number, true/false, url, hex colour, choice list or post ID — a default value and a one-line description that lands in the docblock.

  3. 03

    Write the output markup

    Paste the HTML the shortcode should return and drop {attribute} tokens where values belong. Every token is replaced with a %s and its escaped expression in the generated sprintf().

  4. 04

    Set behaviour, then export

    Choose whether the shortcode encloses content and whether it should run in widgets and excerpts, clear the Checks tab, then copy the snippet or download the file.

Worked example — an enclosing [acme_notice] shortcode

One choice-list attribute with two options, enclosing content, and a wrapper div. This is the Snippet output exactly as it copies.

/**
 * [acme_notice] shortcode.
 *
 * @param array $atts {
 *     Shortcode attributes.
 *
 *     @type string $type Colour of the notice. Default 'info'.
 * }
 * @param string $content Enclosed content.
 * @return string Rendered HTML.
 */
function acme_acme_notice_shortcode( $atts = array(), $content = '' ) {
	$atts = shortcode_atts(
		array(
			'type' => 'info',
		),
		$atts,
		'acme_notice'
	);

	$type = in_array( $atts['type'], array( 'info', 'warning' ), true ) ? $atts['type'] : 'info';

	$inner = wp_kses_post( do_shortcode( $content ) );

	return sprintf(
		'<div class="acme-notice acme-notice--%s">%s</div>',
		esc_attr( $type ),
		$inner
	);
}
add_shortcode( 'acme_notice', 'acme_acme_notice_shortcode' );

Passing the tag as the third argument to shortcode_atts() is what makes the shortcode_atts_acme_notice filter available, so other plugins can adjust your defaults. An editor writes [acme_notice type="warning"]Text here[/acme_notice] — the Usage tab spells that out for you.

Shortcodes — frequently asked questions

The problems that send people looking for a shortcode generator in the first place.

Why does my shortcode output appear at the top of the page?

Because the callback echoes instead of returning. do_shortcode() replaces the tag with whatever the callback returns; anything echoed is printed immediately, before the content is assembled, so it lands at the top of the page. Buffer with ob_start() if you must print, but returning a string is the correct pattern and the only one this generator writes.

Why is my shortcode attribute always empty?

Two common causes. WordPress lowercases attribute keys when it parses the tag, so a key declared with capitals never matches — the generator raises this as an error. The other is smart quotes: the visual editor can turn straight quotes into curly ones, and [tag title=“x”] does not parse. Retype the attribute in the code view.

How do I make a shortcode that wraps content?

Accept a second parameter. An enclosing shortcode callback is function my_shortcode( $atts = array(), $content = '' ), and $content holds whatever sits between the opening and closing tags. Run it through do_shortcode() so nested shortcodes still expand, and through wp_kses_post() before output. Turn on enclosing mode and the generator writes all of that.

Why do shortcodes not work in my widget or excerpt?

WordPress does not run do_shortcode() on those contexts by default. Add add_filter( 'widget_text', 'do_shortcode' ) for classic text widgets and add_filter( 'the_excerpt', 'do_shortcode' ) for excerpts. Both are one-toggle options in this generator. Block-based widgets run shortcodes through the Shortcode block instead.

Can I use a dash in a shortcode tag?

It works, but underscores are the WordPress convention and avoid confusion with HTML attribute syntax. What you cannot use are spaces, square brackets, angle brackets, ampersands and slashes — those break the parser. The generator flags dashes as a warning and the illegal characters as an error.

Should shortcodes go in the theme or a plugin?

A plugin, if the content should survive a redesign. Shortcodes live inside post content, so removing the theme that registered one leaves the raw [tag] text visible on the published page. Use the Plugin file output for anything a client will type into posts.

Where do I paste the code from the Shortcode generator?

You have three good options and one bad one. Best is a small site-specific plugin — the generator can output one for you, and it keeps working when you change theme. A code-snippets plugin is fine too. A child theme's functions.php works but ties the code to that theme. Never edit the parent theme: the next update overwrites it and your code is gone.

Can I use the generated code in client work or a commercial plugin?

Yes. The output is ordinary WordPress API calls that you configured — there is no licence attached to it and no attribution required. Use it in client sites, commercial plugins and themes, or products you sell. The generated file carries a short credit comment you are free to delete.

The other Content generators in the library, plus the WordPress tools most often used alongside this one.