Trusted WordPress tutorials, when you need them most.
Beginner’s Guide to WordPress
25 Million+
Websites using our plugins
Years of WordPress experience
WordPress tutorials
by experts

How to Create a WordPress TinyMCE Plugin

Editorial Note: We earn a commission from partner links on WPBeginner. Commissions do not affect our editors' opinions or evaluations. Learn more about Editorial Process.

If you are WordPress developer, then at some point you may come across customizing or extending the WordPress Visual Editor. For example, you may want to add a button to the Visual Editor’s toolbar to allow your client to easily insert a text box or a call to action button without writing any HTML code. In this article, we will show you how to create a TinyMCE plugin in WordPress.

Tiny MCE toolbar in WordPress Visual Editor


This tutorial is intended for advanced users. If you are a beginner level user who just wants to extend visual editor, then please check out TinyMCE Advanced plugin or take a look at these tips on using WordPress visual editor.

For this tutorial, you will need basic coding skills, access to a WordPress install where you can test it out.

It is a bad practice to develop plugins on a live website. A minor mistake in the code can make your site inaccessible. But if you must do it on a live site, then at least backup WordPress first.

Creating Your First TinyMCE Plugin

We will begin by creating a WordPress plugin to register our custom TinyMCE toolbar button. When clicked, this button will allow user to add a link with a custom CSS class.

The source code will be provided in full at the end of this article, but until then, let’s create the plugin step-by-step.

First, you need to create a directory in wp-content/plugins folder of your WordPress install. Name this folder tinymce-custom-link-class.

From here, we’ll begin adding our plugin code.

The Plugin Header

Create a new file in the plugin directory we just created and name this file tinymce-custom-link-class.php. Add this code to the file and save it.

 * Plugin Name: TinyMCE Custom Link Class
 * Plugin URI:
 * Version: 1.0
 * Author: WPBeginner
 * Author URI:
 * Description: A simple TinyMCE Plugin to add a custom link class in the Visual Editor
 * License: GPL2

This is just a PHP comment, which tells WordPress the name of the plugin, as well as the author and a description.

In the WordPress admin area, activate your new plugin by going to Plugins > Installed Plugins, and then clicking Activate beside the TinyMCE Custom Link Class plugin:

Installed plugin

Setting Up Our Plugin Class

If two WordPress plugins have functions with the same name, then this would cause an error. We will avoid this problem by having our functions wrapped in a class.

class TinyMCE_Custom_Link_Class {
	* Constructor. Called when the plugin is initialised.
	function __construct() {


$tinymce_custom_link_class = new TinyMCE_Custom_Link_Class;

This creates our PHP class, along with a construct, which is called when we reach the line $tinymce_custom_link_class = new TinyMCE_Custom_Link_Class;.

Any functions we add inside this class shouldn’t conflict with other WordPress plugins.

Start Setting Up Our TinyMCE Plugin

Next, we need to tell TinyMCE that we might want to add our custom button to the Visual Editor‘s toolbar. To do this, we can use WordPress’ actions – specifically, the init action.

Add the following code inside your plugin’s __construct() function:

if ( is_admin() ) {
	add_action( 'init', array(  $this, 'setup_tinymce_plugin' ) );

This checks if we are in the WordPress Administration interface. If we are, then it asks WordPress to run the setup_tinymce_plugin function inside our class when WordPress has finished its initial loading routine.

Next, add the setup_tinymce_plugin function:

* Check if the current user can edit Posts or Pages, and is using the Visual Editor
* If so, add some filters so we can register our plugin
function setup_tinymce_plugin() {

// Check if the logged in WordPress User can edit Posts or Pages
// If not, don't register our TinyMCE plugin
if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {

// Check if the logged in WordPress User has the Visual Editor enabled
// If not, don't register our TinyMCE plugin
if ( get_user_option( 'rich_editing' ) !== 'true' ) {

// Setup some filters
add_filter( 'mce_external_plugins', array( &$this, 'add_tinymce_plugin' ) );
add_filter( 'mce_buttons', array( &$this, 'add_tinymce_toolbar_button' ) );

This checks if the current logged in WordPress user can edit Posts or Pages. If they can’t, there’s no point in registering our TinyMCE Plugin for that User, as they’ll never see the Visual Editor.

We then check if the user is using the Visual Editor, as some WordPress users turn this off via Users > Your Profile. Again, if the user is not using the Visual Editor, we return (exit) the function, as we don’t need to do anything else.

Finally, we add two WordPress Filters – mce_external_plugins and mce_buttons, to call our functions which will load the required Javascript file for TinyMCE, and add a button to the TinyMCE toolbar.

Registering the Javascript File and Button to the Visual Editor

Let’s go ahead and add the add_tinymce_plugin function:

* Adds a TinyMCE plugin compatible JS file to the TinyMCE / Visual Editor instance
* @param array $plugin_array Array of registered TinyMCE Plugins
* @return array Modified array of registered TinyMCE Plugins
function add_tinymce_plugin( $plugin_array ) {

$plugin_array['custom_link_class'] = plugin_dir_url( __FILE__ ) . 'tinymce-custom-link-class.js';
return $plugin_array;


This function tells TinyMCE that it needs to load the Javascript files stored in the $plugin_array array. These Javascript files will tell TinyMCE what to do.

We also need to add some code to the add_tinymce_toolbar_button function, to tell TinyMCE about the button we’d like to add to the toolbar:

* Adds a button to the TinyMCE / Visual Editor which the user can click
* to insert a link with a custom CSS class.
* @param array $buttons Array of registered TinyMCE Buttons
* @return array Modified array of registered TinyMCE Buttons
function add_tinymce_toolbar_button( $buttons ) {

array_push( $buttons, '|', 'custom_link_class' );
return $buttons;

This pushes two items onto the array of TinyMCE buttons: a separator (|), and our button’s programmatic name (custom_link_class).

Save your plugin, and then edit a Page or Post to view the Visual Editor. Chances are, the toolbar isn’t displaying right now:


Don’t worry – if we use our web browser’s inspector console, we’ll see that a 404 error and notice have been generated by TinyMCE, telling us that it can’t find our Javascript file.


That’s good – it means we’ve successfully registered our TinyMCE custom plugin, and now need to create the Javascript file to tell TinyMCE what to do.

Creating the Javascript Plugin

Create a new file in your wp-content/plugins/tinymce-custom-link-class folder, and name it tinymce-custom-link-class.js. Add this code in your js file:

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

This calls the TinyMCE Plugin Manager class, which we can use to perform a number of TinyMCE plugin related actions. Specifically, we’re adding our plugin to TinyMCE using the add function.

This accepts two items; the name of the plugin (custom_link_class) and an anonymous function.

If you’re familiar with the concept of functions in coding, an anonymous function is simply a function with no name. For example, function foobar() { ... } is a function that we could call somewhere else in our code by using foobar().

With an anonymous function, we can’t call that function somewhere else in our code – it’s only being called at the point the add() function is invoked.

Save your Javascript file, and then edit a Page or Post to view the Visual Editor. If everything worked, you’ll see the toolbar:


Right now, our button hasn’t been added to that toolbar. That’s because we’ve only told TinyMCE that we are a custom plugin. We now need to tell TinyMCE what to do – that is, add a button to the toolbar.

Update your Javascript file, replacing your existing code with the following:

(function() {
	tinymce.PluginManager.add( 'custom_link_class', function( editor, url ) {
		// Add Button to Visual Editor Toolbar
		editor.addButton('custom_link_class', {
			title: 'Insert Button Link',
			cmd: 'custom_link_class',

Notice our anonymous function has two arguments. The first is the editor instance – this is the TinyMCE Visual Editor. In the same way we can call various functions on the PluginManager, we can also call various functions on the editor. In this case, we’re calling the addButton function, to add a button to the toolbar.

Save your Javascript file, and go back to your Visual Editor. At a first look, nothing seems to have changed. However, if you hover your mouse cursor over to the right of the top row’s rightmost icon, you should see a tooltip appear:


We’ve successfully added a button to the toolbar, but it needs an image. Add the following parameter to the addButton function, below the title: line:

image: url + '/icon.png',

url is the URL to our plugin. This is handy if we want to reference an image file within our plugin folder, as we can append the image file name to the URL. In this case, we’ll need an image called icon.png in our plugin’s folder. Use the below icon:

Reload our Visual Editor, and you’ll now see your button with the icon:

Defining a Command to Run

Right now, if you click the button, nothing will happen. Let’s add a command to TinyMCE telling it what to do when our button is clicked.

In our Javascript file, add the following code below the end of the editor.addButton section:

// Add Command when Button Clicked
editor.addCommand('custom_link_class', function() {
	alert('Button clicked!');

Reload our Visual Editor, click the button and an alert will appear confirming we just clicked the button:


Let’s replace the alert with a prompt, asking the user for the link they want to wrap around the selected text in the Visual Editor:

// Add Command when Button Clicked
editor.addCommand('custom_link_class', function() {
	// Check we have selected some text that we want to link
	var text = editor.selection.getContent({
		'format': 'html'
	if ( text.length === 0 ) {
		alert( 'Please select some text to link.' );

	// Ask the user to enter a URL
	var result = prompt('Enter the link');
	if ( !result ) {
		// User cancelled - exit
	if (result.length === 0) {
		// User didn't enter a URL - exit

	// Insert selected text back into editor, wrapping it in an anchor tag
	editor.execCommand('mceReplaceContent', false, '<a class="button" href="' + result + '">' + text + '</a>');

This block of code performs a few actions.

First, we check if the user selected some text to be linked in the Visual Editor. If not, they’ll see an alert telling them to select some text to link.


Next, we ask them to enter a link, again checking if they did. If they cancelled, or didn’t enter anything, we don’t do anything else.


Finally, we run the execCommand function on the TinyMCE editor, specifically running the mceReplaceContent action. This replaces the selected text with our HTML code, which comprises of an anchor link with class=”button”, using the text the user selected.

If everything worked, you’ll see your selected text is now linked in the Visual Editor and Text views, with the class set to button:




We’ve successfully created a WordPress plugin which adds a button to the TinyMCE visual editor in WordPress. This tutorial has also covered some of the basics of the TinyMCE API and WordPress filters available for TinyMCE integrations.

We added code so that when a user clicks our custom button, they’re prompted to select some text in the Visual Editor, which they can then link to a URL of their choice. Finally, our plugin then replaces the selected text with a linked version that contains a custom CSS class called button.

We hope this tutorial helped you learn how to create a WordPress TinyMCE plugin. You may also want to check out our guide on how to create a site-specific WordPress plugin.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

Disclosure: Our content is reader-supported. This means if you click on some of our links, then we may earn a commission. See how WPBeginner is funded, why it matters, and how you can support us. Here's our editorial process.

Editorial Staff

Editorial Staff at WPBeginner is a team of WordPress experts led by Syed Balkhi with over 16 years of experience in WordPress, Web Hosting, eCommerce, SEO, and Marketing. Started in 2009, WPBeginner is now the largest free WordPress resource site in the industry and is often referred to as the Wikipedia for WordPress.

The Ultimate WordPress Toolkit

Get FREE access to our toolkit - a collection of WordPress related products and resources that every professional should have!

Reader Interactions

7 CommentsLeave a Reply

  1. Syed Balkhi says

    Hey WPBeginner readers,
    Did you know you can win exciting prizes by commenting on WPBeginner?
    Every month, our top blog commenters will win HUGE rewards, including premium WordPress plugin licenses and cash prizes.
    You can get more details about the contest from here.
    Start sharing your thoughts below to stand a chance to win!

  2. Joel says

    Brilliant article – I had to search forever to find something this simple and easy to understand. For someone completely new to this, it was very annoying how every single tutorial would conveniently leave out the directory to create this plugin in. Thanks so much!

  3. Friso says

    Good article, I used it in my own plugin. Quick tip tough, you don’t have to use an object by refence anymore in PHP, so instead of &$this, you can do just $this. Since objects are passed by reference in default

  4. Michael says

    Sorry, but i get always a error message

    Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in C:\xampp\htdocs\wordpress\wp-includes\class-wp-hook.php on line 298

    Can you tell me, whats wrong?

Leave A Reply

Thanks for choosing to leave a comment. Please keep in mind that all comments are moderated according to our comment policy, and your email address will NOT be published. Please Do NOT use keywords in the name field. Let's have a personal and meaningful conversation.