Add live chat to Gatsby

In Gatsby, add the snippet from gatsby-ssr.js, which writes it into the head of every page at build time. The chat loads once and stays through client-side navigation, so an open conversation stays open.

Tested with Gatsby 5.16 on the default starter on 2 November 2026.

Before you start

HTML
<script>window.$pidge = []; window.PIDGE_WEBSITE_ID = "YOUR-WEBSITE-ID";</script>
<script src="https://app.pidge.chat/client/l.js" async></script>

Your own copy is in the Pidge inbox under Websites, in Code for your website, with your website ID already filled in. If you've set up a chat domain, it loads from there instead.

In Gatsby you don't paste those two lines as they are. You add them from gatsby-ssr.js, as below.

Add the snippet in gatsby-ssr.js

gatsby-ssr.js sits in your site's root folder. The default starter already has one that sets lang. Create the file if your site doesn't have it. Add the two scripts with setHeadComponents:

const React = require("react")

exports.onRenderBody = ({ setHtmlAttributes, setHeadComponents }) => {
  setHtmlAttributes({ lang: `en` })
  setHeadComponents([
    <script
      key="pidge-setup"
      dangerouslySetInnerHTML={{
        __html: `window.$pidge = window.$pidge || []; window.PIDGE_WEBSITE_ID = "YOUR-WEBSITE-ID";`,
      }}
    />,
    <script key="pidge-loader" src="https://app.pidge.chat/client/l.js" async />,
  ])
}

The scripts are written into the head of every page Gatsby builds. Run gatsby build and gatsby serve to check, or gatsby develop, which picks it up too.

A <Link> click doesn't reload the page. Gatsby swaps the content inside its own #___gatsby element, and the chat lives next to it in <body>, so it stays put. We clicked between pages with the chat open and it was the same chat, mid-conversation, with the loader fetched once.

The Script component instead

Gatsby's Script component works too, if you'd rather keep this in your layout. Add it to the layout component every page uses, often src/components/layout.js:

import { Script } from "gatsby"

// inside the layout's JSX, after the page content:
<Script id="pidge-setup">
  {`window.$pidge = window.$pidge || []; window.PIDGE_WEBSITE_ID = "YOUR-WEBSITE-ID";`}
</Script>
<Script src="https://app.pidge.chat/client/l.js" />

It loads the chat once and keeps it through page changes, like gatsby-ssr.js. Two differences: it waits until the page has hydrated, so the bubble shows a moment later, and it only covers pages that use that layout. An inline Script needs an id.

Open the chat from your own components

import * as React from "react"

const ChatButton = () => (
  <button
    type="button"
    onClick={() => {
      window.$pidge = window.$pidge || []
      window.$pidge.push(["do", "chat:open"])
    }}
  >
    Chat with us
  </button>
)

export default ChatButton

Touch window only in event handlers or useEffect. Gatsby renders every page in Node during gatsby build, where there's no window. If the script hasn't loaded yet, the command waits in the array and runs when it has. The widget commands list everything else you can push.

List your domains in Pidge

The chat only connects on domains you've listed for the website. In the inbox, open Websites and put each domain on its own line in Domains. Subdomains are included, so example.com also covers www.example.com.

If people visit your host's own address too, like yoursite.netlify.app, list that full address as well.

To try the chat locally, add localhost to the list too. Pidge matches the host name, so gatsby develop on port 8000 and gatsby serve on port 9000 both work. 127.0.0.1 isn't accepted, so open your site at localhost.

Check that it works

  1. Open your site in a private window, so you're seeing what a visitor sees.
  2. The chat bubble should be in the bottom corner. Send yourself a message and answer it from the inbox.
  3. In the inbox, the website's Not installed yet label goes away after the first visit from a listed domain.

If the bubble shows but the chat won't connect, the domain you're on isn't in the website's list in Pidge. If there's no bubble at all, the snippet isn't on the page, or the platform is still serving an older copy of it.

Also click through two or three pages with the chat open and check it stays open.

Gatsby's own guides: gatsbyjs.com/docs/reference/config-files/gatsby-ssr/ and gatsbyjs.com/docs/reference/built-in-components/gatsby-script/

Other platforms

Stuck, or did a step look different on your screen? Tell us in the chat on this page.

Get your snippet

Start free

The free plan covers one website and two people replying. No card needed.