October 14, 2026

How to Add Live Chat to a Vue or Nuxt Site

Add live chat to Vue with the Nuxt config script tag and site key

To add live chat to Vue or Nuxt, you do not need a package: the Talkmio widget is a single script tag. In a Nuxt 3 project you add it to the head in nuxt.config.ts; in a Vue app built with Vite you paste it into index.html before the closing body tag. Signed-in users can be identified with one small object set before the script loads. This guide shows both setups with working code, explains how to test them, and covers the issues that single-page and server-rendered apps usually meet: hydration, route changes, environment variables and content security policies.

The steps use Talkmio as the example, but the same approach works for most widgets that load from a script URL.

What You Need Before You Start

  • A Vue 3 or Nuxt 3 project that you can build and deploy.
  • A Talkmio account and a site key. Sign in at app.talkmio.com, open Websites, add your website and copy the 12-character key. A free account needs no card.
  • A staging environment if you have one. Create a second website in Talkmio for it, with its own site key.

The widget URL has the form https://app.talkmio.com/w/YOUR_SITE_KEY.js. Replace the placeholder with your own key everywhere in the examples below.

Add Live Chat to Nuxt 3

In Nuxt, the cleanest place for a third-party script is the head configuration. Open nuxt.config.ts and add the script under app.head:

export default defineNuxtConfig({
  app: {
    head: {
      script: [
        { src: 'https://app.talkmio.com/w/YOUR_SITE_KEY.js', async: true }
      ]
    }
  }
})

That is all. Nuxt renders the tag on every page, the browser loads it asynchronously, and the chat bubble appears. Because the tag is part of the head configuration, there is no hydration mismatch, and it works with server-side rendering, static generation and client-only mode. The Nuxt documentation on useHead describes the options in more detail.

Keep the key out of the code

If you want different keys for staging and production, read the key from an environment variable through the runtime configuration instead of hard-coding it. Expose it as a public runtime value, then build the script URL from it in app.vue with useHead:

const config = useRuntimeConfig()
useHead({
  script: [{ src: `https://app.talkmio.com/w/${config.public.talkmioKey}.js`, async: true }]
})

Set NUXT_PUBLIC_TALKMIO_KEY in each environment. The site key appears in the page source of every visitor anyway, so it is configuration, not a secret, but keeping it per environment prevents test conversations from mixing with real ones.

Add Live Chat to Vue (Vite)

For a plain Vue 3 single-page app built with Vite, open index.html at the project root and paste the snippet before the closing body tag:

<script src="https://app.talkmio.com/w/YOUR_SITE_KEY.js" async></script>
</body>

The file is served once and the app navigates inside it, so the widget stays loaded while visitors move between routes. If you need different keys per environment, Vite can replace values in index.html at build time through environment variables; check the Vue guide and the Vite documentation for the syntax that matches your version.

Identify Signed-In Users

Talkmio lets you pass the name and e-mail of a signed-in user, so your team sees who is writing. Set a global object before the widget script loads:

window.__TALKMIO_USER__ = { name: 'Anna Example', email: '[email protected]' }

In Nuxt, do this in a client-only plugin, for example plugins/talkmio.client.ts, which sets the object from your auth store and then adds the script tag. In a Vue app, set it in a small inline script or module that runs before the widget script and after the user is known.

Single-page apps raise one question: the user may log in after the widget has loaded. Test that case. If the name does not show up in the Talkmio Inbox after a login without a reload, either load the widget after authentication is known, or reload the page after login. Do not assume; open a test conversation and check the contact details in the Inbox.

Identification is context, not proof. Verify identity before discussing sensitive information, as explained in our article on live chat identity verification, and mention the practice in your privacy policy.

Vue and Nuxt Compared

Question Nuxt 3 Vue with Vite
Where the script goes app.head in nuxt.config.ts, or useHead index.html before the closing body tag
Package needed No No
Server-side rendering Supported, tag rendered in the head Not applicable
Per-environment key Runtime config and environment variable Build-time variable
Identify users Client plugin sets the user object Inline script or module before the widget
Route changes Widget stays loaded Widget stays loaded

Test Before You Announce It

  1. Build and serve the app, then open it in a private window and confirm the bubble appears on the home page and a deep route.
  2. Navigate between routes and check that the bubble stays and does not duplicate.
  3. Ask Mio two or three questions your customers ask, and check that each answer comes from your own pages.
  4. Ask for a person and confirm that the conversation appears in the Inbox with a “needs human” badge.
  5. Log in as a test user and check the contact details in the Inbox.
  6. Repeat on a phone and check that the bubble does not cover important buttons.

“Try Mio” in the app shows the answer, the knowledge pieces used and how long it took, which helps before you go live.

Give the Assistant Content to Learn From

A single-page app has a particular risk: if content is rendered only in the browser, a crawler may see an empty page. Talkmio’s assistant, Mio, reads your website, FAQ and uploaded documents. In the Mio AI knowledge base you can add your website, which Mio reads page by page on the same domain while respecting robots.txt, but also single pages, question and answer pairs, free text and files such as PDF, DOCX, TXT, MD, CSV and HTML up to 15 MB.

  • Use server-side rendering or prerendering for pages that hold policies, prices and documentation. In Nuxt this is the default behaviour.
  • Add Q&A pairs and files for content that lives behind logins or in a client-rendered interface.
  • Write business instructions, such as “never promise release dates; hand billing questions to the team”.
  • Re-read sources after a release so answers match the current version.

Our guide to training an AI chatbot on your website content goes deeper on structure.

Single-Page Apps, Routes and Consent

In a single-page app the browser loads the page once and the router changes the content. That suits a chat widget, which only needs to load once, but a few details deserve attention.

  • Route-specific behaviour. You may not want the bubble on every screen, for example inside a full-screen editor, a checkout step or a login page. Decide which routes should show it. The simplest approach is to load the widget everywhere and hide it where needed with the widget’s own settings and your page layout, then test on mobile.
  • Cookie consent. If you gate third-party scripts behind a consent banner, add the Talkmio script only after consent is given. In Nuxt, a client-only plugin can append the script after your consent state changes. Our article on chat widget cookies and consent explains what to consider.
  • Layouts and nested apps. In Nuxt, if you use several layouts, the head configuration applies to all of them. In micro-frontend setups, load the widget in the shell, not in each embedded app, to avoid duplicates.
  • Preview and test builds. Preview deployments get their own URLs. Use the staging site key there, so preview traffic does not appear as real conversations.

Finally, remember that a chat widget is part of your product’s interface. Check keyboard access and colour contrast of the bubble against your own design, and set the widget colour and position in the Talkmio settings so it fits. Changes there apply within five minutes without a new deployment.

Troubleshooting

The bubble does not appear

Check that the key is correct, that the build contains the script tag (view the page source or inspect the head), and that no ad blocker, browser privacy setting or content security policy blocks app.talkmio.com. If you use a CSP, allow scripts from that host and the widget’s connections to it.

It appears twice

You probably added the script in both nuxt.config.ts and a plugin, or in index.html and in a component. Keep one.

It works locally but not in production

The environment variable is probably missing at build or run time. In Nuxt, public runtime values are read from NUXT_PUBLIC_ variables on the server that runs the app; in Vite, values are fixed at build time.

Hydration warnings in Nuxt

Do not inject the script by manipulating the document in a component that renders on the server. Use the head configuration or a client-only plugin.

The page feels slower

The widget loads asynchronously and should not block rendering. Compare with and without it, and read our guide to chat widget page speed.

What Happens After Installation

Visitors can write at any time. Mio answers from your content in their language and hands the conversation to your team when it cannot answer, when the visitor asks for a person, complains or asks about a specific order. Operators reply from the Inbox, use quick replies with a slash, add internal notes and turn any conversation into a numbered ticket. The free plan covers one operator, one website and 50 AI answers a month; see pricing for paid plans. If you use React instead, our guide to adding live chat to a Next.js or React site covers it.

Frequently Asked Questions

How do I add live chat to a Nuxt 3 site?

Open nuxt.config.ts and add the Talkmio script under app.head.script with your site key, using the URL https://app.talkmio.com/w/YOUR_SITE_KEY.js and the async option set to true. Nuxt renders the tag on every page, so the chat bubble appears without any package or plugin.

How do I add live chat to a Vue 3 app built with Vite?

Paste the one-line script tag before the closing body tag in index.html, using your own site key. The app is served from that file and navigates inside it, so the widget stays loaded across routes. For different keys per environment, replace the value at build time with an environment variable.

Can I identify logged-in users in a single-page app?

Yes. Set window.__TALKMIO_USER__ to an object with name and e-mail before the widget script loads. In Nuxt, use a client-only plugin. Test the case where the user logs in after the page has loaded, and reload the page after login if the name does not appear in the Inbox.

Why does the chat bubble not show in production?

Common causes are a missing environment variable for the site key, a content security policy that blocks app.talkmio.com, an ad blocker, or a duplicate or missing script tag after the build. View the page source or inspect the head in the browser to see whether the script tag is present.

Does the widget slow down my Vue or Nuxt app?

The script loads asynchronously, so it should not block rendering. If you notice a change, compare the page with and without the widget and look at the loading order. Keep the script in the head or before the closing body tag, and avoid loading it more than once.

Do I need a separate site key for staging?

It is a good idea. Create a second website in Talkmio with its own site key and set it in the staging environment, so test conversations do not mix with real customers or your reports. Keep production and staging keys in environment variables.

The Bottom Line

To add live chat to Vue or Nuxt, add one script tag: through app.head in Nuxt, or in index.html in Vue with Vite. Keep the site key per environment, identify signed-in users with a small object, allow the widget in your content security policy and test on a built version rather than only in development. Then give Mio clear, server-rendered pages to learn from. When you are ready, create a free Talkmio account, copy your site key and have the chat running in your app today.


Try Talkmio on your site

Free plan, no card required.

Start free