Install live chat on Vue
Mount the message.com widget from the onMounted lifecycle hook in Vue 3. Works on Vite, Vue CLI, and any Vue shell that runs in a browser. Nuxt gets a dedicated client-only plugin.
Vue 3 with Vite
Drop the snippet into your root App.vue inside an onMounted hook. The guard by element ID prevents double-mounts during Hot Module Reload.
<!-- src/App.vue -->
<script setup lang="ts">
import { onMounted } from "vue";
const WORKSPACE_ID = "YOUR_WORKSPACE_ID";
onMounted(() => {
if (document.getElementById("message-widget-script")) return;
const s = document.createElement("script");
s.id = "message-widget-script";
s.async = true;
s.src = "https://app.message.com/widget.js";
s.dataset.workspace = WORKSPACE_ID;
document.head.appendChild(s);
});
</script>
<template>
<RouterView />
</template>Nuxt 3
Use a client-only plugin so the widget never tries to evaluate during SSR. The .client.ts suffix tells Nuxt to skip this file on the server.
// plugins/message-widget.client.ts
export default defineNuxtPlugin(() => {
if (document.getElementById("message-widget-script")) return;
const s = document.createElement("script");
s.id = "message-widget-script";
s.async = true;
s.src = "https://app.message.com/widget.js";
s.dataset.workspace = "YOUR_WORKSPACE_ID";
document.head.appendChild(s);
});Drop the file into plugins/. Nuxt auto-registers it. No nuxt.config.ts change needed.
Identify the user on sign-in
After your auth flow returns a session, identify the visitor. Compute the HMAC userHash server-side. See Identify logged-in users.
<!-- src/components/IdentifyOnSignIn.vue -->
<script setup lang="ts">
import { onMounted } from "vue";
const props = defineProps<{
user: { email: string; name: string; id: string; userHash: string };
}>();
declare global {
interface Window {
Message?: { identify: (p: Record<string, unknown>) => void };
MessageOnReady?: () => void;
}
}
onMounted(() => {
const identify = () => window.Message?.identify({
email: props.user.email,
name: props.user.name,
userId: props.user.id,
userHash: props.user.userHash,
});
if (window.Message) identify();
else window.MessageOnReady = identify;
});
</script>
<template></template>Push route changes
Watch $route (Options API) or use watch on useRoute() (Composition API). On each change, call window.Message?.update({ pageUrl: window.location.href }) so agents see the visitor's current page.
Verify the install
- Run
npm run dev. - Open the app in a private window.
- The launcher appears in the bottom-right within two seconds.
- Open the browser console. Confirm the
[message]startup log. - Send a test message. The conversation lands in
app.message.com.
Common pitfalls
- SSR crash. If you put the snippet outside
onMountedin a Nuxt app, the server-render step throws ondocument. Use.client.tsplugins or guard withif (process.client). - HMR double-mount. Vite's HMR will remount components. The element-ID dedupe prevents two scripts loading.
- Vue 2 projects. The pattern is the same with the
mountedlifecycle. Composition API is not required.