---
title: "Mentions plugin"
description: "Enables @mention functionality."
canonical_url: "https://www.tiny.cloud/docs/tinymce/latest/mentions/"
md_url: "https://www.tiny.cloud/docs/tinymce/latest/mentions/index.md"
version: "latest"
last_updated: "2026-06-15T05:48:02Z"
tokens: 3032
---
# Mentions plugin

> **Note:** This plugin is only available for [paid TinyMCE subscriptions](/pricing/).
The mentions plugin will present a list of users when a user types the "@" symbol followed by the beginnings of a username after it. It will then query your server using the `mentions_fetch` callback.

## Interactive example

**Example**

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const mentions_fetch = async (query, success) => {
  const searchPhrase = query.term.toLowerCase();
  await fetch(`${API_URL}?q=${encodeURIComponent(searchPhrase)}`)
    .then((response) => response.json())
    .then((users) => success(users.data.map((userInfo) => ({
      id: userInfo.id,
      name: userInfo.name,
      image: userInfo.avatar,
      description: userInfo.custom.role
    }))))
    .catch((error) => console.log(error));
};

const mentions_menu_complete = (editor, userInfo) => {
  const span = editor.getDoc().createElement('span');
  span.className = 'mymention';
  span.setAttribute('data-mention-id', userInfo.id);
  span.appendChild(editor.getDoc().createTextNode('@' + userInfo.name));
  return span;
};

const createCard = (userInfo) => {
  const div = document.createElement('div');
  div.innerHTML = (
    '<div class="card">' +
      '<img class="avatar" src="' + userInfo.image + '">' +
      '<h1>' + userInfo.name + '</h1>' +
      '<p>' + userInfo.description + '</p>' +
    '</div>'
  );
  return div;
};

const mentions_select = async (mention, success) => {
  const id = mention.getAttribute('data-mention-id');
  await fetch(`${API_URL}/${id}`)
    .then((response) => response.json())
    .then((userInfo) => {
      const card = createCard({
        id: userInfo.id,
        name: userInfo.name,
        image: userInfo.avatar,
        description: userInfo.custom.role
      });
      success(card);
    })
    .catch((error) => console.error(error));
};

const mentions_menu_hover = async (userInfo, success) => {
  const card = createCard(userInfo);
  success(card);
};

tinymce.init({
    selector: "textarea",
    plugins: [
      "advlist", "anchor", "autolink", "charmap", "code", "fullscreen",
      "help", "image", "insertdatetime", "link", "lists", "media",
      "preview", "searchreplace", "table", "visualblocks", "mentions"
    ],
    toolbar: "undo redo | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
    content_style: '.mymention{ color: gray; }',
    mentions_fetch,
    mentions_item_type: 'profile',
    mentions_menu_complete,
    mentions_selector: '.mymention',
    mentions_select,
    mentions_menu_hover,
    tinycomments_mode: 'embedded'
});
```

> **Note:** For information on bundling this plugin with module bundlers, see [Bundling TinyMCE - Overview](../bundling-guide/).

## Options

These configuration options affect the execution of the `mentions` plugin. The main option that needs to be implemented is the `mentions_fetch` callback.

### `mentions_fetch`

This option lets you request a list of users from your server that match a search query. The callback gets passed two parameters: one is the search query object, the other is the success callback to execute with the results. The query object has a term property that contains what the user has typed after the "@" sign.

The success call should contain an array of users.

> **Note:** Only the first ten (10) users listed in the array are displayed in the Mentions UI presented to end-users.
For information on the user properties to pass to the success callback for the available mentions item types (`mentions_item_type`), see: [User properties](#user-properties).

**Type:** `Function`

#### Example: using `mentions_fetch`

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const mentions_fetch = async (query, success) => {
  const searchPhrase = query.term.toLowerCase();
  await fetch(`${API_URL}?q=${encodeURIComponent(searchPhrase)}`)
    .then((response) => response.json())
    .then((users) => success(users.data.map((userInfo) => ({
      id: userInfo.id,
      name: userInfo.name,
      image: userInfo.avatar,
      description: userInfo.custom.role
    }))))
    .catch((error) => console.log(error));
};

tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_fetch
});
```
The `success` callback can be passed an optional array of extra items. When clicked, the menu reloads and passes additional query parameters to the fetch function. The extra items can be used to search with different queries or show additional results, such as a full text search (which is slower to fetch). Each extra item should contain:

- A "text" property for the content to be displayed in the menu.
- A "meta" property for that will be passed using the fetch query parameter.

#### Example with extras

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const mentions_fetch = async (query, success) => {
  const searchPhrase = query.term.toLowerCase();
  await fetch(`${API_URL}?q=${encodeURIComponent(searchPhrase)}`)
    .then((response) => response.json())
    .then((users) => {
      const mentions = users.data.map((userInfo) => ({
        id: userInfo.id,
        name: userInfo.name,
        image: userInfo.avatar,
        description: userInfo.custom.role
        ...(query.meta && query.meta.email)
          ? { email: userInfo.custom.email }
          : {}
      }));
      const extras = [{
        text: 'Include email...',
        meta: { email: true }
      }];
      success(mentions, extras);
    })
    .catch((error) => console.log(error));
};

tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_fetch
});
```

### `mentions_item_type`

This option sets which user interface item type to use when displaying the list of users.

- The `name` item will only display the user’s name.
- The `profile` item will display the user’s name and can display an optional image and description.

For information on the properties required for the user object provided to [`mentions_fetch`](#mentions_fetch), see: [User properties](#user-properties).

**Type:** `String`

**Default value:** `'name'`

**Possible values:** `'name'`, `'profile'`

#### Example: using `mentions_item_type`

```js
tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_item_type: 'name'
});
```

#### User properties

The following table describes the properties available for user objects provided to the [`mentions_fetch` callback](#mentions_fetch). Properties may be required, optional, or not available; depending on the [`mentions_item_type`](#mentions_item_type) and [`mentions_select`](#mentions_select) options.

| Name | Value | `name` | `profile` | Description |
| --- | --- | --- | --- | --- |
| id | string | required | required | Used to identify the user mention in different callbacks |
| name | string | required | required | Name to display and highlight matches |
| image | string | not available | optional | Image source for user avatar |
| description | string | not available | optional | Description to display |

### `mentions_min_chars`

This option specifies the number of characters a user needs to type after the "@" symbol before the list of users will be displayed.

**Type:** `Number`

**Default value:** `1`

#### Example: using `mentions_min_chars`

```js
tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_min_chars: 1
});
```

### `mentions_menu_complete`

This option overrides the default logic for inserting the mention into the editor. The callback should return an element created using the editor’s document.

**Type:** `Function`

#### Example: using `mentions_menu_complete`

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const mentions_menu_complete = (editor, userInfo) => {
  const span = editor.getDoc().createElement('span');
  span.className = 'mymention';
  span.setAttribute('data-mention-id', userInfo.id);
  span.appendChild(editor.getDoc().createTextNode('@' + userInfo.name));
  return span;
};

tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_selector: 'span.mymention',
  mentions_menu_complete
});
```

### `mentions_menu_hover`

This option enables you to provide an element to present next to the menu item being hovered. This lets you do custom UIs for presenting user information.

**Type:** `Function`

#### Example: using `mentions_menu_hover`

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const createCard = (userInfo) => {
  const div = document.createElement('div');
  div.innerHTML = (
    '<div class="card">' +
      '<img class="avatar" src="' + userInfo.image + '">' +
      '<h1>' + userInfo.name + '</h1>' +
      '<p>' + userInfo.description + '</p>' +
    '</div>'
  );
  return div;
};

const mentions_menu_hover = async (userInfo, success) => {
  const card = createCard(userInfo);
  success(card);
};

tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_selector: '.mymention',
  mentions_menu_hover
});
```

#### `mentions_menu_hover` with predefined templates

If `mentions_menu_hover` is resolved with an object specifying the type and user details, a predefined hover card template will be used. To use the predefined template, set `type` to `'profile'`. For details on the user properties required for the `profile` template, see: [User properties](#user-properties).

##### Example: using the `'profile'` template with `mentions_menu_hover`

```js
tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_selector: '.mymention',
  mentions_menu_hover: (userInfo, success) =>
    success({ type: 'profile', user: userInfo })
});
```

### `mentions_selector`

This option enables you to provide a custom CSS selector that should match the element created using `mentions_menu_complete`. This enables the plugin to find existing mentions. The callback takes two parameters: the editor instance and the userInfo object.

**Type:** `Function`

#### Example: using `mentions_selector`

```js
tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_selector: 'span.mymention',
  mentions_menu_complete: (editor, userInfo) => {
    const span = editor.getDoc().createElement('span');
    span.className = 'mymention';
    span.setAttribute('data-mention-id', userInfo.id);
    span.appendChild(editor.getDoc().createTextNode('@' + userInfo.name));
    return span;
  }
});
```

### `mentions_select`

This option enables a hover card to be presented when a user hovers over a mention in TinyMCE. This could include details about the user. A custom hover card HTML element can be provided or a predefined template can be specified.

**Type:** `Function`

#### Example: using `mentions_select`

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const createCard = (userInfo) => {
  const div = document.createElement('div');
  div.innerHTML = (
    '<div class="card">' +
      '<img class="avatar" src="' + userInfo.image + '">' +
      '<h1>' + userInfo.name + '</h1>' +
      '<p>' + userInfo.description + '</p>' +
    '</div>'
  );
  return div;
};

const mentions_select = async (mention, success) => {
  const id = mention.getAttribute('data-mention-id');
  await fetch(`${API_URL}/${id}`)
    .then((response) => response.json())
    .then((userInfo) => {
      const card = createCard({
        id: userInfo.id,
        name: userInfo.name,
        image: userInfo.avatar,
        description: userInfo.custom.role
      });
      success(card);
    })
    .catch((error) => console.error(error));
};

tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_selector: '.mymention',
  mentions_select
});
```

#### `mentions_select` with predefined templates

If `mentions_select` is resolved with an object specifying the type and user details, a predefined hover card template will be used. To use the predefined template, set `type` to `'profile'`. For details on the user properties required for the `profile` template, see: [User properties](#user-properties).

##### Example: using the `'profile'` template with `mentions_select`

```js
const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const mentions_select = async (mention, success) => {
  const id = mention.getAttribute('data-mention-id');
  await fetch(`${API_URL}/${id}`)
    .then((response) => response.json())
    .then((userInfo) => {
      const user = {
        id: userInfo.id,
        name: userInfo.name,
        image: userInfo.avatar,
        description: userInfo.custom.role
      };
      success({ type: 'profile', user });
    })
    .catch((error) => console.error(error));
};

tinymce.init({
  selector: 'textarea',
  plugins: 'mentions',
  mentions_selector: '.mymention',
  mentions_select
});
```
