← All posts
Guides6 min read

[GUIDES] · Aug 4, 2026 · 09:40

Add live chat to an Angular app via index.html

One snippet in src/index.html loads the widget once for the whole SPA, every route, no component, no Zone.js churn. Read the widget ID from environment.ts to keep staging out of your production inbox.

Tm

The muro team

muro.chat

#angular#live chat#typescript#spa#ai support#widget install

An Angular app is a single index.html with one <app-root> that the router swaps views into. That architecture makes chat easy: you do not want a widget that mounts and unmounts with a component and re-initializes on every navigation. You want it loaded once, at the shell level, living beside your app rather than inside it. That is exactly what src/index.html is for.

index.html, not a component

Because Angular is a single-page app, the browser loads index.html once and never reloads it during navigation, the router just re-renders <app-root>. Put the snippet in index.html and the widget initializes a single time and persists across every route, with no component lifecycle to fight and no re-init on navigation. It runs entirely outside Angular's zone, so it never triggers change detection or affects your app's performance.

Step 1: grab your widget ID

Sign up for muro (14-day free trial, no card), create a site, and copy the widget ID. Set the accent color, launcher position, agent name and avatar so the bubble looks native to your app.

Step 2: paste the snippet into src/index.html

Open src/index.html and paste the snippet right before </head>:

html<script>
  (function(w,d,s,o){
    w.MuroChat=o;w[o]=w[o]||function(){(w[o].q=w[o].q||[]).push(arguments)};
    var j=d.createElement(s);j.async=1;j.src='https://muro.chat/widget.js';
    d.getElementsByTagName('head')[0].appendChild(j);
  })(window,document,'script','muro');
  muro('init',{widgetId:'YOUR_WIDGET_ID'});
</script>

Replace YOUR_WIDGET_ID, run ng serve, and the bubble is there on every route. The script loads async and is not bundled by the Angular CLI, so it does not touch your build size or your vendor chunks.

Per-environment IDs with environment.ts

Hardcoding one widget ID means staging chats land in your production inbox. The Angular-shaped fix is environment.ts. Keep the loader in index.html but drop its muro('init', ...) line, put the ID in your environment files, and call init from your root component instead:

ts// src/environments/environment.ts
export const environment = { production: false, muroWidgetId: '' };

// src/environments/environment.prod.ts
export const environment = { production: true, muroWidgetId: 'YOUR_WIDGET_ID' };
ts// app.component.ts
import { environment } from '../environments/environment';

ngOnInit() {
  const muro = (window as any).muro;
  if (environment.muroWidgetId && muro) {
    muro('init', { widgetId: environment.muroWidgetId });
  }
}

Production sets the ID and the widget boots; staging leaves it empty and the widget simply never initializes, so no test chats reach your real inbox.

Point the AI at your docs

Paste your docs or help center URL into muro and the AI answers from your own content, in the visitor's language, and hands off to you when it is not sure. For a dashboard-style Angular app, that turns the 'how do I do X' questions into instant in-widget answers instead of support tickets.

Offline? It becomes email

Handed-off conversations are forwarded to your inbox; you reply from your mail client and it lands back in the chat. Saved replies and automation rules keep the whole thing to minutes a day, and a full REST API plus webhooks let you wire conversations into your own systems, the API docs cover it.

Ship it

Paste the loader into src/index.html, move the init call into your root component if you need per-environment IDs, and point the AI at your docs. One load, every route, outside Angular's zone, no component churn, no change-detection cost. Try the widget in the live demo, then add the snippet.

✦ Try it

One support inbox for all your projects, one flat price.

muro is live chat, an AI that answers from your own docs, and a shared inbox for every site you run. See it both sides in the live demo, check the flat pricing, or see how muro compares. It's the same snippet on every platform — browse every install guide.

Tm

✎ Written by

The muro team

muro.chat