> ## 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.

# Migrating from AppSignal for JavaScript

<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>

`@appsignal/browser` replaces [`@appsignal/javascript`](/front-end), its framework integrations, and its plugin packages. This guide maps the old API onto the new one.

`@appsignal/javascript` continues to work and keeps reporting to your existing error lists. New features only land in `@appsignal/browser`, so migrate when you want breadcrumbs without plugins, web vitals, or the Browser views.

## What changes

**One package instead of several.** Error tracking, breadcrumbs, and web vitals are all in `@appsignal/browser`. The plugin packages and framework integration packages have no equivalent, because their functionality is either built in or no longer needed.

**Functions instead of an instance.** There is no client object to create, pass around, or hand to a component. You call `init()` once and import the functions you need wherever you need them.

**Uncaught errors are reported without asking.** `@appsignal/plugin-window-events` existed because you had to opt in to them. They are on by default now. Noise from browser extensions is dealt with by throwing away errors from scripts on other domains, and by `beforeError`, rather than by turning the whole category off.

**Errors report to the `browser` namespace.** `@appsignal/javascript` reported to `frontend`, and there is no `namespace` option any more. Errors from the new package appear in the Browser section of your application rather than in your existing front-end error list. Existing incidents in the `frontend` namespace stay where they are.

<Warning>
  Notification settings are configured per namespace, so the ones you set up for
  `frontend` do not apply to `browser`. Set them up again after migrating, or
  front-end errors will arrive without notifying anyone.
</Warning>

Your existing `frontend` incidents keep their assignees, states, and severities. Errors from the new package arrive as new issues in the `browser` namespace, so they start unassigned, the same as any error AppSignal has not seen before.

**No spans, decorators, or overrides.** The span API and its hooks are gone. Set tags for every error with `setTags()`, pass context for a single error as the second argument to `captureError()`, and remove sensitive text in `beforeError` and `beforeBreadcrumb`.

## Configuration

| `@appsignal/javascript`     | `@appsignal/browser`                                                                              |
| --------------------------- | ------------------------------------------------------------------------------------------------- |
| `new Appsignal({ ... })`    | [`init({ ... })`](/browser/configuration)                                                         |
| `key`                       | `key`, unchanged. The same Front-end API key.                                                     |
| `revision`                  | `appVersion`                                                                                      |
| `namespace`                 | No equivalent. Errors always report to `browser`.                                                 |
| `ignoreErrors: [/pattern/]` | [`beforeError`](/browser/privacy#filtering-errors-and-breadcrumbs), returning `null` for a match. |
| `matchBacktracePaths`       | No equivalent. [Contact us](/support) if you rely on it.                                          |
| No equivalent               | `active`, to switch the SDK off completely outside production.                                    |
| No equivalent               | `endpoint`, `errors.sampleRate`, `breadcrumbs.*`, `privacy.*`.                                    |

Before:

<CodeGroup>
  ```js @appsignal/javascript theme={null}
  import Appsignal from "@appsignal/javascript";
  import { plugin as windowEvents } from "@appsignal/plugin-window-events";
  import { plugin as consoleBreadcrumbs } from "@appsignal/plugin-breadcrumbs-console";
  import { plugin as networkBreadcrumbs } from "@appsignal/plugin-breadcrumbs-network";

  export const appsignal = new Appsignal({
    key: "<YOUR_FRONTEND_API_KEY>",
    revision: "<YOUR_APP_REVISION>",
    ignoreErrors: [/ResizeObserver/],
  });

  appsignal.use(windowEvents());
  appsignal.use(consoleBreadcrumbs());
  appsignal.use(networkBreadcrumbs());
  ```
</CodeGroup>

After:

<CodeGroup>
  ```js @appsignal/browser 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>",
    beforeError: (event) => (/ResizeObserver/.test(event.message) ? null : event),
  });
  ```
</CodeGroup>

Uncaught exceptions, console breadcrumbs, and network breadcrumbs are all covered by that single call.

## Methods

| `@appsignal/javascript`                                            | `@appsignal/browser`                                                                                                                                        |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appsignal.sendError(error)`                                       | [`captureError(error)`](/browser/error-tracking#reporting-errors-manually)                                                                                  |
| `appsignal.sendError(error, (span) => span.setTags({ ... }))`      | `captureError(error, { ... })` for per-error context, or `setTags({ ... })` for tags on every error.                                                        |
| `appsignal.wrap(fn)`                                               | No equivalent. Use `try`/`catch` with `captureError`.                                                                                                       |
| `appsignal.addBreadcrumb({ category, action, message, metadata })` | [`addBreadcrumb({ category, message, data })`](/browser/breadcrumbs#adding-your-own-breadcrumbs). There is no `action` field, and `metadata` is now `data`. |
| `appsignal.createSpan()`, `appsignal.send(span)`                   | No equivalent.                                                                                                                                              |
| `appsignal.addDecorator(fn)`                                       | `setTags()` for tags, `beforeError` for everything else.                                                                                                    |
| `appsignal.addOverride(fn)`                                        | `beforeError` and `beforeBreadcrumb`.                                                                                                                       |
| `appsignal.use(plugin())`                                          | No equivalent. Built in.                                                                                                                                    |
| No equivalent                                                      | `setRouteTemplate()`, which groups errors and web vitals by route.                                                                                          |
| No equivalent                                                      | `setTags()`, `clearTags()`, `destroy()`.                                                                                                                    |

`appsignal.wrap()` ran your code, reported anything it threw, and gave you back a promise that rejects with the same error, so you handled it in a `try`/`catch` or a `.catch()`. The direct replacement makes both halves explicit:

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

  try {
    await riskyOperation();
  } catch (error) {
    captureError(error);
    throw error;
  }
  ```
</CodeGroup>

## Framework integrations

| Package                                                                                                | Replacement                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `@appsignal/react`                                                                                     | [`@appsignal/browser/react`](/browser/react). Pass `captureError` instead of an `instance` prop. There is no `override` prop, and no separate `LegacyBoundary` component. |
| `@appsignal/vue`, `@appsignal/angular`, `@appsignal/preact`, `@appsignal/ember`, `@appsignal/stimulus` | No equivalent. Errors these frameworks let through are reported automatically. Report the ones the framework catches itself with `captureError()` from its error handler. |
| `@appsignal/urql`                                                                                      | No equivalent. Report GraphQL errors with `captureError()` from your client's error exchange.                                                                             |
| `@appsignal/plugin-path-decorator`                                                                     | `setRouteTemplate()`, which is the built-in equivalent.                                                                                                                   |

The React error boundary changes shape:

<CodeGroup>
  ```jsx @appsignal/react theme={null}
  import { ErrorBoundary } from "@appsignal/react";
  import { appsignal } from "./appsignal";

  <ErrorBoundary instance={appsignal} action="Dashboard" tags={{ plan: "pro" }}>
    <Dashboard />
  </ErrorBoundary>
  ```

  ```jsx @appsignal/browser/react theme={null}
  import { captureError, setTags } from "@appsignal/browser";
  import { ErrorBoundary } from "@appsignal/browser/react";

  // Tags are global now
  setTags({ plan: "pro" });

  <ErrorBoundary captureError={captureError}>
    <Dashboard />
  </ErrorBoundary>
  ```
</CodeGroup>

The component name is detected from the React component stack, so there is no `action` prop to set.

## Steps to migrate

1. Install `@appsignal/browser@beta` and remove `@appsignal/javascript` along with every `@appsignal/plugin-*` and framework integration package.
2. Replace your `new Appsignal({ ... })` call with `init({ ... })`, using the configuration table in this guide. Add `endpoint` and `active`.
3. Replace `sendError` with `captureError`, and `wrap` with `try`/`catch`.
4. Move `ignoreErrors` patterns, decorators, and overrides into `beforeError` and `beforeBreadcrumb`.
5. Call `setRouteTemplate()` on each router navigation.
6. Swap the React error boundary import, if you use one.
7. Set up notification settings for the `browser` namespace.
8. Deploy, then confirm errors and web vitals arrive in the Browser section of your application.

Sourcemaps need no change. They are still matched on the revision string, which `appVersion` now supplies.
