Frontend Instrumentation – JavaScript

Complete guide to instrument front-end applications with the Faro SDK, sending data to Elven’s collector-fe.

Overview

This guide aims to instruct the instrumentation of front-end applications using Grafana’s Faro SDK, with the collector-fe, an exclusive component of Elven Observability. You’ll be able to track:

  • User sessions and navigation

  • Custom events

  • Structured logs

  • Performance metrics (such as load time)

Installation

Using NPM:

npm install @grafana/faro-web-sdk
npm install @grafana/faro-web-tracing

Using Yarn:

yarn add @grafana/faro-web-sdk
yarn add @grafana/faro-web-tracing

If you’re using React with React Router:

yarn add @grafana/faro-react

Basic usage

Best practice: create a separate file like faro.ts to configure the SDK and import it in the entry point (index.tsx or App.tsx).

// faro.ts
import { initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing';

initializeFaro({
  url: 'https://seu_collector-fe.com/collect/<TENANT>/<TOKEN>',
  app: {
    name: 'my-app', # Name of your application
    version: '1.0.0', # Your application version
    environment: 'production', # Your application environment
  },
  consoleInstrumentation: {
    disabledLevels: [],
  },
  sessionTracking: {
    samplingRate: 1,
    persistent: true,
  },
  instrumentations: [
    ...getWebInstrumentations(),
    new TracingInstrumentation(),
  ],
});

Setup with React Router (optional)

import {
  initializeFaro,
  createReactRouterV6DataOptions,
  ReactIntegration,
  getWebInstrumentations,
} from '@grafana/faro-react';
import { TracingInstrumentation } from '@grafana/faro-web-tracing';
  app: {
    name: 'my-app', # Name of your application
    version: '1.0.0', # Your application version
    environment: 'production', # Your application environment
  },
  sessionTracking: {
    samplingRate: 1,
    persistent: true,
  },
  instrumentations: [
    ...getWebInstrumentations(),
    new TracingInstrumentation(),
    new ReactIntegration({
      router: createReactRouterV6DataOptions({
        matchRoutes,
      }),
    }),
  ],
});

Logged-in user synchronization

export const FaroUserSync = () => {
  const { user } = useAuth();

  useEffect(() => {
    if (user) {
      faro.api.setUser({
        id: user.uid,
        username: user.displayName ?? 'no-logged',
        email: user.email ?? 'no-logged',
      });
    }
  }, [user]);

  return null;
};

Example with Next.js

When using the Faro SDK in Next.js applications, it’s necessary to ensure that instrumentation happens only on the client side, since window is not available during server-side rendering. The ideal way to configure it is inside Next’s special file, _app.tsx.

Exemplo de uso em pages/_app.tsx

// pages/_app.tsx
import type { AppProps } from 'next/app';
import { useEffect } from 'react';
import { initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing';

function MyApp({ Component, pageProps }: AppProps) {
  useEffect(() => {
    initializeFaro({
      url: process.env.NEXT_PUBLIC_FARO_URL!,
      app: {
        name: 'next-app',
        version: '1.0.0',
        environment: process.env.NODE_ENV,
      },
      sessionTracking: {
        samplingRate: 1,
        persistent: true,
      },
      instrumentations: [
        ...getWebInstrumentations(),
        new TracingInstrumentation(),
      ],
    });
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

Tip: Use variables like NEXT_PUBLIC_FARO_URL in .env.local to keep the token and tenant out of the source code.

Custom events, logs, and metrics

Custom events:

faro.api.pushEvent('click_cta', {
  label: 'Começar Agora',
  category: 'CTA',
  page: '/home',
});

Custom logs:

faro.api.pushLog(['debug'], 'User clicked the sign-up button', {
  location: '/signup',
  component: 'SignupCTA',
});

Custom metrics:

faro.api.pushMeasurement('search_time', {
  value: 273,
  unit: 'ms',
  attributes: {
    page: '/search',
    query: 'observability',
  },
});

Best practices

  • Store FARO_URL in .env (REACT_APP_FARO_URL).

  • Never send sensitive data in events or logs.

  • Prefer importing faro.ts at the start of the application.

  • Use samplingRate according to your app’s volume (e.g., 0.1 in production).

Troubleshooting

Problem
Probable cause
Solution

Events are not being received

Invalid or expired token

Check the JWT

Nothing appears on the dashboard

Incorrect URL or CORS blocked

Check the URL and CORS of the collector-fe

Session does not persist

Blocked cookies or persistent: false

Activate persistent: true

Duplicated logs

initializeFaro being called multiple times

Move to a single file and import once

Authentication and collector URL

The submission URL follows the format:

https://seu_collector-fe.com/collect/<tenant>/<token>

Real example:

https://seu_collector-fe.com/collect/elven/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Refer to: collector-fe – Installation Guide

Testing your instrumentation

  1. Access the app using the browser.

  2. Check in DevTools if the call to collector-fe returns 2xx.

  3. Access the Grafana dashboard and filter by events from your tenant.

Made with love by Elven Observability

If you have any questions or suggestions, feel free to contact us.: elven.works.

Last updated

Was this helpful?