I'm familiar with creating self-closing shortcodes like:

// shortcode
function wpse_shortcode_example( $wpse_atts ) {

    // Attributes
    $wpse_atts = shortcode_atts(
            'foo' => 'bar',
            'width' => '100%',
            'height' => 'auto',

    // Return
    return '<embed 
             src="' . $wpse_atts['src'] . '"
             width="' . $wpse_atts['width'] . '"
             height="' . $wpse_atts['height'] . '";

add_shortcode( 'wpse', 'wpse_shortcode_example' );

but I would like to start adding these to the TinyMCE. I've done several searches but all of the search results are either dated or use an approach that is no longer recommended:

I know Developer is still in it's early stages but the Plugin Handbook only briefly talks about TinyMCE Enhanced Shortcodes and Shortcode API and add_shortcode() don't mention TinyMCE.

So this leads me to my question. What is the basic procedure for turning a self-closing shortcode into a clickable button in the TinyMCE editor?

  • So you mean how to create a button in the TinyMCE editor that injects a self-closing shortcode into the content?
    – birgire
    Jul 22, 2016 at 18:41
  • 1
    @birgire Yes I would like to know the foundation for integrating a custom button into TinyMCE that will add the shortcode to the post visual.
    – user9447
    Jul 22, 2016 at 18:43
  • 1
    Did you check out the great answer here by @bueltge ?
    – birgire
    Jul 22, 2016 at 18:58
  • @birgire no it didn't return from my searching but it's a good Q&A
    – user9447
    Jul 22, 2016 at 19:07

1 Answer 1


We start by adding the custom TinyMCE Button:

function add_mce_button_custom_em() {
    // check user permissions
    if ( !current_user_can( 'edit_posts' ) && !current_user_can( 'edit_pages' ) ) {
    // check if WYSIWYG is enabled
    if ( 'true' == get_user_option( 'rich_editing' ) ) {
        add_filter( 'mce_external_plugins', 'add_tinymce_plugin_custom_em' );
        add_filter( 'mce_buttons', 'register_mce_button_custom_em' );
add_action('admin_head', 'add_mce_button_custom_em');

Then we declare and register the new button:

// Declare script for new button
function add_tinymce_plugin_custom_em( $plugin_array ) {
    $plugin_array['custom_em'] = get_template_directory_uri() .'/plug/custom-em/custom-em.js';
    return $plugin_array;

// Register new button in the editor
function register_mce_button_custom_em( $buttons ) {
    array_push( $buttons, 'custom_em' );
    return $buttons;

Finally, we decide which buttons (more on buttons can be found at Content Formatting) we want to display. Obviously, if you have UX in mind, you would only display a few of them, example:

// TinyMCE: TinyMCE choose which buttons you want to display
function myformatTinyMCE( $in ) {
    $in['toolbar1'] = 'styleselect,bold,custom_em,blockquote,hr,aligncenter,link,unlink,spellchecker,undo,removeformat';
    return $in;
add_filter( 'tiny_mce_before_init', 'myformatTinyMCE' );

As you can see in the add_tinymce_plugin_custom_em function, we are declaring a javascript file inside get_template_directory_uri() .'/plug/custom-em/custom-em.js'

So create the custom-em.js file, and then you have two ways to go about this.

Either you can go with the following shortcode format [shortcode foo="" bar=""] or [shortcode][/shortcode].

Let's start with the [shortcode foo="" bar=""] format:

(function() {
    tinymce.create('tinymce.plugins.custom_em', {
        init : function(ed, url) {
            ed.addButton('custom_em', {
                title : 'Custom EM',
                image : url+'/images/btn_custom_em.png',
                onclick : function() {
                        "[shortcode foo=\"\" bar=\"\"]"
    tinymce.PluginManager.add('custom_em', tinymce.plugins.custom_em);

As you can see, we use an image as the button icon. You can change that into text as outlined in the example below.

The following is what we use on our own platform, it wraps the selection into: <em class="whatever">hello world</em>:

(function() {
    tinymce.PluginManager.add('custom_em', function( editor, url ) {

        editor.on('init', function(e) {
            this.formatter.register('thetarget', {
                inline : 'em',
                classes : 'whatever'

        editor.addButton('custom_em', {
            text: 'Custom EM',
            icon: false,
            onclick : function() {
                var contents = editor.selection.getContent(),
                tags = jQuery(jQuery.parseHTML(contents)).find('em.whatever').andSelf();

Please post results and perform edits. TinyMCE is a plague and requires headache but can be solves in a collaborative manner.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.