# Site script: page views and clicks tied to the contact

> Paste the script (js.bip.marketing/v1.0.0.js, with the bip-namespace attribute) on your site. It records page views, SPAs included, and clicks on external links. Once the visitor becomes a contact, through a form or POST /api/leads with tracker, their next visits go to the contact's Feed and update the Last Location.

Fonte: https://wiki.bip.marketing/en-us/site-script · Atualizado: 2026-10-08

<UseCaseMeta effort="api" plan="free" />

Find out which pages your contacts visit and which links they click. With the BIP script on your site, every contact gets a visit history right in their profile: you know whether the person saw the pricing page or clicked the partner store link before you talk to them.

<Checklist items="Access to your site's code, to paste a script tag on every page|Your account's namespace, in Settings → General|A sign-up form on your site, connected to BIP through your server|An API key with Leads Write, stored on the server" />

## What you'll get

- The pages each contact visits, in their profile's **Feed**, including on single-page apps (SPAs).
- Clicks on links that lead off your site, recorded with no extra setup.
- The contact's **Last Location** (city) updated with every page they visit, ready for the **First / Last Location** criterion in **Segments**.
- URL parameters, such as `utm_source` and `utm_campaign`, stored with the visit.

## How it works

<Steps items="Paste the script with your account's namespace|Link the visitor to the contact at sign-up|Follow the visits in the contact's Feed" />

The script gives each browser an anonymous visitor ID, kept for 10 years. It's available on the page as `window.BIP_VISITOR_ID`.

While the visitor is anonymous, nothing is stored. Once that ID is linked to a contact, through a form or through `POST /api/leads` with the `tracker` field, every visit and click after that goes into that person's profile.

<Callout type="warning">
The history starts when the visitor becomes a contact. Visits made before the link aren't stored. So link the ID at the very first sign-up.
</Callout>

What the script records on its own:

- **View**: when the page loads and on every path change in single-page apps (navigation through `pushState`, `replaceState` and the back and forward buttons).
- **Click**: on `<a>` links that lead to another address, such as a link from `lojahorizonte.com.br` to `parceiro.com.br`. A different subdomain counts too. Links within the same site and links that start with `#` or `javascript:` are left out.

Events are sent with `sendBeacon`, which doesn't hold up the page, and any failure is silent: tracking never interrupts your site.

## Step by step

### 1. Copy the account namespace

1. In **Settings**, open the **General** tab.
2. Under **Account Information**, click the copy button next to **Namespace**.

<Shot src="/img/script-do-site/1-en-us.png" alt="Account namespace in Settings, General tab, Account Information section" url="dash.bip.marketing/…/settings" />

### 2. Paste the script on your site

Paste the tag below on every page, before `</head>`, replacing `YOUR_NAMESPACE` with the namespace you copied:

<Copy label="HTML" code>
<script bip-namespace="YOUR_NAMESPACE" src="https://js.bip.marketing/v1.0.0.js"></script>
</Copy>

If your platform doesn't accept attributes on the `script` tag, set the namespace first:

<Copy label="HTML (alternative)" code>
<script>
  window.BIP_ACCOUNT_NAMESPACE = 'YOUR_NAMESPACE';
</script>
<script src="https://js.bip.marketing/v1.0.0.js"></script>
</Copy>

To check it, open the published site, open the browser console and type `window.BIP_VISITOR_ID`. The visitor ID shows up.

<Callout type="tip">
On `localhost` addresses, the script doesn't send automatic views. Test on the published site or in a staging environment with its own domain.
</Callout>

### 3. Link the visitor to the contact

In your site's sign-up, newsletter or login form, read `window.BIP_VISITOR_ID` and send it along with the form data to **your server**. The server calls `POST /api/leads` with the `tracker` field. From then on, that browser's visits go into the contact's profile.

- The API key stays on the server. The browser never talks to the API directly.
- If the script hasn't loaded yet, `tracker` goes out empty and BIP ignores the field. The contact is created or updated as usual.
- Each browser and device has its own ID. Send `tracker` again at every login: BIP adds the new ID to the same contact.
- `tracker` also works in the `lead` object in `/api/campaigns/trigger`: it creates the contact, links the visitor and fires the welcome message in the same call. See the [API](/en-us/api).

The ready-made code is in [Ready to copy](#ready-to-copy).

<PlanOnly plan="full">
BIP **Forms** send the visitor ID along with the sign-up, with no extra code.
</PlanOnly>

### 4. Check the visits on the contact

1. In **Leads**, open a contact who signed up through your site.
2. In the **Feed**, look for the **Viewed via Web** and **Clicked via Web** entries, with the page address. Each entry also shows the city and the browser.
3. Hover over **Search Params** to see the URL parameters of that visit, such as `utm_source`.

<Shot src="/img/script-do-site/4-en-us.png" alt="Contact Feed with pages viewed and clicks via web" url="dash.bip.marketing/…/leads" />

### 5. Segment by the city of the last visit

Every page visited updates the contact's **Last Location** with the city they browsed from. Use it in **Segments**:

1. In **Segments**, click **New Segment**.
2. In **Add Criteria**, choose **First / Last Location**.
3. In **Type**, choose **Last Location (City)**, **(Region)** or **(Country)**, or **Last Location (Geo)** for a radius on the map.
4. Choose the **Operator** and fill in the **Value** (for the Geo type, **In radius** and the circle on the map).
5. Check the live count and save.

The location is always the city: a radius selects the cities whose center falls inside the circle.

<Shot src="/img/script-do-site/5-en-us.png" alt="First / Last Location criterion with the Last Location (City) type" url="dash.bip.marketing/…/segments/…" />

<PlanOnly plan="full">
In **Flows**, the **Filter** step accepts the **Event** criterion with the URL **Entity Type**: it picks out who visited a page or clicked an external link from it.
</PlanOnly>

## Reference

### What the script records

| Event | When                                                         | What gets stored                                                                                            |
| ----- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| View  | When the page loads and on every path change in SPAs         | Page (without `https://` and without anything after `?`), URL parameters, referring page, browser and city  |
| Click | Click on an `<a>` link that leads to another address (host)  | Page where the click happened, clicked link, browser and city                                               |

### Manual functions

Available on `window` once the script loads.

| Function                    | What it does                                     | When to use it                                                                                               |
| --------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `BIP_SEND_VIEW_EVENT()`     | Sends a view of the current page                 | Screens that change without changing the URL path: tabs, steps with `?step=`, content loaded on the same page |
| `BIP_SEND_CLICK_EVENT(url)` | Sends a click with the URL you pass              | Buttons that aren't `<a>` links, or internal links you want to count                                         |
| `BIP_SET(token)`            | Swaps the visitor ID in this browser             | Using an ID you've already linked to the contact, for example after login                                    |
| `BIP_RESET()`               | Clears this browser's ID                         | Logout on a shared computer: the next visit starts out anonymous                                             |

### Read-only variables

| Variable                     | What it returns                            |
| ---------------------------- | ------------------------------------------ |
| `window.BIP_VISITOR_ID`      | Visitor ID in this browser                 |
| `window.BIP_LAST_EVENT_SENT` | The last event sent, for checking          |

### What changes on the contact

| Where             | What the visit does                                                                    |
| ----------------- | -------------------------------------------------------------------------------------- |
| **Feed**          | A **Viewed via Web** or **Clicked via Web** entry, with the page, the city and the browser |
| **Last Location** | Becomes the city of the visited page (views)                                           |
| **Search Params** | The visit's URL parameters, such as `utm_source`, are stored with the view             |

### Installation

| Item           | Value                                                          |
| -------------- | -------------------------------------------------------------- |
| Script         | `https://js.bip.marketing/v1.0.0.js`                           |
| Namespace      | `bip-namespace` attribute or `window.BIP_ACCOUNT_NAMESPACE`    |
| Where to paste | Every page, before `</head>`                                   |
| localhost      | No automatic views                                             |

## Ready to copy

### Script for every page

<Copy label="HTML" code>
<script bip-namespace="YOUR_NAMESPACE" src="https://js.bip.marketing/v1.0.0.js"></script>
</Copy>

### Form that links the visitor to the contact

In the browser, Loja Horizonte sends the ID along with the newsletter sign-up to its own server:

<Copy label="TypeScript (browser)" code>
// Loja Horizonte newsletter form
const form = document.querySelector<HTMLFormElement>('#newsletter');
form?.addEventListener('submit', async event => {
  event.preventDefault();
  const dados = new FormData(event.currentTarget as HTMLFormElement);
  await fetch('/api/newsletter', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      nome: dados.get('nome'),
      email: dados.get('email'),
      tracker: (window as any).BIP_VISITOR_ID ?? ''
    })
  });
});
</Copy>

On the server, the `/api/newsletter` route creates or updates the contact in BIP with `tracker`:

<Copy label="TypeScript (server)" code>
// /api/newsletter route on the Loja Horizonte server
const API_KEY = process.env.BIP_API_KEY ?? 'YOUR_API_KEY';
export async function cadastrarNewsletter(body: { nome: string; email: string; tracker: string }) {
  const res = await fetch('https://api.bip.marketing/api/leads', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'x-bip-api-key': API_KEY },
    body: JSON.stringify({
      name: body.nome,
      email: body.email,
      tracker: body.tracker,
      tags: ['newsletter']
    })
  });
  if (!res.ok) throw new Error(`BIP ${res.status}: ${await res.text()}`);
  return res.json(); // { id, ... }
}
</Copy>

The same call in curl, for testing:

<Copy label="curl" code>
curl -X POST https://api.bip.marketing/api/leads \
  -H "Content-Type: application/json" \
  -H "x-bip-api-key: YOUR_API_KEY" \
  -d '{"name": "Sofia Costa", "email": "sofia.costa@exemplo.com", "tracker": "VISITOR_ID", "tags": ["newsletter"]}'
</Copy>

### Click on a button that isn't a link

<Copy label="TypeScript (browser)" code>
// "Falar com a loja" (talk to the store) button, which opens the chat
document.querySelector('#falar-com-a-loja')?.addEventListener('click', () => {
  (window as any).BIP_SEND_CLICK_EVENT?.('https://lojahorizonte.com.br/atendimento');
});
</Copy>

### Segment by the city of the last visit

| Criterion             | Type                 | Operator | Value    |
| --------------------- | -------------------- | -------- | -------- |
| First / Last Location | Last Location (City) | Contains | Curitiba |

## How to measure

- **In the browser**: in the published site's console, `window.BIP_VISITOR_ID` shows the ID and `window.BIP_LAST_EVENT_SENT` shows the last event sent.
- **On the contact**: in **Leads**, open someone who signed up through the site. The **Feed** shows every **Viewed via Web** and **Clicked via Web**, and the **Last Activity Location** follows the city of the latest visit.
- **In the segment**: with the **First / Last Location** criterion → **Last Location (City)**, the live count shows how many contacts had their last activity in each city.

## Frequently asked questions

### Do visits from before sign-up show up?

No. The history starts the moment the visitor ID is linked to the contact. So send `tracker` with the very first form the person fills out.

### Does it work on single-page apps (React, Vue, Angular)?

Yes. The script detects every path change in the URL and records a new view. For screens that change without changing the path, such as tabs or steps at the same address, call `BIP_SEND_VIEW_EVENT()`.

### Why don't I see any events when I test on my computer?

On `localhost` addresses, automatic views aren't sent. And the visitor has to be linked to a contact. Test on the published site, sign up through the form and browse around: the visits show up in the contact's **Feed**.

### Can the script break my site?

No. Any tracking failure is ignored without affecting the page, and events go out with `sendBeacon`, which doesn't wait for a response.

## See also

- [BIP API: keys, contacts, events and triggers](/en-us/api)
- [Segments: the 10 criteria to filter contacts](/en-us/segments)
- [Webhooks: push every send to your system](/en-us/webhooks)
- [Compliance: preferences portal, opt-out and topics](/en-us/compliance)
- [Full API reference](https://bipmarketing.readme.io)
