A conversation is a place where two or more people write messages to each other. Some messaging apps use words like chat, chatroom or channel for this concept. Any sort of conversation, from a brief 1-on-1 chat to a continuously active 20-person chat room, is called a conversation in TalkJS.

A conversation has one or more participants and zero or more ordered messages.

Group chats vs 1-on-1 chats

TalkJS does not fundamentally differentiate between one-on-one conversations and group conversations. They're all just conversations.

Any conversation with more than two participants is treated as a group conversation. TalkJS treats these conversations slightly different. For example, sender names are shown in the message bubbles in group conversations and not in one-on-one conversations.

If you add a third participant to a one-on-one conversation, then it automatically turns into a group conversation.

The conversation ID

Every conversation needs to have a unique ID that you choose. Choosing your own conversation ID keeps you firmly in control of the granularity of a conversation. For example, should any two people who chat have a single, continuous conversation? Or should there be a new, separate conversation for every purchase or transaction, even if two given users may have multiple transactions?

Here are three ways in which TalkJS customers often choose a conversation ID:

1. One conversation per purchase

If your app tracks purchases or transactions or something similar, and you want to have a single conversation for every purchase, then it may be very effective to use your internal purchase ID as a conversation ID. One purchase, one conversation. Simple!

2. One conversation per two users

However, if you just want to create a conversation between two specific users, then inventing and storing a conversation ID might be cumbersome. In that case, it might be better to use a conversation ID that is derived from the user IDs that will participate in the conversation.

Our JS SDK provides a helper function, Talk.oneOnOneId that does exactly that: it orders two user IDs alphabetically, combines them, and hashes the result. This way, invoking it for any two users will always yield the same conversation ID.

See its page on the JS SDK reference for detailed information about how it works. If you also use the REST API, then you may need to replicate its behavior in your backend language. oneOnOneId has been designed to be easy to replicate in all popular languages and if it's not then we'll gladly help.

3. One conversation per topic (channel / chat room)

If you use TalkJS to make (semi-)public chat rooms that are divided per topic, then just use the channel topic or channel name as the conversation ID, and use setParticipant or the REST API to add the current user to it when appropriate.

Securing the conversation

It might be easy for users to guess other users' conversation IDs. That's a risk, because it means that they may be able to join conversations they're not supposed to be a part of.

For example, if you take approach 1 above, and purchase IDs are auto-incrementing, then a user who gets added to conversation 12345 about purchase 12345 may be able to deduct that there's also a conversation 12344. If they're tech savvy, they could enter some TalkJS calls in the browser developer tools and join conversation 12344.

This is a risk if the underlying IDs are predictable (for instance, because they're incrementing numbers and not UUIDs), or if the IDs can be easily looked up (by looking at public URLs, JavaScript source code, and so on).

Hard-to-predict IDs

A pragmatic approach to prevent this is to make the conversation ID hard to predict. You can do this easily and securely by computing an HMAC of the logical conversation ID. This is similar to how you generate the Identity Verification signature. You'd then use the result of the HMAC signature as the real conversation ID.

For example, if your backend is written in Ruby:

require 'openssl'

# assume that `purchase` is some database record about the current purchase
predictable_conversation_id = purchase.id
conversation_id = OpenSSL::HMAC.hexdigest('sha256', "SOMERANDOMSECRET", predictable_conversation_id)

The SOMERANDOMSECRET string can be any secret, just a random sequence of characters is fine. Securely store it in the backend as you would any other secret. Our GitHub examples repository has code samples that demonstrate how to do this in other languages.

Alternatives

If you need more control over who can access conversations, you can also disable synchronizing conversation data via the browser entirely. If you do this, then you can only create or modify conversations via the REST API, so then it does not matter if conversation IDs are easy to predict.

Conversation data

Field Type Description
id string

As described above.

Examples: 12345, "9c686648d9f4", "purchase:12345;customer:6789"

subject string

Optional. Describes the conversation in a human-friendly way. TalkJS will display it above the conversation and optionally in the Inbox's conversation feed. You can include some limited wiki-style formatting here.

Examples: "House by the sea", "House <https://example.com|by the sea>"

photoUrl string

Optional. The URL of a photo or icon for this conversation. Displayed in the chat UI instead of a user photo. Recommended in group conversations, because otherwise TalkJS falls back to a placeholder picture.

Example: "https://demo.talkjs.com/img/alice.jpg"

welcomeMessages string[]

Optional. An array of strings which will be rendered as System Messages at the start of this conversation.

Example: ["Hey there!", "We're usually online during office hours"]

custom object of strings

JSON-structured custom data that you wish to associate to this conversation. TalkJS does nothing with this data except make it available in the events that we send to your code and in your Email/SMS notification templates. You can use custom data for all kinds of purposes, such as customizing a user's email notification text, or transmitting contextual conversation data such as internal database IDs that this conversation relates to.

Example: {"purchaseId": "12345"}

Must be an object with string keys and string values; arbitrarily deeply nested JSON is not supported. If you need structured data for one of your custom fields, consider serializing it yourself (using e.g. JSON.stringify or similar functions). See also User.custom.

Further reading