Proposal for emoji reactions content type

This improvement proposal idea imagines a way to add emoji reactions in clients that support XMTP. This proposal relies heavily on knowledge of this reply content type improvement proposal idea, specifically the ideas around using referencing_message_id.

Update 2023-11-28

@rygine has added a reply below, indicating how a version of the proposed Reaction content type has been implemented in the XMTP SDKs so far. Should this approach be favored by the community, I will draft a formal XIP to see that it be enshrined as an official content type.

In it there are two new additions to the content type, action and schema which are described below:


Emoji reactions in messaging apps are useful because they provide a quick and easy way for users to express their emotions, thoughts, hot takes, etc. to a message without having to type out a response. This can help to facilitate more efficient, effective, and even evocative communication, as well as add an element of fun and personality to the conversation. Additionally, emoji reactions can be a useful tool for group chats, as they allow multiple users to react to a message at once, providing a more comprehensive understanding of the group’s overall response. :grin:

This proposal introduces a means to support emoji-as-reactions.

  authorityId: ""
  typeId: “emojiReaction
  versionMajor: 0
  versionMinor: 1

Note the use of the name emojiReaction. This is to focus specifically on the use of emoji as the reaction medium.

The encoded content MUST have the following parameters:

  // The message ID for the message that is being reacted to
  referencing_message_id: string,
  // The emoji character
  emoji: string,


Additional context

As emoji are characters in the UTF-8 (unicode) character set, support for encoding and decoding UTF-8 is required by supporting clients.


See this proposal for definition.


In the above specification, the emoji character is added directly to the property, such as 🫠.


const reaction = {
  emoji: "🫠"

await conversation.send(reply, {
  contentType: ContentTypeEmojiReaction,
  contentFallback: `[Reaction] ${client.address} reacted to ${message.content} with:\n\n${reaction.emoji}`

In the above example, the fallback text includes all or a portion of the message being replied to, so that the context can be understood in clients that do not yet support reactions. This is similar to how iMessage handles reactions in SMS conversations.

As mentioned in the reply content type proposal, it may be desirable to truncate ${message.content} to ~140 characters so as to not make for an overwhelming experience.


The presentation of emoji reactions is intentionally left out of this proposal, as those are decisions to be made by client applications. The official proposal may include some examples of possible UI.

Additional considerations

Clients SHOULD account for situations when an emoji character is sent that isn’t yet supported by the client or OS. This may happen when an OS update includes new emoji characters, which are then made available to a sender, but may not be supported on the recipient’s client, OS, or device.

We have implemented this proposal in an official content type located here and published on the NPM registry here.

This implementation contains 2 additional fields from the proposal: action and schema.


The action field has 2 possible values: added and removed. This field allows for un-reacting to messages. Because of this, processing reactions now requires all conversation messages in order to get the final state of reactions.


As part of ongoing internal conversations, it was suggested to add a schema field to help guide developers with processing reactions.

There are 3 possible values to cover the most common use cases:

  • unicode: This value indicates the reaction is unicode value corresponding to an emoji and should be displayed as is
  • shortcode: This value means that the reaction is a string alias or shortcode for an emoji and should be converted by clients as they see fit
  • custom: The reaction is custom and may not refer to an emoji

For more information on shortcodes, check out this resource.

The final payload for the reaction content type can be found here.

An example implementation of this content type has been added to our official React Playground, which can be accessed live here. The PR that included this implementation can be found here.

Code sample

import { ContentTypeReaction } from "@xmtp/content-type-reaction";
import type { Reaction } from "@xmtp/content-type-reaction";

// react with 👍
const reaction: Reaction = {
  action: "added",
  content: "👍",
  schema: "unicode",

await conversation.send(reaction, {
  contentType: ContentTypeReaction,
  contentFallback: `${client.address} reacted to "${originalMessage.content}" with {reaction.content}`

// un-react with 👍
const reaction: Reaction = {
  action: "removed",
  content: "👍",
  schema: "unicode",

await conversation.send(reaction, {
  contentType: ContentTypeReaction,
  contentFallback: `${client.address} un-reacted to "${originalMessage.content}" with {reaction.content}`