Customization

The Intercom component has fixed position and styling. This guide shows what can be customized and workarounds for common needs.


Fixed Properties (Cannot Customize)

Position:

  • Bottom-right corner

  • Mobile: 112px from bottom, 16px from right

  • Desktop: 40px from bottom, 40px from right

Styling:

  • Dark theme only

  • 50x50px trigger button

  • 400px × 530px max popover size

  • HelpCircle/CircleX icons

Behavior:

  • Portal rendering

  • Requires authentication


What You Can Customize

1. When the Component Renders

Conditional Display:

{showSupport && <Intercom username="support" />}

Route-Based:

import { useLocation } from "react-router-dom";

function App() {
  const location = useLocation();

  const username = location.pathname.startsWith("/billing")
    ? "billing_support"
    : "general_support";

  return <Intercom username={username} />;
}

User-Based:

import { useDeva } from "@bitplanet/deva-sdk";

function App() {
  const { user } = useDeva();

  const username = user?.role === "premium"
    ? "premium_support"
    : "standard_support";

  return <Intercom username={username} />;
}

2. Which Agent to Chat With

Change the username prop to switch between different AI agents:

<Intercom username="support" />
<Intercom username="sales" />
<Intercom username="billing_support" />

3. Load Behavior

<Intercom username="support" fetchOnMount={true} />

Common Scenarios

Hide on Specific Pages

import { useLocation } from "react-router-dom";

function App() {
  const location = useLocation();
  const hideOnPages = ["/login", "/signup"];
  const showIntercom = !hideOnPages.includes(location.pathname);

  return <>{showIntercom && <Intercom username="support" />}</>;
}

Multiple Chat Options

Don't render multiple Intercom instances. Use conditional rendering:

function App() {
  const [activeChat, setActiveChat] = useState<string | null>(null);

  return (
    <>
      <div className="fixed top-4 right-4 flex gap-2">
        <button onClick={() => setActiveChat("support")}>
          Support
        </button>
        <button onClick={() => setActiveChat("sales")}>
          Sales
        </button>
      </div>

      {activeChat && <Intercom username={activeChat} />}
    </>
  );
}

Layout Considerations

Avoid Position Conflicts

The Intercom button occupies bottom-right space. Ensure your fixed elements don't overlap:

// Bad: Button overlaps Intercom
<button className="fixed bottom-4 right-4">
  My Button
</button>

// Good: Button positioned elsewhere
<button className="fixed bottom-4 left-4">
  My Button
</button>

Reserve Space for Fixed Elements

.my-fixed-element {
  bottom: 150px; /* Mobile: Above Intercom at 112px */
}

@media (min-width: 768px) {
  .my-fixed-element {
    bottom: 80px; /* Desktop: Above Intercom at 40px */
  }
}

Z-Index Stacking

Default stacking order:

  1. Page content (z-index: auto)

  2. Intercom trigger (z-index: 10)

  3. Intercom popover (z-index: 50)

  4. Your modals (z-index: 100+)

Ensure your modals use z-index: 100+ to appear above Intercom.


Best Practices

Rendering:

  • Render at root level, not inside scrollable containers

  • Use single instance per page

  • Unmount when not needed for performance

User Experience:

  • Don't show immediately on page load (delay 3-5 seconds)

  • Use descriptive agent usernames (billing_support vs support)

  • Hide on auth pages (/login, /signup)

  • Show based on user permissions

Performance:

  • Default fetchOnMount={false} is optimal (loads on open)

  • Only use fetchOnMount={true} if users need instant access


Limitations Summary

Feature
Customizable?

Button position

❌ Fixed bottom-right

Button styling

❌ Fixed icon/size/colors

Popover dimensions

❌ Fixed max-width/height

Theme

❌ Dark theme only

Z-index values

❌ Fixed (trigger: 10, popover: 50)

When component renders

✅ Conditional rendering

Which agent to chat with

username prop

Message load timing

fetchOnMount prop

Layout around component

✅ Your CSS/positioning


Last updated