In one of the WordPress plugins I developed recently I had to add a list a buttons (which is a custom post type) in the TinyMCE pop up. It was basically a select field where I needed to populate button ID and title as option fields.

Since I see a lot of people asking how to add dynamic content inside TinyMCE pop up so thought of sharing how I dealt with it.

Dynamic Content in TinyMCE

In this tutorial I will show you how to dynamically add post data as options inside TinyMCE pop up select field. So without any ado let’s jump right into it.

Step 1. Create TinyMCE Button

First of all create a TinyMCE button. Add the below code to your plugin file.

// Hooks your functions into the correct filters
function twd_mce_button() {
	// 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', 'twd_add_mce_plugin' );
		add_filter( 'mce_buttons', 'twd_register_mce_button' );
add_action( 'admin_head', 'twd_mce_button' );

// Script for our mce button
function twd_add_mce_plugin( $plugin_array ) {
	$plugin_array['twd_mce_button'] = plugin_dir_url( __FILE__ ) . 'mce.js';
	return $plugin_array;

// Register our button in the editor
function twd_register_mce_button( $buttons ) {
	array_push( $buttons, 'twd_mce_button' );
	return $buttons;

Here we are using basic WordPress TinyMCE filters to hook our MCE plugin into TinyMCE. You can read more about it on TinyMCE Custom Buttons page on

Step 2. Fetch Post Titles

Now I will make use of wpdb class to fetch the post titles and then return the data that I require (post id and title) as a JSON string in the format that TinyMCE select field expects.

 * Function to fetch cpt posts list
 * @return json
public function twd_posts( $post_type ) {

	global $wpdb;
   	$cpt_type = $post_type;
	$cpt_post_status = 'publish';
        $cpt = $wpdb->get_results( $wpdb->prepare(
        "SELECT ID, post_title
            FROM $wpdb->posts 
            WHERE $wpdb->posts.post_type = %s
            AND $wpdb->posts.post_status = %s
            ORDER BY ID DESC",
    ) );

    $list = array();

    foreach ( $cpt as $post ) {
		$selected = '';
		$post_id = $post->ID;
		$post_name = $post->post_title;
		$list[] = array(
			'text' =>	$post_name,
			'value'	=>	$post_id

	wp_send_json( $list );


Step 3. Store JSON Data with TinyMCE Editor Instance

You might ask why set data inside TinyMCE editor instance? This is because this way we will be able to easily access our data inside the TinyMCE pop up. Here we just need to create a new property under TinyMCE Editor instance to store our data. I will use AJAX here to store the data from previous step.

 * Function to fetch buttons
 * @since  1.6
 * @return string
public function twd_list_ajax() {
	// check for nonce
	check_ajax_referer( 'twd-nonce', 'security' );
	$posts = twd_posts( 'post' );
	return $posts;
add_action( 'wp_ajax_twd_cpt_list', 'twd_list_ajax' );

 * Function to output button list ajax script
 * @since  1.6
 * @return string
public function twd_cpt_list() {
	// create nonce
	global $pagenow;
	if( $pagenow != 'admin.php' ){
		$nonce = wp_create_nonce( 'twd-nonce' );
		?><script type="text/javascript">
			jQuery( document ).ready( function( $ ) {
				var data = {
					'action'	: 'twd_cpt_list', // wp ajax action
					'security'	: '<?php echo $nonce; ?>' // nonce value created earlier
				// fire ajax ajaxurl, data, function( response ) {
			  		// if nonce fails then not authorized else settings saved
			  		if( response === '-1' ){
				  		// do nothing
			  		} else {
			  			if (typeof(tinyMCE) != 'undefined') {
			  				if (tinyMCE.activeEditor != null) {
								tinyMCE.activeEditor.settings.cptPostsList = response;
add_action( 'admin_footer', 'twd_cpt_list' );


Step 4. Create TinyMCE Plugin

This is the last step where we need to create a TinyMCE plugin. The code below is basic JavaScript code to create a plugin. The only change here is that we are using TinyMCE editor instance property that we created earlier to add values to our select field. Submitting the form prints out a short code with id parameter containing the dynamic content.

(function() {
	tinymce.PluginManager.add('twd_mce_button', function( editor, url ) {
		editor.addButton('twd_mce_button', {
			text: '{ TWD CPT Posts }',
			icon: false,
			tooltip: 'CPT List',
			onclick: function() { {
					title: 'Insert List',
					width: 400,
					height: 100,
					body: [
							type: 'listbox',
							name: 'listboxName',
							label: 'TWD CPT Posts',
							'values': editor.settings.cptPostsList
					onsubmit: function( e ) {
						editor.insertContent( '[twd_post_title id="' + + '"]');

I hope through this tutorial you will be able to add dynamic content inside TinyMCE pop up in WordPress. If something is unclear or if you have any suggestion to improve this code then please use the comment form below.

About the author

11 Responses
  1. Will Hershfeld

    Hi Gautam – This tutorial is exactly what I’m looking for – I’ve just got to access a different post type.

    Could you elaborate a little on the where each of these code segments should be placed?

      1. Kassandra

        Hi Guatam. This is great! Thank you. However, I was wondering, how can I get this functionality to work in the TinyMCE for regular posts and not just books.

  2. Paul

    Thank you very much for posting this. It’s very helpful and I’ll be utilising something like this in a personal project I’m in the middle of.

  3. Thanks for the work, i would be very interested in learning doing this, but unfortunately, i’ve just installed your plugin, make the change for fetching posts, and it does not work… Can you please help ?

    1. Gautam Thapar

      Hi Max,

      May I know what changes you made? You just need to change “book” to “post” on line 136 in twd-mce-button.php to get list of posts.

Leave a Reply

May be Subscribe?