Mention users
Tag users in chat messages with @ mentions. Type @ followed by at least three letters to see username suggestions.
Version 2
This document covers message draft version 2 unless otherwise noted.
tip
Channel references, user mentions, and links are MessageElement instances with different mentionType values.
Configuration options:
- User source: channel members or all app users
- Suggestions: up to 100 usernames (default: 10)
- Username length: up to 200 characters
- Mentions per message: up to 100 (default: 10)
Implementation follows similar patterns to channel referencing and links.
Version 1
In version 1, map each @ to a user for it to be treated as a mention. Unmapped @ displays as plain text.
Version 1 workflow:
- Configure draft message behavior
- Add
onChangelistener to track mentions - Set suggested users count
- Add/remove mentioned users
- Publish the draft message
- Optionally, render mentions as links or show user details on hover
Requires App Context
Enable App Context in the Admin Portal to mention users.
Interactive demo
See user mentions and channel references in action with this React demo.
Want to implement something similar?
Test it out
Type in @Mar or @Man in the input field and select one of the suggested users to mention.
Add user mentions
Add user mentions with @ followed by at least three letters (e.g., @Mar).
Mentioned users are stored in the MessageDraft object. When sent with send(), mention data is saved to message metadata.
Method signature
You can add a user reference by calling the addMention() method with the target of MentionTarget.user.
Refer to the addMention() method for details.
Sample code
Create the Hello Alex! I have sent you this link on the #offtopic channel. message where Alex is a user mention.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3
4// Add initial text
5messageDraft.update("Hello Alex!")
6
7// Add a user mention to the string "Alex"
8messageDraft.addMention(6, 4, "mention", "alex_d")
Remove user mentions
removeMention() removes a user mention from a draft message.
Method signature
You can remove user mentions from a draft message by calling the removeMention() method at the exact offset where the user mention starts.
Refer to the removeMention() method for details.
Offset value
Provide the exact offset position where the mention starts; otherwise, it won't be removed.
Sample code
Remove the user mention from the Hello Alex! I have sent you this link on the #offtopic channel. message where Alex is a user mention.
1// assume the message reads
2// Hello Alex! I have sent you this link on the #offtopic channel.`
3
4// remove the channel reference
5messageDraft.removeMention(6)
Send message with mentions
send() publishes the text message with mentioned users and emits events of type mention.
Method signature
Head over to the Drafts documentation for details on the method signature, input, and output parameters.
Sample code
Send the previously drafted message in which you mention users @James, Sarah and @Twain, Mark.
1// Create a new MessageDraftV2 instance with the suggested user source as "channel"
2const messageDraft = channel.createMessageDraftV2({
3 userSuggestionSource: "channel"
4});
5
6// Change the text
7messageDraft.update("Hello @James, Sara and @Twain, Mark.")
8
9// Add first user mention
10messageDraft.addMention(7, 12, "mention", "sarah_j")
11
12// Add second user mention
13messageDraft.addMention(24, 12, "mention", "twain_m")
14
15messageDraft.send().then((response) => {
show all 19 linesShow mention as link
getMessageElements() renders user mentions as clickable links in published messages. Create custom functions to customize rendering.
Also used for plain/text links and channel references.
Method signature
Head over to the Links documentation for details on the method signature, input, and output parameters.
Sample code
Show all linked mentions in a message as clickable links.
1message.getMessageElements()
Other examples
Customize mention rendering with these examples.
Add company links
Add a link to a PubNub profile under each user mention.
- React
- React Native
- Vue
- Angular
1const renderMessagePart = (messagePart: MixedTextTypedElement) => {
2 if (messagePart.type === "mention") {
3 // assuming messagePart.content.id is the user ID
4 const pubnubProfileUrl = `https://pubnub.com/profiles/${messagePart.content.id}`;
5 return (
6 <span>
7 <a href={pubnubProfileUrl}>{messagePart.content.name}</a>
8 {" "}
9 {/* add a space after the user mention */}
10 </span>
11 );
12 }
13 return "";
14}
1import React from 'react';
2import { Text, Linking, View } from 'react-native';
3
4const renderMessagePart = (messagePart) => {
5 if (messagePart.type === "mention") {
6 const pubnubProfileUrl = `https://pubnub.com/profiles/${messagePart.content.id}`;
7 return (
8 <View>
9 <Text>
10 <Text onPress={() => Linking.openURL(pubnubProfileUrl)}>
11 {messagePart.content.name}
12 </Text>
13 {" "}
14 </Text>
15 </View>
show all 20 lines1<template>
2 <div>
3 <span v-for="messagePart in messageParts" :key="messagePart.content.id">
4 <template v-if="messagePart.type === 'mention'">
5 <a :href="getPubnubProfileUrl(messagePart.content.id)">{{ messagePart.content.name }}</a>
6 <!-- add a space after the user mention -->
7 </template>
8 </span>
9 </div>
10</template>
11
12<script>
13export default {
14 data() {
15 return {
show all 27 lines1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-message',
5 template: `
6 <span>
7 <ng-container *ngFor="let messagePart of messageParts">
8 <ng-container *ngIf="messagePart.type==='mention'">
9 <a [href]="getPubnubProfileUrl(messagePart.content.id)">
10 {{ messagePart.content.name }}
11 </a>
12
13 </ng-container>
14 <ng-container *ngIf="messagePart.type!=='mention'">
15 <!-- render other message elements, like text:
show all 33 linesModify display color
Change the mentions display color from the default blue to green.
- React
- React Native
- Vue
- Angular
1const renderMessagePart = (messagePart: MixedTextTypedElement) => {
2 if (messagePart.type === "mention") {
3 const linkStyle = {
4 color: "green", // set the color to green
5 // add any other desired styles here, e.g., textDecoration: "underline"
6 };
7
8 return (
9 <a href={`https://pubnub.com/${messagePart.content.id}`} style={linkStyle}>
10 {messagePart.content.name}
11 </a>
12 );
13 }
14
15 return "";
show all 16 lines1import React from 'react';
2import { Text } from 'react-native';
3
4const renderMessagePart = (messagePart) => {
5 if (messagePart.type === "mention") {
6 const linkStyle = {
7 color: "green", // set the color to green
8 // add any other desired styles here, e.g., textDecorationLine: "underline"
9 };
10
11 return (
12 <Text style={linkStyle}>
13 {messagePart.content.name}
14 </Text>
15 );
show all 19 lines1<template>
2 <div>
3 <span v-for="messagePart in messageParts" :key="messagePart.id">
4 <a v-if="messagePart.type === 'mention'"" :href="`https://pubnub.com/${messagePart.content.id}`" :style="linkStyle">
5 {{ messagePart.content.name }}
6 </a>
7 <!-- render other message elements, like text:
8 <span v-else>
9 <span :style="color: green;" v-if="messagePart.type === 'text'">{{ messagePart.content.text }}</span>
10 </span> -->
11 </span>
12 </div>
13</template>
14
15<script>
show all 31 lines1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-message',
5 template: `
6 <ng-container *ngFor="let messagePart of messageParts">
7 <a *ngIf="messagePart.type === 'mention'"
8 [href]="'https://pubnub.com/' + messagePart.content.id"
9 style="color: green;">
10 {{ messagePart.content.name }}
11 </a>
12 </ng-container>
13 `,
14})
15export class MessageComponent {
show all 21 linesShow linked mention preview
getMessagePreview() returns message draft elements (text, user mentions, channel references, URLs). Format each element type separately, such as rendering mentions as profile links.
Method signature
Head to the Links documentation for details on the method signature, input, and output parameters.
Sample code
Show a preview of the linked mention.
1messageDraft.getMessagePreview()
For examples of how you can customize linked mention previews, refer to the getMessageElements() method that's similar in structure but is meant for final, published messages.
Collect all user-related mentions
getCurrentUserMentions() retrieves all instances where the current user was mentioned in channels or threads. Use this to build a mentions feed.
Method signature
This method has the following signature:
1chat.getCurrentUserMentions({
2 startTimetoken?: string;
3 endTimetoken?: string;
4 count?: number;
5}): Promise<{
6 enhancedMentionsData: UserMentionData[];
7 isMore: boolean;
8}>
Input
| Parameter | Description |
|---|---|
startTimetokenType: stringDefault: n/a | Timetoken delimiting the start of a time slice (exclusive) to pull messages with mentions from. For details, refer to the Fetch History section. |
endTimetokenType: stringDefault: n/a | Timetoken delimiting the end of a time slice (inclusive) to pull messages with mentions from. For details, refer to the Fetch History section. |
countType: numberDefault: 100 | Number of historical messages with mentions to return in a single call. Since each call returns all attached message actions by default, the maximum number of returned messages is 100. For more details, refer to the description of the includeMessageActions parameter in the JavaScript SDK docs. |
Output
| Parameter | Description |
|---|---|
Promise<>Type: object | Returned object containing two fields: enhancedMentionsData and isMore. |
→ enhancedMentionsDataType: UserMentionData[] (ChannelMentionData or ThreadMentionData) | Array listing the requested number of historical mention events with a set of information that differ slightly depending on whether you were mentioned in the main (parent) channel or in a thread. For mentions in the parent channel, the returned ChannelMentionData includes these fields: event (of type mention), channelId where you were mentioned, message that included the mention, userId that mentioned you. For mentions in threads, the returned ThreadMentionData includes similar fields, the only difference is that you'll get parentChannelId and threadChannelId fields instead of just channelId to clearly differentiate the thread that included the mention from the parent channel in which this thread was created. |
→ isMoreType: boolean | Info whether there are more historical events to pull. |
Sample code
List the last ten mentions for the current chat user.
1await chat.getCurrentUserMentions(
2 {
3 count: 10
4 }
5)
Show notifications for mentions
listenForEvents() monitors mention events in channels and threads you're a member of. Use this to trigger pop-up notifications.
Events documentation
See Chat events for details on mention event types.
Method signature
This method has the following parameters:
1chat.listenForEvents({
2 user: string;
3 type?: "mention";
4 callback: (event: Event<"mention">) => unknown;
5}): () => void
Input
| Parameter | Description |
|---|---|
user *Type: stringDefault: Channel equal to user ID | Channel to listen for new mention events. In the case of mention events, this channel is always the current user's ID. You can refer to it through chat.currentUser.id. |
typeType: stringDefault: n/a | Type of events. mention is the type defined for all mention-created events. |
callback *Type: n/a Default: n/a | Callback function passed as a parameter. It defines the custom behavior to be executed whenever a mention event type is detected on the specified channel. |
channelType: stringDefault: | This parameter is deprecated. Use user instead. mention events. In the case of mention events, this channel is always the current user's ID. You can refer to it through chat.currentUser.id. |
methodType: stringDefault: | This parameter is deprecated. You no longer have to provide a method used to send this event type as the method is now passed automatically. publish for all events related to reporting. |
Output
| Type | Description |
|---|---|
() => void | Function you can call to disconnect (unsubscribe) from the channel and stop receiving mention events. |
Sample code
Print a notification for a mention of the current chat user on the support channel.
1const chat = {
2 listenForEvents: async (config) => {
3 const simulateEvent = () => {
4 const event = "mention";
5 const eventData = {
6 channel: "support",
7 user: "John",
8 message: "You have a new support request!",
9 };
10 if (event === config.type) {
11 config.callback(eventData);
12 }
13 };
14
15 // simulate a single event when listening starts
show all 28 linesCreate message with mentions
createMessageDraft() creates a draft message with user mentions.
Mentioned users are added to the MessageDraft object and stored in message metadata when sent.
Method signature
Head over to the Drafts documentation for details on the method signature, input, and output parameters.
Sample code
Create a message mentioning channel members @James, Sarah and @Twain, Mark.
1// version 2
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3
4// Add initial text
5messageDraft.update("Hello Alex and Sarah!")
6
7// Add a user mention to the string "Alex"
8messageDraft.addMention(6, 4, "mention", "alex_d"))
9
10// Add a user mention to the string "Alex"
11messageDraft.addMention(15, 5, "mention", "sarah_j"))
12
13// version 1
14const newMessageDraft = this.channel.createMessageDraft({ userSuggestionSource: "channel" })
15const suggestedUsers = []
show all 27 linesTrack mentions
- Version 2
- Version 1
In message draft v2, use the Message draft state listener to track mentions.
Version 1 only
See Message Draft for version differences.
onChange() detects @ mentions in text input. When found, return suggested users and add them to the mention.
Method signature
This method has the following signature:
1messageDraft.onChange(text: string): Promise<{
2 users: {
3 nameOccurrenceIndex: number;
4 suggestedUsers: User[];
5 };
6 channels: {
7 channelOccurrenceIndex: number;
8 suggestedChannels: Channel[];
9 };
10}>
Input
| Parameter | Description |
|---|---|
text *Type: stringDefault: n/a | Typed in a message containing @ that is mapped to a specific user's name (or # for a channel reference). |
Output
| Parameter | Description |
|---|---|
Promise<>Type: object | Returned object containing these fields: users (for @mentions) and channels (for #references). |
usersType: object | Returned object containing these fields for mentioned users: nameOccurrenceIndex and suggestedUsers. |
→ nameOccurrenceIndexType: number | Specific occurrence of @ in the message (like 3) that is mapped to a given user. |
→ suggestedUsersType: User[] | List of users that match the typed text after @, like Mark for @Mar. |
channelsType: object | Returned object containing these fields for referenced channels: channelOccurrenceIndex and suggestedChannels. |
→ channelOccurrenceIndexType: number | Specific occurrence of # in the message (like 3) that is mapped to a given channel. |
→ suggestedChannelsType: Channel[] | List of channels that match the typed text after #, like Support for #Sup. |
Sample code
Track mentions for messages on the current channel.
1const newMessageDraft = this.channel?.createMessageDraft()
2
3 async handleInput(text: string) {
4 const response = await newMessageDraft.onChange(text)
5
6 const suggestedUsers = response.users.suggestedUsers
7 const lastAffectedNameOccurrenceIndex = response.users.nameOccurrenceIndex
8 }
Get user suggestions
Version 1 only
See Message Draft for version differences.
getUserSuggestions() returns users matching a 3-letter string from channel members or global users.
Example: typing Sam returns Samantha, Samir, etc. Default limit: 10 users (max: 100).
Method signature
This method can be called on two Chat SDK objects and has the following signature:
-
Called on the
Channelobject1channel.getUserSuggestions(
2 text: string,
3 {
4 limit: number
5 }
6): Promise<Membership[]> -
Called on the
Chatobject1chat.getUserSuggestions(
2 text: string,
3 {
4 limit: number
5 }
6): Promise<User[]>
Input
| Parameter | Description |
|---|---|
text *Type: stringDefault: n/a | At least a 3-letter string typed in after @ with the user name you want to mention. |
limit *Type: numberDefault: 10 | Maximum number of returned usernames that match the typed 3-letter suggestion. The default value is set to 10, and the maximum is 100. |
Output
| Type | Returned on Channel object | Returned on Chat object | Description |
|---|---|---|---|
Promise<Membership[]> | Yes | No | Returned array of Membership objects. |
Promise<User[]> | No | Yes | Returned array of User objects. |
Sample code
Return five channel users whose names start with Mar.
1chat.getUserSuggestions(
2 "@Mar, can you look at this ticket?",
3 { limit: 5 }
4)
Add mentioned user
Version 1 only
See Message Draft for version differences.
addMentionedUser() maps an @ character to a specific user. Without this mapping, @ displays as plain text.
Method signature
This method has the following signature:
1messageDraft.addMentionedUser(
2 user: User,
3 nameOccurrenceIndex: number
4): void
Input
| Parameter | Description |
|---|---|
user *Type: UserDefault: n/a | User object that you want to map to a given occurrence of @ in the message. |
nameOccurrenceIndex *Type: numberDefault: n/a | Specific occurrence of @ in the message (like 3) that you want to map to a given user. |
Output
| Type | Description |
|---|---|
void | Method returns no output data. |
Sample code
Map @Twain, Mark to the third @ in the message.
1const response = await messageDraft.onChange("Hello @twai")
2// let's say it returns { suggestedUsers: [user Mark Twain, someOtherUser...], nameOccurrenceIndex: 0 }
3messageDraft.addMentionedUser(response.suggestedUsers[0], response.nameOccurrenceIndex)
Remove mentioned user
Version 1 only
See Message Draft for version differences.
removeMentionedUser() unmaps an @ occurrence from a user. Deleting any character from a mention automatically removes the mapping.
Method signature
This method has the following signature:
1messageDraft.removeMentionedUser(
2 nameOccurrenceIndex: number
3): void
Input
| Parameter | Description |
|---|---|
nameOccurrenceIndex *Type: numberDefault: n/a | Specific occurrence of @ in the message (like 3) that you want to unmap from a given user. |
Output
| Type | Description |
|---|---|
void | Method returns no output data. |
Sample code
Remove @Twain, Mark from the third @ in the message.
1messageDraft.removeMentionedUser(3)
Show user details on highlighting
Version 1 only
See Message Draft for version differences.
getHighlightedMention() returns user details when the cursor hovers over a mention, or null when moved away.
Method signature
This method has the following signature:
1messageDraft.getHighlightedMention(selectionStart: number): {
2 mentionedUser: null;
3 nameOccurrenceIndex: number;
4} | {
5 mentionedUser: User;
6 nameOccurrenceIndex: number;
7}
Input
| Parameter | Description |
|---|---|
selectionStart *Type: numberDefault: n/a | Position of the cursor above the given mention (@) in the message. |
Output
| Parameter | Description |
|---|---|
mentionedUserType: User or null | Mentioned user mapped to the number of mention (nameOccurrenceIndex) in the message, or a null value if no user is returned. |
nameOccurrenceIndexType: number | Specific occurrence of @ in the message (like 3) that is mapped to a given user. |
Sample code
Highlight a mention (if any) of the current caret position.
1handleCaret(event: any) {
2 this.currentlyHighlightedMention = this.newMessageDraft.getHighlightedMention(
3 this.userInput?.nativeElement.selectionStart
4 )
5}
Get mentioned users (deprecated)
Deprecated
This method is deprecated.
Use the mentionedUsers getter method to return all users mentioned in a message.
Method signature
This method has the following signature:
1message.mentionedUsers: {
2 id: string;
3 name: string
4}[]
Properties
| Property | Description |
|---|---|
mentionedUsersType: array | Method can return a value of any type. |
Returns
| Property | Description |
|---|---|
objectType: array | List of key-value pairs that stand for specific mentioned users. |
→ idType: string | Unique identifier of the mentioned user. |
→ nameType: string | Name of the mentioned user. |
Sample code
Check if the last message on the support channel contains any mentions.
1// reference the "support" channel
2const channel = await chat.getChannel("support")
3// get the last message on the channel
4const lastMessage = (await channel.getHistory({count: 1})).messages[0]
5// check if it contains any user mentions
6message.mentionedUsers