---
title: "Send custom events | Grafana Cloud documentation"
description: "Use Faro Web SDK to send custom events"
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Send custom events

Faro correlates multiple data points such as logs, measurements, traces, and exceptions, to provide insights into how users interact with your web application. This is a powerful tool when you want to identify user experience bottlenecks with context-rich data from across the stack.

Although integrating the Faro Web SDK in your application provides auto instrumentation, there are cases where you might want to track user behavior by sending events during a session (for example, when a user clicks a button. The SDK includes an event API that can send any event.

The events sent to the collector endpoint are ingested by a Loki instance as logs with a specific label `kind=event`. For more information about Loki labels, refer to [Labels](/docs/loki/latest/get-started/labels/).

To reduce data usage Faro de-duplicates events. This means if two similar events are emitted consecutively, Faro only sends the event once.

## Before you begin

- Ensure you have registered your app in the Frontend Observability plugin
- Set up the Faro Web SDK from the [quickstart](/docs/grafana-cloud/monitor-applications/frontend-observability/quickstart/) or [instrumentation](/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/) documentation.

## Steps

A Faro instance is an object that can be accessed, after initialization, by either importing it from the `@grafana/faro-web-sdk` or by referencing it from the `window` global object.

typescript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```typescript
// Import the global faro instance
import { faro } from '@grafana/faro-web-sdk';
```

The `faro.api` object is a wrapper of the Faro API and provides a [`pushEvent`](https://github.com/grafana/faro-web-sdk/tree/main/packages/core#events) method with which you can send any event. You can also provide optional event metadata and a domain that is used to group events.

typescript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```typescript
// Send custom events with Faro SDK.
// 1. Send a simple, string based event
// 2. Send an event with enriched context

// Simple usecase
faro.api.pushEvent('user clicked add-to-cart');

// Context rich usecase
faro.api.pushEvent(
  'user clicked add-to-cart',
  {
    cartLength: 5,
  },
  'checkout'
);
```

## API

The events API allows you to pass the following parameters and options:

typescript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```typescript
pushEvent: (name: string, attributes?: EventAttributes, domain?: string, options?: PushEventOptions)
```

### Parameters

Expand table

| Name         | Description                                                                                   |
|--------------|-----------------------------------------------------------------------------------------------|
| `name`       | The name of the event                                                                         |
| `attributes` | Includes additional event attributes as key/value pairs                                       |
| `domain`     | Separates events by domain                                                                    |
| `options`    | Configures the behavior of the push API or injects additional data to change the signal data. |

### Push event options

Expand table

| Name                   | Description                                                                                                                                                                                                                       |
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `skipDedupe`           | Pushes the signal even if it is identical to the previous one                                                                                                                                                                     |
| `spanContext`          | Provides a custom `spanContext` to the signal                                                                                                                                                                                     |
| `timestampOverwriteMs` | The timestamp represents the exact moment when the respective API was called. In most cases, this precision is sufficient. The `timestampOverwriteMs`option allows you to pass an adjustment timestamp which can be used instead. |

## Modify beacon data before send

Faro provides the `beforeSend` hook which gets the current beacon (TransportItem) as it’s parameter, which allows you to modify beacon data before send:

ts ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```ts
initializeFaro({
  // ... faro configuration
  beforeSend: (item) => {
    switch (item.type) {
      case 'exception':
      case 'event':
      case 'trace':
      case 'measurement':
        return item;
      case 'log':
        return item.meta.user?.attributes?.['sendNoLogs'] ? null : item;
    }
  }
```
