# Bubblegram Docs

## Quick Start

Get from zero to a working chat widget in under 5 minutes.

	1. **Create an account** Sign up at [dash.bubblegram.co](https://dash.bubblegram.co).
	2. **Create a project** Enter a name and your site's domain (e.g. `example.com`).
	3. **Connect Telegram** Click **Link Telegram** in your project. One tap adds the bot and links the group. See [Telegram Setup](#telegram-setup).
	4. **Embed the script tag** Paste one line of HTML into your site. See [Embed the Widget](#embed-widget).
	5. **Done.** The chat bubble appears on your site. Visitors send messages; you reply in Telegram. Replies are delivered back to the widget in real time.


---

## Telegram Setup

Bubblegram delivers visitor messages to a Telegram group. Each visitor gets a dedicated topic thread so conversations stay organized.


---

### 1. Create a Telegram group

1. Open Telegram and tap the pencil icon (or "New Message").
2. Choose **New Group**.
3. Optionally add members (you can add yourself from another account, or a teammate). You can also skip this and create the group alone.
4. Give the group a name, then create it.


---

### 2. Enable Topics (Forum mode)

Topics allow each visitor to get their own thread inside the group. Without this, all messages arrive in one mixed stream.

**On desktop**

1. Open the group and click **Manage group**.
2. Go to **Topics** and enable it.
3. Set the display to **List**. This makes it easier to scan and manage multiple visitor conversations.

**On mobile**

1. Tap the group name at the top to open group info.
2. Tap **Group settings**.
3. Go to **Topics** and enable it.
4. Select **List** as the display style.

> **Warning:** **Required.** Topics must be enabled before linking. The bot creates a new topic for each visitor.

> **Info:** **Unmute the group.** Telegram mutes groups by default. Open the group, tap the bell icon, and select **Unmute** so you get notified when visitors send messages.

[Video: /assets/EnableTopics.mp4](/assets/EnableTopics.mp4)


---

### 3. Add the bot

In the dashboard, open your project and click **Link Telegram**. This opens Telegram with the bot pre-selected and admin permissions pre-filled. Confirm. The bot joins, gets admin rights, and links your group automatically. No extra steps.

> **Info:** **Token expires in 10 minutes.** If the link expires, go back to the dashboard and click **Link Telegram** again to get a new one.

![Link Telegram button in the Project Builder](/assets/link-to-telegram.png)

**Already have the bot in the group?**

If the bot was already a member before you started setup, the deep link won't fire. Instead, copy the `/start` command from the dashboard and send it in the group manually:

```
/start YOUR_LINK_TOKEN
```

The bot replies: *"Project linked successfully."* Then promote it to admin. It needs permission to manage topics, post messages, and delete messages.


---

## Embed the Widget

The widget loads from a CDN and is initialized with your project's API key.


---

### Script tag

Add this to your HTML, just before the closing `</body>` tag:

```html
<script
  src="https://cdn.bubblegram.co/widget.js"
  data-key="pk_live_YOUR_KEY_HERE"
  async
></script>
```

Your API key is shown in the project's **Embed** section in the dashboard, visible after your Telegram group is linked.


---

### Attributes

| Attribute | Required | Description |
| --- | --- | --- |
| `data-key` | **Required** | Your project's public API key. Starts with `pk_live_`. |
| `data-api` | **Optional** | API base URL. Defaults to `https://api.bubblegram.co`. |
| `data-email` | **Optional** | Pre-fill the visitor's email. Useful on server-rendered pages where the user is already signed in. Skips the email input even when "Require email" is enabled. |


---

### JavaScript API

After the script loads, a `Bubblegram` object is available on `window`. You can control the widget programmatically:

```js
Bubblegram.open()                        // open the chat panel
Bubblegram.close()                       // close the chat panel
Bubblegram.connect()                     // reconnect WebSocket (if disconnected)
Bubblegram.setEmail('user@example.com')  // pre-fill email for signed-in users
```

The widget has no way to detect your app's auth state on its own. Without `data-email` or `setEmail`, every visitor shows up as anonymous in your dashboard, signed in or not. Call `setEmail` yourself once the email is known after client-side auth. For example, in React or Next.js after the session loads:

```js
useEffect(() => {
  if (session?.user?.email) {
    window.Bubblegram?.setEmail(session.user.email)
  }
}, [session?.user?.email])
```

If this runs before `widget.js` has finished loading (common in SPAs, since the script tag is `async`), `window.Bubblegram` won't exist yet and the call is silently lost. Use the queue stub shown in the React/Next.js examples below to make it safe to call anytime.

Calling `setEmail` with a *different* email than the one already set starts a fresh conversation: the current session is cleared and reinitialized, local message history is wiped, and the WebSocket reconnects, before the new email is saved. The first `setEmail` call for a visitor (no email set yet) doesn't trigger this. Keep this in mind if you call `setEmail` again later, e.g. when a visitor switches accounts, since any messages from the old session won't carry over.

On server-rendered pages (PHP, Rails, Django, etc.) where the email is available at render time, use the `data-email` attribute instead:

```html
<script
  src="https://cdn.bubblegram.co/widget.js"
  data-key="pk_live_YOUR_KEY_HERE"
  data-email="<?= $currentUser->email ?>"
  async
></script>
```

For React, Next.js, or other SPAs, add the script to your root HTML file. In Vite or Create React App, that's `index.html`:

```html
<script>
  window.Bubblegram = window.Bubblegram || (function () {
    var q = []
    var api = { q: q }
    ;['init', 'sendMessage', 'connect', 'open', 'close', 'setEmail', 'destroy'].forEach(function (m) {
      api[m] = function () { q.push([m, Array.prototype.slice.call(arguments)]) }
    })
    return api
  })()
</script>
<script
  src="https://cdn.bubblegram.co/widget.js"
  data-key="pk_live_YOUR_KEY_HERE"
  async
></script>
```

In Next.js, use the built-in `Script` component in your `_app.tsx` or root layout. Load the stub with `beforeInteractive` so it exists before any of your components try to call `Bubblegram`:

```jsx

<Script id="bubblegram-stub" strategy="beforeInteractive">
  {`window.Bubblegram = window.Bubblegram || (function () {
    var q = []
    var api = { q: q }
    ;['init', 'sendMessage', 'connect', 'open', 'close', 'setEmail', 'destroy'].forEach(function (m) {
      api[m] = function () { q.push([m, Array.prototype.slice.call(arguments)]) }
    })
    return api
  })()`}
</Script>
<Script
  src="https://cdn.bubblegram.co/widget.js"
  data-key="pk_live_YOUR_KEY_HERE"
  strategy="afterInteractive"
/>
```


---

### Attachments

Visitors can attach a file to any widget message: images, PDFs, or a short video. It shows up in Telegram in the same topic as the rest of the conversation, and replying with a file works the same way in the other direction.

**Limits**

| Type | Accepted formats | Max size |
| --- | --- | --- |
| Image | JPEG, PNG, WebP, GIF, HEIC/HEIF | 5 MB |
| PDF | application/pdf | 15 MB |
| Video | MP4, WebM, QuickTime | 20 MB |

HEIC/HEIF photos (the default on iPhone) are converted automatically so they open in any browser. The video limit matches Telegram's own file-fetch limit for bots, so it isn't something we can raise on our end.

> **Info:** **Plan requirement.** Attachments are available on the starter, pro, and custom plans. On the free plan, visitors can't attach files.


---

## Widget Customization

All visual settings are configured in the **Project Builder** in your dashboard. Changes are reflected in the live preview as you edit and applied to your site when you click **Publish changes**.

![Project Builder: customization panel with live preview](/assets/builder-page-2.png)

| Setting | Description | Limit |
| --- | --- | --- |
| **Brand color** | Primary color for the chat button, header, and sent messages. | Any hex color |
| **Logo** | Shown in the widget header. PNG, JPEG, or WebP. | 512 KB max |
| **Welcome message** | Displayed as the first message when the widget opens, before the visitor types anything. | 200 characters |
| **Greeting bubble** | Short text shown in a speech bubble above the chat button. Leave empty to hide it. | 100 characters |
| **Require email** | When on, visitors must enter their email before sending a message. When off, anonymous messaging is allowed. | Toggle |


---

## Email channel

The email channel puts your support inbox in the same Telegram group as your widget chats. Someone emails `support@yoursite.com`, it lands as a topic in Telegram, you reply in the topic, and they get a normal email back from your own address.

Nothing changes about how you work. You answer everything in Telegram, whether the person used the widget or sent an email.

> **Info:** **Pro plan.** The email channel is available on Pro and Custom plans. On the Free plan the setup page is visible but incoming emails are not delivered.

### How it works

You keep your existing mailbox. We do not replace it, and you do not move your email anywhere. You set up a forwarding rule that sends a copy of incoming mail to a private address we generate for your project. That address is the only piece of plumbing involved.

1. A customer emails your support address.
2. Your mail provider forwards a copy to your Bubblegram address.
3. We create a Telegram topic for that sender and post the message, with attachments.
4. You reply in the topic.
5. They receive an email reply. If your domain is verified it comes from your own address.
6. Their reply comes straight back to the same topic, no forwarding involved.

Setup is two steps. Step 1 gets email flowing into Telegram and is all most people need. Step 2 makes replies go out from your own domain instead of ours, and is optional.


---

### 1. Turn on the email channel

Open your project in the dashboard, go to the **Email** tab, and click **Enable email channel**. You get an address that looks like this:

```
875a8eff4f3940e4a2f5937e37565a13@mail.bubblegram.co
```

It is unique to the project and not guessable. Treat it as private: anyone who knows it can post into your Telegram group. It does not change if you disable and re-enable the channel later, so your forwarding rule keeps working.


---

### 2. Forward your support email

Set up forwarding to that address in whatever provider hosts your support inbox. The dashboard shows exact steps for your provider. Gmail is the one worth walking through here, because it takes two settings that look like one.

**Gmail and Google Workspace**

1. Open Gmail, click the gear icon, then **See all settings**.
2. Go to the **Forwarding and POP/IMAP** tab.
3. Click **Add a forwarding address**, paste your Bubblegram address, then click Next, Proceed, OK.
4. Gmail emails us a confirmation link. It shows up on the Email tab within a few seconds: open it and click Confirm.
5. Go back to the **Forwarding and POP/IMAP** tab in Gmail settings, select **Forward a copy of incoming mail to**, then choose the address above from the dropdown next to it.
6. Scroll to the bottom of the page and click **Save Changes**.

> **Warning:** **Don't skip the last step.** Step 4 only proves you own the address. Gmail does not forward anything until you select the option in step 5 and click Save Changes, and it discards the setting if you close the tab first. This is the single most common reason mail never arrives.

You never have to go hunting for Gmail's confirmation email. It is sent to an address only we can read, so we watch for it, pull out the link, and put it on the Email tab. It also goes to your Telegram group as a backup.

Google Workspace accounts follow the same six steps. If step 3 fails outright, forwarding is probably disabled for your organization, or restricted to an allowlist of domains that yours needs to be added to.

**Other providers**

| Provider | Where to set it up |
| --- | --- |
| **Outlook** | Settings > Mail > Forwarding > Enable forwarding. Check "Keep a copy of forwarded messages", then Save. |
| **Microsoft 365** | Same as Outlook. Your admin may need to allow external forwarding under Security & Compliance > Anti-spam > Outbound policy. |
| **Cloudflare Email Routing** | Dashboard > your domain > Email > Email Routing > Create address, with the destination set to your Bubblegram address. No confirmation step, so this is the quickest option. |
| **Anything else** | Look for a forwarding or redirect setting and point it at your Bubblegram address. |

> **Info:** **Google Workspace admins.** Turn forwarding on in Admin Console > Apps > Google Workspace > Gmail > End User Access > Automatic forwarding. Policy changes can take up to 24 hours to take effect.

**Confirming it works**

Nothing arrives on its own. Once forwarding is saved, email your support address from a personal account. Within a few seconds a topic appears in Telegram and the dashboard flips step 1 to done on its own, with no refresh needed. Forwarding only applies to mail that arrives after you saved, so anything already sitting in the inbox stays there.


---

### 3. Reply from your own domain

This step is optional. Skip it and everything still works, replies just go out from `noreply@mail.bubblegram.co` instead of your own address.

Enter your domain and the address you want replies to come from, for example `support@yoursite.com`. The from address has to be on the domain you are verifying. We generate three DNS records for you to add at your registrar:

| Record | Type | What it does |
| --- | --- | --- |
| **SPF** | `TXT` | Authorizes our servers to send mail as your domain. |
| **DKIM** | `CNAME` | Signs outgoing mail so receivers can verify it is really you. |
| **DMARC** | `TXT` | Tells receivers what to do with mail that fails the checks. |

The dashboard checks verification for you every few seconds and updates each record as it goes green. DNS changes usually take a few minutes, occasionally a few hours. You can close the tab and come back.

> **Info:** **One custom domain per account.** If you need more than one, get in touch and we'll sort it out.


---

### What it looks like in Telegram

Each sender gets their own topic, named with an envelope so you can tell it apart from widget chats at a glance:

```
📧 john@example.com
```

The first message in a new topic is preceded by a short info card:

```
From: john@example.com
Subject: Can't reset my password
```

Attachments come through as files or photos in the same topic (see [attachment limits](/docs/embed-widget#attachments)). Quoted reply chains and signatures are stripped, so you see what the person actually wrote rather than the whole thread. If a message fails sender authentication, we flag it at the top rather than hiding it, since that's a common sign of a spoofed address.

**Replying**

Just reply in the topic. A few details worth knowing:

- Several quick replies are bundled into one email rather than sent separately, so you can think out loud without filling someone's inbox.
- Replies thread properly in the recipient's client, under `Re: their subject`.
- When they reply, it comes directly back to us and into the same topic. It does not depend on your forwarding rule, and it works even if they answer from a different address than the one they wrote in with.
- If someone starts in the widget and continues by email, or the other way around, it stays in one topic with the full history.
- `/close` works the same as it does for widget chats. If they email again later, the topic reopens.


---

### What we filter out

A support inbox receives a lot that isn't a customer talking to you. Rather than forwarding all of it into Telegram, we drop the following silently:

| Dropped | Why |
| --- | --- |
| Out of office and auto-replies | Marked as automatic by the sending server. Left alone they can ping-pong with your replies forever. |
| Newsletters and mailing lists | Marked as bulk mail. Nobody is waiting on an answer. |
| `noreply@`, `no-reply@`, `mailer-daemon@`, `postmaster@` | Automated senders that got caught by your forwarding rule. |
| Our own outgoing replies | If you forward the same address we send from, replies would loop back to us. We tag and ignore them. |

So a forwarded newsletter is not a useful way to test your setup. Send an ordinary email from a personal account instead.

**Limits**

- Around 15 emails per minute per project, in short bursts of up to 20.
- 5 emails per sender per 5 minutes, which stops one loop or one angry refresher from flooding the group.
- Up to 20 new conversations at once, then roughly 6 per minute after that.
- Message bodies are capped at 50,000 characters.

These are far above normal support volume. If you are hitting them, something is looping and we should look at it together.

> **Warning:** **If your plan lapses.** Incoming emails stop being delivered and we post a notice in your Telegram group once a day. Your forwarding rule keeps running at your provider, so mail is not bouncing, it just isn't reaching Telegram until you're back on Pro.

**Turning it off**

**Disable email channel** on the Email tab stops delivery. Your address and domain verification are kept, so re-enabling later is one click and your existing forwarding rule still points to the right place. Remember to remove the forwarding rule at your provider too, otherwise your mail is being copied somewhere that ignores it.


---

## Multiple Sites

Each **project** in Bubblegram corresponds to one website and one Telegram group. Every project is fully isolated:

- Its own API key for the embed script
- Its own widget configuration (colors, messages, logo)
- Its own Telegram group with separate topic threads
- Its own message history and analytics

To add a second site, create a new project in the dashboard and run through the Telegram setup again for that site's group.

> **Info:** **Plan limits.** The Free plan includes 1 project. Pro and Custom plans support multiple projects.


---

## Bot commands

Type these commands as replies inside any conversation thread in your Telegram group:

| Command | What it does |
| --- | --- |
| `/close` | Mark the conversation as resolved. |
| `/draft` | Toggle draft mode for this topic. While on, anything you type here stays a draft and isn't sent to the visitor. Toggle it off (or use the button on the message) to send normally again. |
| `/status` | Show linked project info for this group. |
| `/unlink` | Remove the project link from this group. |


---

## Troubleshooting

### Widget not appearing on my site

Check that the `data-key` attribute in your script tag matches the API key shown in your project's Embed section. The key starts with `pk_live_`. Also confirm the script tag is in the `<body>`, not the `<head>`.

<TroubleItem title="Messages aren't arriving in Telegram">
	Your project may not be linked. Open the project in the dashboard. If the status shows **Not linked**, click **Link Telegram** and complete the flow. The bot must be in the group and have admin rights.
</TroubleItem>

### Origin mismatch error

The domain saved in your project settings must exactly match the domain your site runs on. Enter it without `https://` and without a trailing slash. For example: `example.com`, not `https://example.com/`. Subdomains count as different domains.

<TroubleItem title="Bot joined the group but messages aren't creating topics">
	The bot needs admin rights. Open your Telegram group, go to **Administrators**, find the bot, and ensure it has permission to manage topics, post messages, and delete messages. Without these, topic creation fails silently.
</TroubleItem>

### I set up forwarding in Gmail but no email arrives

Almost always the last step. Go back to Gmail's **Forwarding and POP/IMAP** tab and check that **Forward a copy of incoming mail to** is actually selected, then scroll down and click **Save Changes**. Verifying the address does not switch forwarding on by itself, and Gmail throws the setting away if you leave the page without saving. After that, send yourself a test email from a different account. Only mail arriving after you saved gets forwarded.

<TroubleItem title={'Gmail says "An error occurred with the secure Google verification"'}>
	This is Gmail failing before it sends anything, not a problem with your Bubblegram address. The usual cause is being signed into several Google accounts in the same browser: open an incognito window, sign into just the one account, and try again. On Google Workspace, forwarding may be disabled for your organization, in which case your admin needs to allow it under Admin Console > Apps > Google Workspace > Gmail > End User Access. Ad blockers and privacy extensions can also break the verification popup. If you've tried several times in a row, wait an hour before retrying.
</TroubleItem>

<TroubleItem title="The Gmail confirmation code isn't showing in the dashboard">
	Click **Re-send email** next to the pending address in Gmail and watch the Email tab. The code appears within a few seconds and is also posted to your Telegram group. If it still doesn't show up, the confirmation never reached us, which usually means the address was pasted with a typo. Compare it against the address on the Email tab character for character, or remove it in Gmail and add it again.
</TroubleItem>

### My test email never showed up in Telegram

Check what you sent. Newsletters, notifications and anything from a `noreply@` address are filtered out on purpose, so they make a poor test. Send an ordinary message from a personal mailbox instead. Also confirm your plan is still Pro: on the Free plan the email channel is set up but incoming mail is not delivered, and we post a notice in your Telegram group once a day when that happens.

### Replies are coming from noreply@mail.bubblegram.co

That's the default sender until your own domain is verified. Finish step 3 on the Email tab by adding the SPF, DKIM and DMARC records at your registrar. Until all three verify, replies still send and still thread correctly, they just come from our address rather than yours.

### Link token expired

Link tokens are valid for 10 minutes. If you waited too long between generating the token and completing the setup, go back to your project in the dashboard, click **Link Telegram** again, and use the newly generated token.

