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

# Instrumentation

> Turn dataLayer pushes, custom events and triggers into pagent events without changing your site

Many sites already announce what visitors do: a Google Tag Manager `dataLayer.push` on purchase, a `CustomEvent` when a form is sent, a gtag `event` call. pagent can listen for these and record them as [events](/docs/guides/tracking/events), so you don't have to add `window._pgnt.push` calls to your code.

There are three ways to instrument a site from pagent:

| Method | Listens for | Needs JavaScript execution |
| - | - | - |
| [Observed events](#observed-events) | dataLayer and gtag pushes, window `CustomEvent`s | No |
| [Triggers as events](#triggers-as-events) | A trigger matching on a page view | No |
| [Instrumentation scripts](#instrumentation-scripts) | Anything a short script can detect | Yes |

All three produce ordinary events. Build [conversion goals](/docs/guides/tracking/conversion-goals) on them the same way as on events your code reports.

## Observed events

An observed event is a definition that tells the SDK: "when the page pushes `purchase` into `dataLayer`, record a pagent event called `purchase`". The SDK only listens for events you defined. It does not collect anything else from your dataLayer.

### Record and define events with the Chrome extension

The fastest way to find what your site emits is the Events recorder in the [pagent Chrome extension](https://chromewebstore.google.com/detail/kaafhmlenkdmmnjoajepghdaoejiamhf).

<Steps>
  <Step title="Arm the recorder">
    Open your site, open the extension and go to **Events**. Click **Arm and reload**. The page reloads with a recorder installed before any of your scripts run.
  </Step>

  <Step title="Do the action">
    Browse your site and perform the actions you want to track: add a product to the cart, submit a form, complete a checkout. The recorder lists every `CustomEvent`, dataLayer push and gtag call it sees, grouped by name. Nothing is sent to your visitors while you record.
  </Step>

  <Step title="Define the events you need">
    Click **Stop recording**, select the events to keep and click **Define events**. For each one, set:

    * **Label**: the pagent event name, for example `purchase`. Lowercase letters, digits and `_ . : -`, up to 120 characters.
    * **Listen on every page** or **Only listen on matching pages**: limit where the SDK listens, for example `/checkout/*`.
    * **Forwarded properties**: up to three payload fields to keep with the event, for example `ecommerce.currency`. Fields that look like personal data are marked **PII**; leave those out.
    * **Revenue path** (optional): the payload field that holds the order value, for example `ecommerce.value`.
  </Step>
</Steps>

The SDK picks up new definitions within about a minute. The events then appear under **Tracking → Sources → Events** with the source **dataLayer** or **Window event** and the status **Defined**.

### What the SDK listens for

* **dataLayer pushes** in both common shapes: GTM objects with an `event` key, and gtag calls such as `gtag("event", "purchase", { value: 49.99 })`.
  ```javascript theme={"dark"}
  window.dataLayer.push({ event: "purchase", ecommerce: { value: 49.99, currency: "EUR" } });
  ```
  Entries pushed before the SDK loaded are replayed, so early pushes are not lost. Your dataLayer keeps working exactly as before: the page's own push runs first and pagent never throws into it.
* **Window events**: a `CustomEvent` dispatched anywhere on the page. Properties and revenue are read from the event's `detail`.
  ```javascript theme={"dark"}
  window.dispatchEvent(new CustomEvent("newsletter:subscribed", { detail: { list: "weekly" } }));
  ```

Only the declared properties and the revenue field leave the page. The rest of the payload is never sent to pagent.

<Note>
  **Revenue units differ from reported events.** Observed revenue is read in major units, the way tag managers send it: `value: 49.99` is recorded as 4999 cents. Events you report with `window._pgnt.push` must send integer cents yourself. See [Tracking revenue](/docs/guides/tracking/revenue).
</Note>

### Editing a definition

Open **Tracking → Sources → Events** and choose **Edit definition** on the event. You can change the display name, description, page scope, forwarded properties and revenue path. The label cannot change: it links everything already recorded.

A page scope only limits where the SDK listens. It never filters events that were already recorded.

### Observed vs defined

Events you report with `window._pgnt.push` or the REST API register themselves on first use. Their status is **Observed** until you edit their definition, after which it is **Defined**. Both statuses work the same for goals.

Observed dataLayer and window events only have history from the moment their definition was published. Reported events have history from the first time your code sent them.

## Triggers as events

A trigger (under **Triggers** in pagent) already describes a condition on your site, for example "cart has items" or "visitor came from a paid campaign". You can record every page view where it matches as an event.

1. Open **Tracking → Sources → Events** and click **Track a trigger**.
2. Pick the **Trigger**, enter a **Label** such as `cart_has_items`, and optionally a display name.
3. Click **Add event**.

The event is recorded on every page view where the trigger matches. Create an event goal on it to measure it in tests.

## Instrumentation scripts

When an action cannot be observed from a dataLayer push or a window event, an instrumentation script can detect it and report it. Scripts are short snippets the SDK runs once per page load.

1. Open **Tracking → Instrumentation** and click **New script**.
2. Give it a **Name**, for example `Newsletter signup bridge`.
3. Write the **Code**. Report events with `window._pgnt.push`:
   ```javascript theme={"dark"}
   document.addEventListener("submit", (e) => {
       if (e.target.matches("#newsletter")) {
           window._pgnt.push({ kind: "event", label: "newsletter_signup" });
       }
   }, true);
   ```
4. Leave **Run at page start** on to run it on every page, or turn it off and pick a **Trigger** to run it only where that trigger matches.
5. Make sure the script is **Enabled** and save.

Keep scripts safe to run more than once, and report events rather than conversions.

<Warning>
  Instrumentation scripts require JavaScript execution. Turn it on under **Settings → Advanced → JavaScript execution → Allow JavaScript execution**. While it is off, scripts are not published to your site. On sites with a Content Security Policy that blocks `unsafe-eval`, scripts cannot run; use observed events instead, which need no script.
</Warning>
