Adding a custom form-tag

This is the first entry in a series of articles to help developers customize Contact Form 7.

The first topic is expanding Contact Form 7’s form-tags. As you probably know, form-tags are code in a specific format within square brackets, usually representing form controls like text input fields and submit buttons. Currently, Contact Form 7 supports 30 different types of form-tags by default.

These are examples of typical form-tags:

[text* your-name]
[textarea your-message]
[submit "Send"]

They look like WordPress shortcodes, but unlike shortcodes, form-tags only work within a Contact Form 7 form area.

You can add your own custom form-tags as well. There are two steps to add custom form-tags: (1) register form-tag types and a corresponding callback function, and (2) define the callback function. Let’s look at each step.


To register form-tag types, call wpcf7_add_form_tag() function. wpcf7_add_form_tag() accepts three parameters (two required and one optional).

The first parameter is a string value containing the type of the tag. The first word in a form-tag is its type. In the examples presented above, “text*”, “textarea”, and “submit” are types. You can use lower-case letters ([a-z]), digits ([0-9]), underscores (“_“), and asterisks (“*“) in a form-tag type. Tag types with a trailing asterisk (e.g., “text*”, “email*”) are used for required input fields.

If you have two or more form-tag types sharing the same callback function, you may want to register them together. In such cases, specify an array of strings as the first parameter.

The second parameter is a callback function called when Contact Form 7 parses the form-tag. More on callback functions later.

The optional third parameter is an array of features that the form-tag type supports. For example, a form-tag type whose instances have a name part supports name-attr feature.

The name of a form-tag is the second word in the form-tag. In the examples above, “your-name” and “your-message” are names. Some form-tags don’t have names, like [submit "Send"].

For form-tag types supporting name-attr feature, pass array( 'name-attr' => true ) as the third parameter of wpcf7_add_form_tag().

Note that you have to use wpcf7_init action hook when you call wpcf7_add_form_tag(). For reference, see how Contact Form 7 registers default form-tags.

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_text' );

function wpcf7_add_form_tag_text() {
    array( 'text', 'text*', 'email', 'email*', 'url', 'url*', 'tel', 'tel*' ),
    array( 'name-attr' => true )

Callback function

The next step is defining the callback function. This function takes a WPCF7_FormTag object as its only argument, which represents information from an actual form-tag, including its type, name, options, values, etc.

The callback function must return a text value. Usually they return HTML snippets that represent a form control. The returned text replaces the form-tag when Contact Form 7 generates a form from a form template containing form-tags.

As a demonstration, let’s create a simple form-tag that displays the current time (let’s call it “[clock]”).

Add the following code at an appropriate place. Many developers prefer to use theme’s functions.php file for small custom coding. Don’t directly edit files in the plugin (contact-form-7) folder because you risk breaking the plugin code, and you’ll lose your customization when the plugin is updated.

add_action( 'wpcf7_init', 'custom_add_form_tag_clock' );

function custom_add_form_tag_clock() {
  wpcf7_add_form_tag( 'clock', 'custom_clock_form_tag_handler' ); // "clock" is the type of the form-tag

function custom_clock_form_tag_handler( $tag ) {
  return date_i18n( get_option( 'time_format' ) );

Then, add this line to your form area:

Current Time: [clock]

If it works correctly, you should see a line like this in the form:

Current Time: 12:16 pm

That’s it. Obviously this “[clock]” demo is too simple for practical use, but it’s enough to show the concept of the Contact Form 7 form-tags. To improve and make it suitable for practical use, you’ll need to learn:

  • How to retrieve information from form-tag components and construct more complex form controls using this information.
  • How to validate user input, and if it’s invalid, how to show a validation error.

Upcoming recipes will cover these areas.