Before you start
- A Vue 3 app made with
npm create vueor Vite, or a Nuxt app. - Your snippet from Websites in the Pidge inbox.
<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.
Vue: index.html
- Open
index.htmlin the project root, next topackage.json. - Paste the two lines just before
</body>, after the line that loads your app. Change the first line towindow.$pidge || [], so commands your components push early are kept.
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script>window.$pidge = window.$pidge || []; window.PIDGE_WEBSITE_ID = "YOUR-WEBSITE-ID";</script>
<script src="https://app.pidge.chat/client/l.js" async></script>
</body>
- Build and deploy as usual.
The chat adds itself next to #app, not inside it, so Vue never renders over it.
You don't need a plugin, a component or an onMounted for it.
Nuxt: nuxt.config.ts
Add both scripts under app.head:
export default defineNuxtConfig({
app: {
head: {
script: [
{ innerHTML: 'window.$pidge = window.$pidge || []; window.PIDGE_WEBSITE_ID = "YOUR-WEBSITE-ID";' },
{ src: "https://app.pidge.chat/client/l.js", async: true, tagPosition: "bodyClose" },
],
},
},
})
Keep tagPosition: "bodyClose" on the second entry. Nuxt sorts the tags in
<head> and writes async scripts above inline ones, so with
both in the head the loader comes first. In our test, the chat didn't start that way.
bodyClose puts the loader at the end of the page, after the line that sets
your website ID.
Nuxt writes both tags into the HTML it renders on the server, so they're there on the first load of any page, not only after the app starts in the browser.
Page changes
You don't need to do anything. Pidge notices when the address changes, so
<RouterLink> and <NuxtLink> clicks and the back
button keep the same chat, open or closed, and the inbox shows which page the visitor is on.
There's no route hook to add.
Open the chat from your own components
Vue templates can't see window, so
@click="window.$pidge.push(…)" fails with
Cannot read properties of undefined. Call a function from
<script setup> instead:
<script setup lang="ts">
declare global {
interface Window {
$pidge?: { push: (...commands: unknown[]) => void } | unknown[];
}
}
function openChat() {
window.$pidge = window.$pidge || [];
window.$pidge.push(["do", "chat:open"]);
}
</script>
<template>
<button type="button" @click="openChat">Chat with us</button>
</template>
This works the same in Vue and Nuxt.
To pass a logged-in customer's name, push it in onMounted. In Nuxt,
<script setup> also runs on the server, where there's no
window, so touching it at the top level breaks the page with a 500 error.
onMounted only runs in the browser:
onMounted(() => {
window.$pidge = window.$pidge || [];
window.$pidge.push(["set", "user:nickname", [user.name]]);
});
If the script hasn't loaded yet, the command waits in the array and runs when it has.
For emails your team can trust, sign them on the server: see
signed visitor emails. Push
["do", "session:reset"] when someone logs out. 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 your host gives the app a second address, like yourapp.netlify.app or
yourapp.vercel.app, list that full address too if people visit it there.
To try the chat while you develop, add localhost to the list too. Pidge
matches the host name, so any port works. 127.0.0.1 isn't accepted, so open
your dev server at localhost.
Check that it works
- Open your site in a private window, so you're seeing what a visitor sees.
- The chat bubble should be in the bottom corner. Send yourself a message and answer it from the inbox.
- Click through two or three pages and check the chat is still there.
- 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
your host is still serving an older build. In Nuxt, view the page source and check that
l.js is near the end of the body, after the line with your website ID.
Vue's own guide: vuejs.org/guide/essentials/template-syntax.html. Nuxt's: nuxt.com/docs/4.x/getting-started/seo-meta
Other platforms
- WordPress
- Shopify
- Squarespace
- Wix
- Webflow
- Ghost
- Framer
- Next.js
- Astro
- React
- Gatsby
- Hugo
- Jekyll
- Laravel
- Django
- Carrd
- Plain HTML
Stuck, or did a step look different on your screen? Tell us in the chat on this page.