---
source_url: https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/links
title: Links
updated_at: 2026-05-25T11:25:02.823Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Links

:::warning Version 2 functionality
This document uses message drafts v2 unless otherwise specified.
:::

Encode URLs (`www`, `http`, `https`) as clickable links or create hyperlinks with custom text.

:::tip Generic referencing
Channel references, user mentions, and links share the same `MessageElement` structure with different `mentionType` values.
:::

## Add links

`addMention()` adds a link to a [draft message](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts).

### Method signature

Call `addMention()` with `mentionType` set to `textLink`. See [addMention()](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts#add-message-element) for details.

### Sample code

Create the `Hello Alex! I have sent you this link on the #offtopic channel.` message where `link` is a URL.

```ts
// Create a message draft
messageDraft = channel.createMessageDraft({ userSuggestionSource: "global" })

// Add initial text
messageDraft.update("Hello Alex! I have sent you this link on the #offtopic channel.")

// Add a user mention to the string "Alex"
messageDraft.addMention(33, 4, "textLink","https://example.com")
```

## Remove links

`removeMention()` removes a link from a [draft message](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts).

### Method signature

Call `removeMention()` at the exact offset where the link starts. See [removeMention()](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts#remove-message-element) for details.

:::warning Offset value
If you don't provide the position of the first character of the message element to remove, it isn't removed.
:::

### Sample code

Remove the link from the `Hello Alex! I have sent you this link on the #offtopic channel.` message where `link` is a URL.

```c
// assume the message reads
// Hello Alex! I have sent you this link on the #offtopic channel.`

// remove the link mention
messageDraft.removeMention(33)
```

## Render URLs

`getMessageElements()` returns URLs as link elements in published messages. Customize rendering with your own functions. This method also handles [mention rendering](https://www.pubnub.com/docs/chat/chat-sdk/build/features/users/mentions#show-mention-as-link).

### Method signature

This method has the following signature:

```ts
message.getMessageElements(): MixedTextTypedElement[]
```

#### Input

This method doesn't take any parameters.

#### Output

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| MixedTextTypedElement[] | array | Optional |  | A returned array of elements that the message is composed of. Each element is a separate array. For plain text, you'll get a `text` type element, like `{"type": "text", "content": { "text": "This is a sample text "}}`. For plain links, you'll get a `plainLink` element, like `{"type": "plainLink", "content": {"link": "https://my-company.com"}}`. For text links, you'll get a `textLink` element, like `{"type": "textLink", "content": {"link": "https://my-company.com", "text": "my company"}}`. For [mentions](https://www.pubnub.com/docs/chat/chat-sdk/build/features/users/mentions), you'll get a `mention` element, like `{"type": "mention", "content": {"name": "Peter", "id": "some-id-for-peter"}}`. For [channel references](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/references), you'll get a `channelReference` element, like `{"type": "channelReference", "content": {"name": "Support", "id": "some-id-for-channel"}}`. |

### Sample code

Show all URLs starting with `www`, `http`, or `https` as clickable links.

```ts
message.getMessageElements()
```

### Other examples

Customize link rendering with these examples.

#### Show links as plain text

Show all URLs starting with `www`, `http`, or `https` as plain text instead of clickable links.

##### React

```ts
const renderMessagePart = (messagePart: MixedTextTypedElement) => {
  if (messagePart.type === "plainLink") {
    return messagePart.content.link;
  }
  return "";
}
```

##### React Native

```jsx
import React from 'react';
import {Text, Linking} from 'react-native';

const showClickableLink = (url) => {
    if(url.startsWith('http') || url.startsWith('https') || url.startsWith('www')) { 
        return (
            <Text style={{color: 'blue'}} onPress={() => Linking.openURL(url)}>
               {url}
            </Text>
        );
    }
    return url;
};

export default showClickableLink;
```

##### Vue

```html
<template>
    <a v-if="isURL(text)" :href="text" target="_blank">{{ text }}</a>
    <p v-else>{{ text }}</p>
</template>

<script>
export default {
    props: {
        text: String
    },
    methods: {
        isURL(str) {
            return str.startsWith('http') || str.startsWith('https') || str.startsWith('www');
        }
    }
}
</script>
```

##### Angular

You can create a component to handle the rendering of URLs using Angular's built-in directive for binding attributes and events:

```html
<!-- your-component.component.html -->
<a *ngIf="isUrl(url)" [href]="url" target="_blank">{{ url }}</a>
<p *ngIf="!isUrl(url)">{{url}}</p>
```

Add the corresponding TypeScript code:

```ts
// your-component.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css'],
})
export class YourComponent {
  @Input() url: string;

  isUrl(): boolean {
    return this.url.startsWith('http') || this.url.startsWith('https') || this.url.startsWith('www');
  }
}
```

#### Change background color of plain links

Change the background color of all plain links to yellow.

##### React

```ts
if (messagePart.type === "plainLink") {
    const linkStyle = { backgroundColor: "yellow" };
    return (
      <a href={messagePart.content.link} style={linkStyle}>
        {messagePart.content.link}
      </a>
    );
  }
  return "";
```

##### React Native

```jsx
import { Text, Linking } from 'react-native';

if (messagePart.type === "plainLink") {
    const linkStyle = { backgroundColor: 'yellow' };
    return (
        <Text 
            onPress={() => Linking.openURL(messagePart.content.link)} 
            style={linkStyle}
        >
            {messagePart.content.link}
        </Text>
    );
}
return null;
```

##### Vue

```html
<template>
  <div>
    <a v-bind:style="linkStyle" v-bind:href="messagePart.content.link" v-if="messagePart.type === 'plainLink'">
      {{ messagePart.content.link }}
    </a>
  </div>
</template>

<script>
export default {
  data() {
    return {
      messagePart: {
        type: 'plainLink',
        content: {
          link: 'http://example.com',
        },
      }, 
      linkStyle: {
        backgroundColor: 'yellow',
      },
    };
  },
};
</script>
```

##### Angular

Use `[style]` to bind a styles object to an HTML element:

```html
<a *ngIf="messagePart?.type === 'plainLink'" [href]="messagePart?.content.link" [style]="{'background-color': 'yellow'}">
   {{messagePart?.content.link}}
</a>
```

Add the corresponding TypeScript code:

```ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{
  messagePart = {
    type: 'plainLink', 
    content: { 
      link: 'http://example.com' 
    } 
  };
}
```

#### Change background color of text links

Change the background color of all text links to red.

##### React

```ts
const renderMessagePart = (messagePart: MixedTextTypedElement) => {
  if (messagePart.type === "textLink") {
    return (
      <a href={messagePart.content.link} style={{ backgroundColor: 'red' }}>
        {messagePart.content.text}
      </a>
    );
  }
  return "";
}
```

##### React Native

```ts
import { Text, TouchableHighlight } from 'react-native';

const renderMessagePart = (messagePart) => {
  if (messagePart.type === "textLink") {
    return (
      <TouchableHighlight onPress={() => handleLinkPress(messagePart.content.link)}>
        <Text style={{ backgroundColor: 'red' }}>{messagePart.content.text}</Text>
      </TouchableHighlight>
    );
  }
  return null;
}
```

##### Vue

```html
<template>
  <div>
    <span v-if="messagePart.type === 'textLink'">
      <a :href="messagePart.content.link" :style="{ backgroundColor: 'red' }">
        {{ messagePart.content.text }}
      </a>
    </span>
    <span v-else></span>
  </div>
</template>

<script>
export default {
  props: {
    messagePart: Object // assuming the messagePart is passed as a prop
  }
}
</script>
```

##### Angular

```ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <ng-container *ngFor="let messagePart of messageParts">
      <a *ngIf="messagePart.type === 'textLink'" [href]="messagePart.content.link" [ngStyle]="{ 'background-color': 'red' }">
        {{ messagePart.content.text }}
      </a>
    </ng-container>
  `,
})
export class AppComponent {
  messageParts: MixedTextTypedElement[] = [
    {
      type: 'text',
      content: {
        link: 'https://example.com',
        text: 'Link 1',
      },
    },
    {
      type: 'textLink',
      content: {
        link: 'https://example.com',
        text: 'Link 2',
      },
    },
    // ... other message parts
  ];
}

interface MixedTextTypedElement {
  type: string;
  content: {
    link: string;
    text: string;
  };
}
```

#### Exclude selected links

Don't display YouTube links as plain links.

##### React

```ts
const renderMessagePart = (messagePart: MixedTextTypedElement) => {
  if (messagePart.type === "plainLink") {
    const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//i;
    if (youtubeRegex.test(messagePart.content.link)) {
      // if it's a YouTube link, you can handle it differently, for example, embedding the video or displaying a custom YouTube link format
      return <div>Custom rendering for YouTube link: {messagePart.content.link}</div>;
    } else {
      // for other plain links, display them as regular anchor tags
      return <a href={messagePart.content.link}>{messagePart.content.link}</a>;
    }
  }
  return "";
}
```

##### React Native

```ts
import { Text, Linking } from 'react-native';

const renderMessagePart = (messagePart) => {
  if (messagePart.type === 'plainLink') {
    const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//i;
    if (youtubeRegex.test(messagePart.content.link)) {
      // if it's a YouTube link, you can handle it differently, for example, embedding the video or displaying a custom YouTube link format
      return <Text>Custom rendering for YouTube link: {messagePart.content.link}</Text>;
    } else {
      // for other plain links, display them as regular anchor tags
      return (
        <Text onPress={() => Linking.openURL(messagePart.content.link)}>
          {messagePart.content.link}
        </Text>
      );
    }
  }
  return null;
};
```

##### Vue

```ts
<template>
  <div>
    <template v-if="messagePart.type === 'plainLink'">
      <template v-if="isYouTubeLink(messagePart.content.link)">
        <!-- Custom rendering for YouTube link -->
        <div>Custom rendering for YouTube link: {{ messagePart.content.link }}</div>
      </template>
      <template v-else>
        <!-- Display plain links as anchor tags -->
        <a :href="messagePart.content.link">{{ messagePart.content.link }}</a>
      </template>
    </template>
  </div>
</template>

<script>
export default {
  props: {
    messagePart: {
      type: Object,
      required: true
    }
  },
  methods: {
    isYouTubeLink(link) {
      const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//i;
      return youtubeRegex.test(link);
    }
  }
};
</script>
```

##### Angular

```ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-message',
  template: `
    <ng-container *ngFor="let messagePart of messageParts">
      <div *ngIf="messagePart.type === 'plainLink'">
        <ng-container *ngIf="isYouTubeLink(messagePart.content.link)">
          Custom rendering for YouTube link: {{ messagePart.content.link }}
        </ng-container>
        <a *ngIf="!isYouTubeLink(messagePart.content.link)" href="{{messagePart.content.link}}">
          {{ messagePart.content.link }}
        </a>
      </div>
    </ng-container>
  `,
})
export class MessageComponent {
  messageParts: MixedTextTypedElement[] = []; // replace MixedTextTypedElement with your actual type

  isYouTubeLink(link: string): boolean {
    const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//i;
    return youtubeRegex.test(link);
  }
}
```

## Show text link preview

`getMessagePreview()` returns message draft elements (text, URLs, [mentions](https://www.pubnub.com/docs/chat/chat-sdk/build/features/users/mentions), [channel references](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/references)) for custom rendering.

### Method signature

This method has the following signature:

```ts
messageDraft.getMessagePreview(): MixedTextTypedElement[]
```

#### Input

This method doesn't take any parameters.

#### Output

| Parameter | Description |
| --- | --- |
| `MixedTextTypedElement[]`Type: `array` | A returned array of elements that the message is composed of. Each element is a separate array. For plain text, you'll get a `text` type element, like `{"type": "text", "content": { "text": "This is a sample text "}}`. For plain links, you'll get a `plainLink` element, like `{"type": "plainLink", "content": {"link": "https://my-company.com"}}`. For text links, you'll get a `textLink` element, like `{"type": "textLink", "content": {"link": "https://my-company.com", "text": "my company"}}`. For [user mentions](https://www.pubnub.com/docs/chat/chat-sdk/build/features/users/mentions), you'll get a `mention` element, like `{"type": "mention", "content": {"name": "Peter", "id": "some-id-for-peter"}}`. |

### Sample code

Show a preview of the modified link.

```ts
// replace a link with text
messageDraft.addLinkedText(
  {
    text: "this support article",
    link: "https://www.support-article.com/",
    positionInInput: 10
  }
)
//show the preview of the changed link
messageDraft.getMessagePreview()
```

For examples of how you can customize [draft message](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts) previews, refer to the [getMessageElements() method](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/links#other-examples) that's similar in structure but is meant for final, published messages.

## Add linked text

`addLinkedText()` replaces a plain link with descriptive text in a [draft message](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts).

### Method signature

This method has the following signature:

```ts
messageDraft.addLinkedText({
  text: string;
  link: string;
  positionInInput: number;
}): void
```

#### Input

| Parameter | Description |
| --- | --- |
| `text` *Type: `string`Default: n/a | Text that you want to replace the link with. |
| `link` *Type: `string`Default: n/a | Link that you want to replace with text. |
| `positionInInput` *Type: `number`Default: n/a | Position of a character in a message where the link you want to replace starts. It's counted from the beginning of the message (including spaces), with `0` as the first character. |

#### Output

| Type | Description |
| --- | --- |
| `void` | Method returns no output data. |

#### Errors

You'll get the `You need to insert a URL` error if you don't provide a URL. If you try to replace a link with a different link, you'll get the `You cannot insert a link inside another link` error.

### Sample code

Replace `Check out this support article https://www.support-article.com/.` with `Check out this support article`.

```ts
messageDraft.addLinkedText(
  {
    text: "this support article",
    link: "https://www.support-article.com/",
    positionInInput: 10
  }
)
```

## Remove linked text

`removeLinkedText()` removes a linked URL from text in a [draft message](https://www.pubnub.com/docs/chat/chat-sdk/build/features/messages/drafts).

### Method signature

This method has the following signature:

```ts
messageDraft.removeLinkedText(positionInInput: number): void
```

#### Input

| Parameter | Description |
| --- | --- |
| `positionInInput` *Type: `number`Default: n/a | Beginning of the text in a message where the link you want to remove starts. The position is counted from the beginning of the message (including spaces), with `0` as the first character. |

#### Output

| Type | Description |
| --- | --- |
| `void` | Method returns no output data. |

#### Errors

If you don't provide the link text's position in the message, you'll get the `You need to insert a number` error. If you try to remove a link that doesn't exist, you'll get the `This operation is noop. There is no link at this position.` error.

### Sample code

Remove a link from the "Check out `this support article`." message.

```ts
messageDraft.removeLinkedText(10)
```

## Get text links (deprecated)

:::warning Deprecated
This method is deprecated.
:::

`textLinks` returns all text links in a message.

### Method signature

This method has the following signature:

```ts
message.textLinks: TextLink[]
```

#### Properties

| Property | Description |
| --- | --- |
| `textLinks`Type: `TextLink[]` | Array of text links included in the message. |

### Sample code

Get all text links included in the message with the `16200000000000000` timetoken.

```ts
// reference the "message" that you're interested in
const message = await channel.getMessage("16200000000000000")

// get all text links
message.textLinks
```