What “Customization” Actually Means When You Own the Stack
Most customer support platform decisions end the same way: choose a SaaS product, absorb its limitations, and pay per seat indefinitely. Chatwoot is open-source, and self-hosting it changes the terms of that deal entirely. The ceiling on what you can modify shifts from “whatever toggles the vendor exposed in the settings page” to “whatever your team has the capacity to build.”
This guide covers the real boundaries of that shift - widget configuration, white-labeling, both API layers, webhooks, dashboard apps, and the specific advantages that only appear on a self-hosted installation. Every technical detail below maps to Chatwoot’s official developer documentation at developers.chatwoot.com. Check anything load-bearing for your project against the docs directly before shipping it.
Configuring the Chat Widget
The website live-chat widget is the most visible surface in a Chatwoot deployment, and it has more configurable surface area than it first appears. The standard embed is a Chatwoot SDK script combined with a chatwootSettings object you define before the script loads. That settings object controls locale, position, bubble type, launcher title, and dark mode behavior.
window.chatwootSettings = {
locale: "en", // any locale Chatwoot ships, e.g. "he", "ar", "fr"
position: "right", // "left" or "right"
type: "expanded_bubble", // "standard" or "expanded_bubble"
launcherTitle: "Chat with us",
darkMode: "auto", // "light" or "auto"
};
The widget’s color scheme and avatar pull directly from inbox settings in the dashboard, so non-developers can update those without touching any code. What that clean separation buys you in practice: designers and support managers handle appearance; engineers handle behavior.
Beyond static configuration, the SDK exposes runtime methods that make the widget context-aware - which is where generic chat bubble territory ends and actual product integration begins.
// Attach the logged-in user so conversations link to the right contact
window.$chatwoot.setUser("USER_IDENTIFIER", {
name: "Jane Doe",
email: "jane@example.com",
});
// Pass structured context visible to the agent during the conversation
window.$chatwoot.setCustomAttributes({
plan: "business",
signup_date: "2026-01-15",
});
// Route or segment with a conversation label
window.$chatwoot.setLabel("vip");
// Switch locale at runtime when the user changes site language
window.$chatwoot.setLocale("he");
The setCustomAttributes call is the most underused of these. Whatever key-value pairs you pass appear next to the conversation on the agent side - plan tier, account age, cart value, anything structured - without the agent needing to ask. On a closed SaaS platform, that kind of contextual surfacing depends entirely on what the vendor chose to support. On a self-hosted install, you define the attributes.
On self-hosted specifically, widget string patches and launcher icon replacements are also available by modifying source directly. That’s not an option on Chatwoot Cloud.
White-Labeling and Removing Chatwoot Branding
Self-hosted installations expose three environment variables that strip Chatwoot’s own branding from the interface: INSTALLATION_NAME, BRAND_NAME, and BRAND_URL. Set those in your deployment configuration and the product presents under your name, not Chatwoot’s.
This is self-hosted only. No equivalent exists on the cloud version.
The Two API Layers
Chatwoot runs two distinct APIs, and understanding which one you need before you start building saves significant rework time.
The Application API operates within a single account. It handles the objects you’d expect: conversations, contacts, messages, labels, inboxes. If you’re building an integration that creates conversations from an external form, syncs contact data from your CRM, or reads message history to feed into a reporting tool, this is the layer you’re working with. Authentication is per-account.
The Platform API sits above that. It manages accounts, users, and bots across an entire Chatwoot installation - not just one account. This is the API you’d use to build multi-tenant tooling, provision accounts programmatically, or manage bot configurations at the infrastructure level. It requires a platform access token rather than a user-level token.
Most product integrations need only the Application API. The Platform API becomes relevant when you’re building tooling for the installation itself - automation around provisioning, admin workflows that span multiple accounts, or agent management at scale.
Self-hosted installations remove API rate limits. On Chatwoot Cloud, rate limits apply. If you’re running high-volume automation - bulk contact syncs, webhook-driven conversation creation, reporting pipelines - self-hosting eliminates that constraint entirely.
Webhooks: Pushing Events Into External Systems
Chatwoot’s webhook system covers the event types you’d need to wire it into surrounding infrastructure. Key events include conversation_created, message_created, conversation_status_changed, and contact_created. Configure a webhook endpoint in the inbox settings, and Chatwoot will POST a payload to that URL each time the event fires.
The practical application here is direct. A conversation_created event hitting an n8n workflow can trigger a CRM record update, a Slack notification, or a ticket creation in a project management tool. A message_created event can feed a custom sentiment analysis pipeline. The events are the integration surface; what you do with them is up to your stack.
On self-hosted, you can also build custom channels - meaning Chatwoot can receive and send messages through communication surfaces that aren’t natively supported. This goes beyond webhooks into modifying how Chatwoot understands what a “channel” is. The official documentation covers the custom channel API under the developer guides section at developers.chatwoot.com.
Dashboard Apps: Embedding Your Own Tools in the Agent Inbox
Dashboard apps are the least-discussed customization surface in Chatwoot, and arguably the most useful for teams with existing internal tooling.
The feature works through an iframe. You configure a URL pointing to any web application you control, and Chatwoot embeds it inside the agent inbox interface. When an agent opens a conversation, Chatwoot passes conversation context - contact details, conversation ID, labels - into the embedded app via a postMessage event.
What that enables: an agent handling a conversation can simultaneously view the customer’s order history from your e-commerce backend, see their subscription status from your billing system, or pull up a risk score from an internal tool - all without leaving the inbox. The embedded app is fully yours; Chatwoot just provides the frame and the context injection.
This isn’t available through a vendor toggle. It’s available because self-hosted Chatwoot gives you direct access to configure what gets embedded and what context gets passed.
What Self-Hosting Actually Unlocks Over Cloud
The full list of self-hosted-only capabilities, stated plainly:
- Direct database access - query or modify data at the PostgreSQL level for reporting, migration, or custom tooling
- Source code modification and forking - patch behavior that isn’t exposed through configuration
- No API rate limits - relevant for high-volume automation pipelines
- Custom channels - extend Chatwoot to message surfaces it doesn’t natively support
- Full rebranding - via
INSTALLATION_NAME,BRAND_NAME,BRAND_URL - Widget string and icon patching - modify launcher text and icons at the source level
The tradeoff is infrastructure ownership. You’re running the Rails app, the PostgreSQL database, the Redis instance, and the Sidekiq workers. Updates, backups, and uptime are your responsibility. That’s a real cost. Whether it’s worth it depends on how close to the customization ceiling your use case sits.
For teams whose requirements fit within what the vendor chose to expose, cloud is fine. For teams building multi-channel support infrastructure where the widget, the API, the branding, and the data layer all need to behave according to specifications the vendor never anticipated - self-hosted is the only path where those requirements are even addressable.
The setCustomAttributes method accepts any key-value pairs you define, and there’s no documented limit on the number of attributes per conversation.