AnveVoice

Add a Voice AI Agent to an Angular App (2026)

Add the AnveVoice voice agent to an Angular app: one script tag in src/index.html, server rendering notes, router behaviour and fixes for common problems.

How to add AnveVoice to an Angular application

Open the index.html file of your Angular project (src/index.html in a default workspace) and paste the AnveVoice script tag just before the closing body tag. Angular loads that file once, so the voice button stays on screen while visitors move between routes. Steps checked against the official documentation on 2026-10-14.

At a glance

  • Where the code goes: src/index.html, the host page named by the build target's index option in angular.json
  • Coding needed: None: one line of HTML. A small service is only needed if you must inject the tag from TypeScript
  • Plan limits: None from Angular. Free AnveVoice plan works on any build
  • Time: About 2 minutes, then rebuild and redeploy

Before you start

Create a voice bot at app.anvevoice.app (the Free plan needs no card) and copy its embed ID from the dashboard. You will paste that ID into the install tag shown below. Angular's file-structure reference describes src/index.html as the main HTML page served to visitors, and notes that the CLI adds your own JavaScript and CSS bundles to it during the build. That is why you normally never touch the file. A third-party tag such as AnveVoice is the exception: the CLI knows nothing about it, so you add it by hand and it survives every build.

  • 1. Copy the install tag — Swap YOUR_EMBED_ID for the value from your dashboard. Append &position=bottom-left or &theme=dark to the URL if you want a different corner or colour scheme. Code: <script src="https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID" async></script>

Method 1: edit src/index.html (recommended)

The location of the host page is not hard-wired. Angular's workspace configuration reference documents an index option on the build target that holds the path of the file used to generate the application's HTML. Open angular.json, find projects → your-app → architect → build → options → index, and edit whichever file it points to. In a project made by ng new that is src/index.html.

  • 1. Open the host page — Open the file named by the index option. You will see an app-root element inside the body and no script tags, because the CLI injects those at build time.
  • 2. Paste the tag below app-root — Place the AnveVoice tag after the app-root element and before the closing body tag. The async attribute means it never delays Angular's bootstrap.
  • 3. Rebuild — Run ng serve for development, which reloads on save, or ng build for a production bundle. The tag is copied through unchanged into the generated index.html in your output folder.

Why not the scripts array in angular.json

The same reference describes a scripts option for build targets: an array of JavaScript files, with paths relative to the workspace root, that are loaded as if you had written them in a script tag in index.html. Its examples are local entry-point files and the page says nothing about remote URLs. Do not download embed.js and list it there. A vendored copy would never receive updates and would bypass the embed ID in the URL. Keep the remote tag in index.html.

Optional: inject from TypeScript, safely with SSR

Applications created with the server-rendering flag, or later upgraded with ng add @angular/ssr, run component code on the server where window and document do not exist. Angular's SSR guide tells you to keep browser-only work out of that path, to use the DOCUMENT injection token instead of the global document, and to rely on afterNextRender, which runs only in the browser. A static tag in index.html needs none of this and is the simplest choice. If you want the tag only in production or only on some routes, create a small root-level component or service and add the script from afterNextRender. Guard it so a second call does nothing. Older Angular versions export DOCUMENT from @angular/common instead of @angular/core. Use the import your project's version expects.

  • 1. Inject from the root component — Add this to your root component's constructor. It runs in the browser only, uses the DOCUMENT token, and skips the insert if the tag already exists. Code: import { Component, DOCUMENT, afterNextRender, inject } from '@angular/core'; @Component({ selector: 'app-root', template: '<router-outlet />' }) export class App { private doc = inject(DOCUMENT); constructor() { afterNextRender(() => { const src = 'https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID'; if (this.doc.querySelector(`script[src="${src}"]`)) return; const s = this.doc.createElement('script'); s.src = src; s.async = true; this.doc.body.appendChild(s); }); } }

Routing and deployment gotchas

  • Angular is a single-page application, so the router swaps views without reloading index.html. The AnveVoice tag executes once per full page load and stays alive across route changes; you do not need a router hook.
  • Angular's deployment guide says the server must return the host page index.html for URLs it has no file for. Make sure your fallback serves your edited index.html, otherwise deep links open without the voice button.
  • A <base href> in index.html does not affect the absolute https URL of the AnveVoice tag, so subfolder deployments are fine.
  • Prerendered or server-rendered output is generated from the same host page, so the tag appears in the delivered HTML as well.

Check that it works

  • 1. Load the app — Open the dev server or your deployed site in a private window. localhost counts as a secure context for the microphone; a deployed site must use HTTPS.
  • 2. Look for the button — A round microphone button appears bottom-right unless you set position. Click it, allow the microphone and ask something about your pages.
  • 3. Confirm the request — In the browser's Network tab, filter for embed.js and check it returns 200. View the page source or the built dist/index.html to confirm the tag is present once.

Common problems

  • Button missing after deploy: you edited a different index file than the one the production configuration uses. Check the index option under each configuration in angular.json.
  • Tag appears twice: it is in index.html and in a component. Keep one; AnveVoice ignores a duplicate, but one source is easier to maintain.
  • Content Security Policy blocks it: allow https://anvevoice.app in script-src and connect-src if your host sends a CSP header.
  • ReferenceError: document is not defined during build: a component touches document outside afterNextRender. Move that code into afterNextRender or use the DOCUMENT token.
  • Old bundle served: your CDN or service worker is caching the previous index.html. Purge it, or bump the service worker version.

Sources

  • Angular docs: workspace file structure (src/index.html) (https://angular.dev/reference/configs/file-structure) — checked 2026-10-14
  • Angular docs: workspace configuration (index and scripts options) (https://angular.dev/reference/configs/workspace-config) — checked 2026-10-14
  • Angular docs: server and hybrid rendering (https://angular.dev/guide/ssr) — checked 2026-10-14
  • Angular docs: deployment (https://angular.dev/tools/cli/deployment) — checked 2026-10-14

Related

  • How to add AnveVoice to a React app
  • How to add AnveVoice to a Vue app
  • How to add AnveVoice to an Ember.js app
  • How to add AnveVoice to a plain HTML website

Try AnveVoice on your site

Free plan: $0, 50,000 tokens a month, no card. Get your embed ID in the dashboard, then paste one tag.