> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Installing AppSignal for Browser

<Note>
  Browser monitoring is a beta [AppSignal Labs](/labs) feature. The
  `@appsignal/browser` package is published under the `beta` tag on npm, and its
  configuration and API may still change between beta releases. Share feedback
  in our [Discord community](https://discord.gg/EjF6ykYx63).
</Note>

If you are adding a new application to AppSignal, follow the [installation guide](/guides/new-application) first.

## Find your Front-end API key

Browser monitoring uses your application's Front-end API key, listed under "Front-end error monitoring" on the ["Push & deploy" page](https://appsignal.com/redirect-to/app?to=api_keys) of your application's settings.

This key is app-specific, so a staging and a production app each have their own. It is meant to be exposed in public, so it is safe to include in your front-end bundle.

It is not one of the Push keys your back-end integrations use. Those are on the same page, listed as the Organization Push key and the App environment Push key, and they are write-only keys that must stay secret.

If you ever need to replace the Front-end API key, that page has a button to cycle it. Cycling generates a new key and invalidates the old one in a single step, and you cannot undo it, so deploy the new key promptly. Anything still sending the old key stops reporting in the meantime.

## Install the package

<CodeGroup>
  ```sh npm theme={null}
  npm install @appsignal/browser@beta
  ```

  ```sh yarn theme={null}
  yarn add @appsignal/browser@beta
  ```

  ```sh pnpm theme={null}
  pnpm add @appsignal/browser@beta
  ```
</CodeGroup>

While browser monitoring is in beta, install from the `beta` tag. Without it, package managers resolve to the latest stable release, and there is not one yet.

## Initialize the SDK

Call `init()` once, as early in the page lifecycle as you can. Anything that throws before `init()` runs is not captured.

Create an `appsignal.js` file next to your application's entry point:

<CodeGroup>
  ```js appsignal.js theme={null}
  import { init } from "@appsignal/browser";

  init({
    key: "<YOUR_FRONTEND_API_KEY>",
    endpoint: "https://appsignal-endpoint.net",
    active: process.env.NODE_ENV === "production",
    appVersion: "<YOUR_APP_REVISION>",
  });
  ```
</CodeGroup>

Then import that file as the first import in your entry point, before your application code and before other libraries:

<CodeGroup>
  ```js main.js theme={null}
  // Place this at the top, before any other import
  import "./appsignal";

  // Your application code follows
  ```
</CodeGroup>

Three of those options matter on the first install:

* `active` ties collection to your build environment, so development, test, and CI runs stay quiet. When it is `false`, `init()` does nothing at all: it changes nothing on the page, starts no timers, and makes no requests. Every other function does nothing too, so you can call them anywhere without checking first.
* `appVersion` is the release tag, commit SHA, or deploy ID of the running build. Errors and web vitals are tagged with it, which is what makes the version filters and [sourcemap](/browser/error-tracking#sourcemaps) lookups work.
* `endpoint` is where data is sent. Use `https://appsignal-endpoint.net` unless you proxy AppSignal traffic through your own domain. When you leave it out, the SDK posts to the current origin, which is the setting you want if you do proxy.

For the full list, see the [configuration options](/browser/configuration).

## Install without a bundler

If you add JavaScript to your pages with a plain `<script>` tag rather than building it with a bundler, use the UMD build. It provides the same functions on a global called `AppsignalBrowser`:

<CodeGroup>
  ```html HTML theme={null}
  <script src="https://cdn.jsdelivr.net/npm/@appsignal/browser@1.0.0-beta.3/dist/browser.umd.js"></script>
  <script>
    AppsignalBrowser.init({
      key: "<YOUR_FRONTEND_API_KEY>",
      endpoint: "https://appsignal-endpoint.net",
      appVersion: "<YOUR_APP_REVISION>",
    });
  </script>
  ```
</CodeGroup>

Pin the version in the URL rather than using a floating tag, so a new release cannot change what your users download.

## Report the current route

Single-page applications should tell the SDK which route template the user is on, for example `/users/:id` rather than `/users/42`:

<CodeGroup>
  ```js JavaScript theme={null}
  import { setRouteTemplate } from "@appsignal/browser";

  setRouteTemplate("/users/:id");
  ```
</CodeGroup>

Call it every time your router navigates. Both errors and web vitals are grouped by whatever route you report. A template keeps a thousand order pages together, instead of splitting them into a thousand routes with one visit each.

If you never call it, AppSignal works out a template from the URL itself by replacing anything that looks like an ID. That works, but the groups it produces are rougher than the ones you get from telling it directly.

For React Router, Next.js, and other React setups, see [AppSignal for Browser with React](/browser/react).

## Verify the installation

1. Deploy a build with `active` set to `true`, or temporarily set `active: true` in development.
2. Open your application and throw an error from the browser console, for example `setTimeout(() => { throw new Error("AppSignal test error") })`. Throwing from the console directly is caught by the console itself and never reaches `window`.
3. Open the Errors view in the Browser section of your application in AppSignal. The error arrives within a few seconds.

Web vitals take longer to appear. They are batched and flushed when the page is hidden or the route changes, so navigate away or switch tabs before checking the Performance view.

If nothing arrives, work through the [troubleshooting page](/browser/troubleshooting).

## Content Security Policy

If your application sends a Content Security Policy header, add the AppSignal endpoint to `connect-src`, or requests are blocked:

<CodeGroup>
  ```sh Shell theme={null}
  Content-Security-Policy: connect-src 'self' https://appsignal-endpoint.net
  ```
</CodeGroup>

## Assets hosted on a CDN

When a script loaded from another domain throws an error, the browser refuses to share the details. Your page sees only the message `Script error.`, with no stack trace and no line number. There is nothing there to debug, so the SDK throws those away.

To get the real errors from scripts on a CDN, serve them with an `Access-Control-Allow-Origin` header and add the `crossorigin` attribute to the script tags:

<CodeGroup>
  ```html HTML theme={null}
  <script src="//cdn.example.com/bundle.js" crossorigin="anonymous"></script>
  ```

  ```erb Rails theme={null}
  <%= javascript_include_tag "application", :crossorigin => :anonymous %>
  ```
</CodeGroup>

***

<Note>
  📖 Continue with our [installation guide](/guides/new-application).
</Note>

## Uninstall

1. Remove the `import "./appsignal"` line from your entry point, and delete `appsignal.js`.
2. Remove `@appsignal/browser` from your `package.json`, then run `npm install` or `yarn install` to update your lockfile. Alternatively, run `npm uninstall @appsignal/browser` or `yarn remove @appsignal/browser`.
3. Commit and deploy. Your application stops sending browser data as soon as the new build is live.
4. Optionally, [remove the app](/guides/application/deleting-applications) in AppSignal.

To stop collection for the rest of the current page without a redeploy, call `destroy()`. It takes effect immediately, but does not persist: the next page load starts collecting again.

<Note>
  📖 Continue with our [uninstall
  guide](/guides/application/deleting-applications).
</Note>
