Quick answer
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.
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.
What you need
- 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_sourceandutm_campaign, stored with the visit.
How it works
- 1Paste the script with your account's namespace
- 2Link the visitor to the contact at sign-up
- 3Follow 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.
What the script records on its own:
- View: when the page loads and on every path change in single-page apps (navigation through
pushState,replaceStateand the back and forward buttons). - Click: on
<a>links that lead to another address, such as a link fromlojahorizonte.com.brtoparceiro.com.br. A different subdomain counts too. Links within the same site and links that start with#orjavascript: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
- In Settings, open the General tab.
- Under Account Information, click the copy button next to Namespace.

Screenshot coming soon
2. Paste the script on your site
Paste the tag below on every page, before </head>, replacing YOUR_NAMESPACE with the namespace you copied:
<script bip-namespace="YOUR_NAMESPACE" src="https://js.bip.marketing/v1.0.0.js"></script>
If your platform doesn't accept attributes on the script tag, set the namespace first:
<script> window.BIP_ACCOUNT_NAMESPACE = 'YOUR_NAMESPACE'; </script> <script src="https://js.bip.marketing/v1.0.0.js"></script>
To check it, open the published site, open the browser console and type window.BIP_VISITOR_ID. The visitor ID shows up.
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,
trackergoes out empty and BIP ignores the field. The contact is created or updated as usual. - Each browser and device has its own ID. Send
trackeragain at every login: BIP adds the new ID to the same contact. trackeralso works in theleadobject in/api/campaigns/trigger: it creates the contact, links the visitor and fires the welcome message in the same call. See the API.
The ready-made code is in Ready to copy.
BIP Full only
BIP Forms send the visitor ID along with the sign-up, with no extra code.
4. Check the visits on the contact
- In Leads, open a contact who signed up through your site.
- 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.
- Hover over Search Params to see the URL parameters of that visit, such as
utm_source.

Screenshot coming soon
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:
- In Segments, click New Segment.
- In Add Criteria, choose First / Last Location.
- In Type, choose Last Location (City), (Region) or (Country), or Last Location (Geo) for a radius on the map.
- Choose the Operator and fill in the Value (for the Geo type, In radius and the circle on the map).
- Check the live count and save.
The location is always the city: a radius selects the cities whose center falls inside the circle.

Screenshot coming soon
BIP Full only
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.
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
<script bip-namespace="YOUR_NAMESPACE" src="https://js.bip.marketing/v1.0.0.js"></script>
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:
// 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 ?? ''
})
});
});On the server, the /api/newsletter route creates or updates the contact in BIP with tracker:
// /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, ... }
}The same call in curl, for testing:
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"]}'Click on a button that isn't a link
// "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');
});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_IDshows the ID andwindow.BIP_LAST_EVENT_SENTshows 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.