Creating Custom Tokens in Drupal 9

What are Tokens?

A token is basically just a placeholder for an actual value. You might have gone through an arcade station where you can purchase tokens to use in slot machines for example. Instead of configuring the machines to accept multiple denominations of money, we can just configure it to accept tokens in exchange for actual money.

It’s not much different in Drupal programming, a token is also a placeholder of a dynamically generated string. For example you create a feature where you want to display a popup message when a user is successfully authenticated -- say “Good morning, John!”. If you only have five users, it might be faster just to create a custom string for each but good morning is just one of the variations. How about “good afternoon” or “good evening”?

For this requirement you can format your token such as [greeting], [name]

When do you use a token?

The common use for a token in Drupal is integration with other modules. Because modules are contributed, they are not likely to have the calculations of dynamic values you need. So you have to use a token in order to supply the values you want to these contributed modules.

One commonly used contributed module is the workbench moderation email. This module accepts tokens for sending customized emails to different roles and users within and outside your site. Let’s say you want to include the author name in the subject or body field of the notification email, you can do so by using the available tokens provided in Drupal.

Another commonly used module is the meta tag module, this allows you to add dynamic meta tag contents such as page title, url, image or description.

How to create your own token?

In one of our projects, we were limited in the meta tag translation because the default tokens available in Drupal are too long and the meta tag translation title field for some reason only accepts 128 characters. We have to find a way to include dynamic strings from our project to be included in the meta tag.

Below is an example of how we created the custom tokens :

  • Create a custom module directory inside modules/custom/yourmodule. In our case, we called it metatag_tokens because we always use a definitive module name so it will be easier to identify in the future. Just by reading the module name, we can already see that it is for metatag and tokens.
  • Add a file in the newly created directory and place all the necessary items here. Make sure to describe what this custom module is used for.

name: Metatag Tokens
type: module
description: "This module is used for adding custom tokens specifically for Metatag"
package: Custom
core_version_requirement: ^8 || ^9

  • Add the yourmodule.module file and make sure to include the hook token info and hooks token. These are the basic requirements to successfully create a custom token.
    • The token info hook is where you define the token information and how it will appear in the tokens list.
    • The hooks token is where you place all the calculation codes to create a dynamic string.


* Implements hook_token_info().
function metatag_tokens_token_info() {
   $type = [
       'name' => t('Metatag Custom Tokens'),
       'description' => t('Tokens for custom things.'),
   $node['title'] = [
       'name' => t("Open Graph Title"),
       'description' => t('Adds dynamic title to the open graph metatag.'),
   $node['description'] = [
       'name' => t("Open Graph Description"),
       'description' => t('Adds dynamic description to the open graph metatag.'),
   return [
       'types' => ['custom' => $type],
       'tokens' => ['custom' => $node],
* Implements hook_tokens().
function metatag_tokens_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) {
   $replacements = [];
   $language = \Drupal::languageManager()->getCurrentLanguage()->getId();

   if ($type == 'custom') {
       foreach ($tokens as $name => $original) {
           switch ($name) {
               case 'title':
                if ($language == 'en') {
                  $replacements[$original] = ' This is the English title';
                } elseif ($language == 'ko') {
                  $replacements[$original] = ' This is the Korean title';
                } elseif ($language == 'de') {
                  $replacements[$original] = ' This is the German title';
                } elseif ($language == 'zh-hans') {
                  $replacements[$original] = ' This is the Chinese title';
                } else {
                  $replacements[$original] = ' This is the default title';
              case 'description':
                if ($language == 'en') {
                  $replacements[$original] = ' This is the English description';
                } elseif ($language == 'ko') {
                  $replacements[$original] = ' This is the Korean description';
                } elseif ($language == 'de') {
                  $replacements[$original] = ' This is the German description';
                } elseif ($language == 'zh-hans') {
                  $replacements[$original] = ' This is the Chinese description';
                } else {
                  $replacements[$original] = ' This is the default description';
   return $replacements;

  • Install the module like any other modules
  • Always clear the cache using Drush cr or if you have admin toolbar installed, you can flush cache.
  • Browse the tokens to verify that your custom tokens are shown

Profile picture for user Jeffy Lepatan
Jeffy Lepatan Manager [ Acret PH ]

I grew up in a slum in Cebu and at a young age I already learned that having a comfortable life is not something you get for free, you have to work hard to achieve it. Being the eldest out of seven siblings, I make sure that I share whatever I achieve with my younger brothers and sisters. I think that is the most important trait that I could share with my team, so that nobody gets left behind. I am truly grateful to our CEO for giving me a chance to be part of something big, that is why as a developer, I make my contributions by challenging myself everyday in order to make software solutions that would help&nbsp;the internet space easier to navigate. And as a manager, I encourage my team to always be grateful for an opportunity to create something useful for others while having fun doing it and to help build each other up within the team. I've never been anywhere outside the country and I dream of the day when I can visit other countries just by putting on a VR headgear then seconds later it will feel like you're there. I believe advancements in development technologies can make that possible. Going anywhere in the world within minutes - why not?