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}`

I have a question about the shortcode schema. Given that there are a bunch of different shortcode formats, how would a recipient know which format to use (slack vs github vs emojibase)? It seems like we’d need more information to make use of this type.

What is the expected behaviour if the recipient is not able to read that particular shortcode format? Would we expect the Reaction to disappear, or should it use the fallback text?

i think this is something that the client should determine. if a client chooses not to support a shortcode format, i think it’s reasonable that it should also display a fallback in those cases.

we could also choose one or more standards to support, if the community thinks that’s the best approach.

But what happens when I send a shortcode between Client App A and Client App B? Somewhere, the choice of shortcode format needs to be communicated between those two apps.

An alternative approach would be to remove shortcode support from the spec for v1 and allow developers to use the custom emoji type where there would be no expectation of interoperability. Although I think that would really limit the usage of shortcode emoji.

what if we expand the schema option to include more explicit shortcode options, such as: shortcode-github, shortcode-slack, shortcode-discord, etc… ?

this would allow us to provide robust typing for the values and make it clear how a client should display the shortcode.

That could work. We could also allow for a parameter on the content type indicating the shortcode schemas, so we don’t have to enumerate all possibilities. But it does give you less options for type narrowing.

1 Like

At Converse we’ve been using the content type already implemented and we’re quite happy with it currently. We’re only using emoji-utf-8 characters with the unicode schema for now.


i like that idea, let’s do it.


Hello @mg -

It looks like there is resounding and clarifying support for your proposal for an emoji reactions content type!

Would you like to move forward with creating a formal XIP Draft for your idea?

You can get started by writing up your proposal using this XIP template.

For more info about how to fill out the template front matter and the overall process, see XIP-0: What is an XIP?

When you have your XIP Draft ready, open a PR in the XIPs folder in the XIPs repo.

If you have any questions, please feel free to post to Help & Resources: XIPs.

With much aloha,

XIP Editor

1 Like

This is now an XIP draft! See link here: by daria-github · Pull Request #36 · xmtp/XIPs · GitHub

1 Like

I’m in favor of removing some of the types and making this more interoperable. Per the tech review meeting today. :+1:

1 Like

Because this idea has progressed to become XIP-20: Reactions content type, we are closing this topic. Please direct all further discussions to the XIP-20 topic linked here.