# Conversion tracking for developers and AI assistants

ChatQuote’s chat widget reports three moments from each visitor’s chat to your website and to the ad platforms your admin connects. This page is for whoever sets up the site: a developer or an AI coding assistant.

## The three events

- First message (`first_message`): The visitor sends their first message.
- Contact details given (`contact_provided`): The visitor gives a valid email or phone number.
- Chat completed (`lead_completed`): The assistant wraps up a quote chat, or it reaches its message limit. A chat that only asks questions never records it.

Each event has an ID, so a platform that gets it both ways counts it once. Google Analytics can’t, so it takes one way only.

A chat the visitor abandons is completed 2 hours later, and only ChatQuote’s server can report it.

## Two ways to send them

- Your website’s tag: The platform’s tag already on your site reports each event, for chats in your website widget. Shares the event and its ID.
- ChatQuote’s server: ChatQuote reports each event directly, including chats on your shareable link and abandoned chats. Also shares the visitor’s email and phone, hashed so nobody can read them, the ad click, the page and the browser.

The conversation itself is never shared.

Your ChatQuote admin chooses the way for each platform, under Configure assistant › Conversion tracking.

## Install the widget

Add this script to every page, before the closing body tag. Your admin copies it with your organisation’s key from Configure assistant › Test & install.

```html
<script src="https://chatquote.app/widget.js" data-chatquote-key="<your-public-key>" async></script>
```

## What your page receives

Your website receives each chat event once the widget is installed. Use the events in Google Tag Manager or your own code.

- `chatquote:<event>`: Fired on window for each event, with `event.detail = { event, eventId }`.
- `{ event: "chatquote_<event>", chatquote_event_id: "<id>" }`: Pushed to window.dataLayer, when your page has one.
- `ChatQuote.on(event, callback)`: Calls your function with `{ event, eventId }`. Available once the widget has loaded.

Pass the event ID to your tags as their transaction ID or event ID, so a platform that also gets the event from ChatQuote’s server counts it once.

### Calls on your own tags

When a platform sends from your website’s tag, the widget calls that platform’s tag on your page with the event’s ID, so a copy from ChatQuote’s server counts once.

The widget never loads a tag: the platform’s base tag must already be loaded and initialised on every page. Don’t add your own calls for these events, or each one counts twice.

#### Google Ads

```js
// First message
gtag("event", "conversion", { send_to: "<conversion-id>/<conversion-label>", transaction_id: "<event-id>" });

// Contact details given
gtag("event", "conversion", { send_to: "<conversion-id>/<conversion-label>", transaction_id: "<event-id>" });

// Chat completed
gtag("event", "conversion", { send_to: "<conversion-id>/<conversion-label>", transaction_id: "<event-id>" });
```

#### Google Analytics 4

```js
// First message
gtag("event", "chatquote_first_message", { send_to: "<measurement-id>" });

// Contact details given
gtag("event", "generate_lead", { send_to: "<measurement-id>" });

// Chat completed
gtag("event", "chatquote_lead_completed", { send_to: "<measurement-id>" });
```

#### Meta

```js
// First message
fbq("trackSingle", "<pixel-id>", "Contact", {}, { eventID: "<event-id>" });

// Contact details given
fbq("trackSingle", "<pixel-id>", "Lead", {}, { eventID: "<event-id>" });

// Chat completed
fbq("trackSingleCustom", "<pixel-id>", "ChatQuoteLeadCompleted", {}, { eventID: "<event-id>" });
```

#### ChatGPT ads (OpenAI)

```js
// First message
oaiq("measure", "custom", { type: "custom" }, { event_id: "<event-id>", custom_event_name: "chatquote_first_message" });

// Contact details given
oaiq("measure", "lead_created", { type: "customer_action" }, { event_id: "<event-id>" });

// Chat completed
oaiq("measure", "custom", { type: "custom" }, { event_id: "<event-id>", custom_event_name: "chatquote_lead_completed" });
```

## Set up each platform

Your admin connects each platform in ChatQuote. These are the values each one needs and where to find them.

### Google Ads

See which campaigns and keywords bring you leads, and let Smart Bidding find more.

On your page: the Google tag (gtag.js), configured with your AW- conversion ID.

Google tag on your site? Start with it. Add ChatQuote’s server to also count your shareable link.

#### Conversion ID

Identifies your Google Ads account to your website’s Google tag.

1. Go to Goals › Conversions › Summary and open any conversion action.
2. Under Tag setup, select Use Google Tag Manager and copy the Conversion ID.

[Open Conversions in Google Ads](https://ads.google.com/aw/conversions)

#### How to create conversion actions

Create one conversion action for each event you want to count.

1. Go to Goals › Conversions › Summary and select + Create conversion action.
2. Under Conversions on a website, enter your domain and select Scan.
3. Untick Conversions from phone calls, then select Save and continue.
4. Choose Contact, Submit lead form or Request quote as the category. Select See all if yours isn’t shown.
5. Select + Create conversion › Manually with code, then open Conversion settings.
6. Under Action optimisation, we recommend Secondary for now: a Primary action changes your campaigns’ bidding straight away.
7. Under Value, choose Use the same value for each conversion and enter what a lead is worth to you.
8. Select Done, add your other events with Add another category, then Save and continue › Finish.

A new action can take a few hours to accept events.

[Open Conversions in Google Ads](https://ads.google.com/aw/conversions)

#### Conversion label

Tells your website’s Google tag which conversion action this event counts as.

1. Open the event’s conversion action in Goals › Conversions › Summary, or stay on the last screen after creating it.
2. Under Tag setup, select Use Google Tag Manager and copy the Conversion label.

[Open Conversions in Google Ads](https://ads.google.com/aw/conversions)

#### Conversion actions for ChatQuote’s server alone

Create one conversion action for each event you want to count.

1. Go to Goals › Conversions › Summary and select + Create conversion action.
2. Tick Conversions offline, then select Add data source › Continue.
3. Choose Skip this step and set up a data source later, then Done › Continue.
4. Choose a category, then Save and continue › Agree and finish.

A new action can take a few hours to accept events.

[Open Conversions in Google Ads](https://ads.google.com/aw/conversions)

#### Customer ID

The Google Ads account that receives the conversions.

1. Select your profile picture at the top right of Google Ads.
2. Copy the 10-digit customer ID under your account name.

[Open Google Ads](https://ads.google.com/)

#### Manager account ID (optional)

Only if you added ChatQuote’s service account to a manager account instead.

1. Enter that manager account’s 10-digit customer ID.

[Open Google Ads](https://ads.google.com/)

#### Conversion action ID

Tells ChatQuote’s server which conversion action this event counts as.

1. Open the event’s conversion action in Goals › Conversions › Summary.
2. Copy the ctId number from the page’s address.

[Open Conversions in Google Ads](https://ads.google.com/aw/conversions)

#### Enhanced conversions

Lets Google Ads match chats to ad clicks by email and phone.

1. Go to Goals › Settings and expand Customer data use.
2. Tick Turn on enhanced conversions, select Agree and save, and accept the customer data terms.

[Open Goals settings in Google Ads](https://ads.google.com/aw/conversions/customersettings)

#### Check it works

1. Open Tag Assistant and connect your website.
2. Chat with your assistant: each conversion shows in Tag Assistant.
3. Google Ads can say No tag found even when your tag works: Tag Assistant shows what your site really sends.
4. Google Ads counts only chats that came from an ad click, and can take a day to report them.

[Open Tag Assistant](https://tagassistant.google.com/)

### Google Analytics 4

See chats and leads alongside your website’s analytics, and count them as key events.

On your page: the Google tag (gtag.js), configured with your G- measurement ID.

Google Analytics can’t count a chat once if it gets it both ways. Your website’s tag is simplest.

- First message: Sent as `chatquote_first_message`
- Contact details given: Sent as `generate_lead`
- Chat completed: Sent as `chatquote_lead_completed`

#### Measurement ID

Identifies the Google Analytics property that receives the events.

1. Go to Admin › Data streams and open your web stream.
2. Copy the Measurement ID. It starts with G-.

[Open Data streams in Google Analytics](https://analytics.google.com/analytics/web/#/?pagename=admin-streams)

#### Measurement Protocol API secret

Lets ChatQuote’s server send events to this property.

1. In your web stream, open Measurement Protocol API secrets.
2. Accept the acknowledgement if asked, select Create, then copy the secret value.

[Open Data streams in Google Analytics](https://analytics.google.com/analytics/web/#/?pagename=admin-streams)

#### Check it works

1. In Google Analytics, open Reports › Realtime.
2. Chat with your assistant on your site: the events show within a minute.

[Open Google Analytics](https://analytics.google.com/)

#### Key event

To count it as a conversion, mark `generate_lead` as a key event in Google Analytics.

Google Analytics counts an event as a conversion only once it’s a key event.

1. Go to Admin › Data display › Events and select + Create event.
2. Enter `generate_lead`, turn on Mark as key event, choose Create with code and select Create.
3. Under Default key event value, choose Don’t set a default key event value, or enter your own currency and value.

If Google Ads imports your key events, don’t import `generate_lead` while ChatQuote sends to Google Ads too: each chat would count twice.

[Open Events in Google Analytics](https://analytics.google.com/analytics/web/#/?pagename=admin-events)

### Meta

See which Facebook and Instagram ads bring you leads, and let Meta find more people like them.

On your page: the Meta Pixel, initialised with your pixel ID.

Recommended: both. Meta counts each chat once.

- First message: Sent as `Contact`
- Contact details given: Sent as `Lead`
- Chat completed: Sent as `ChatQuoteLeadCompleted`

#### Pixel ID

Identifies the Meta Pixel (dataset) that receives the events.

1. In Events Manager, open Data sources or Datasets.
2. Select your pixel and copy the number next to its name.

[Open Events Manager](https://business.facebook.com/events_manager2/list)

#### Conversions API access token

Lets ChatQuote’s server send events to your pixel.

1. In Events Manager, select your pixel and open Settings.
2. Under Conversions API, select Generate access token and copy it. This needs developer access to your business.

[Open Events Manager](https://business.facebook.com/events_manager2/list)

#### Test event code (optional)

Only used by Send test event, so the test appears in Test events.

1. In Events Manager, select your pixel and open Test events.
2. Copy the code shown for server events, such as TEST12345.

[Open Events Manager](https://business.facebook.com/events_manager2/list)

#### Check it works

1. In Events Manager, select your pixel and open Test events.
2. Enter your website’s address, select Open website and chat: the events show as they happen.

[Open Events Manager](https://business.facebook.com/events_manager2/list)

### ChatGPT ads (OpenAI)

See which ChatGPT ads bring you leads.

On your page: the OpenAI pixel, initialised with your pixel ID.

Recommended: both. ChatGPT ads counts each chat once.

- First message: Sent as `chatquote_first_message`
- Contact details given: Sent as `lead_created`
- Chat completed: Sent as `chatquote_lead_completed`

ChatGPT ads optimises campaigns only on `lead_created`, sent for Contact details given. Campaigns that already count it will count these chats too.

#### Pixel ID

Identifies the ChatGPT ads pixel that receives the events.

1. In OpenAI Ads Manager, open Conversions in the left menu.
2. Copy the Pixel ID shown under your data source’s name, or create a data source first.

[Open Conversions in OpenAI Ads Manager](https://ads.openai.com/settings/conversions)

#### Conversions API key

Lets ChatQuote’s server send events to your pixel.

1. On the Conversions page, select the key icon at the top right, then Create new key.
2. Copy the whole key: it starts with sk-svc.
3. Save it in ChatQuote, then select Send test event under Check it works to check the key.

An API key from Settings won’t work.

[Open Conversions in OpenAI Ads Manager](https://ads.openai.com/settings/conversions)

#### Check it works

1. In OpenAI Ads Manager, open Conversions › Event Stream and select Start polling.
2. Chat with your assistant on your site: each event shows within seconds, from the pixel and, with ChatQuote’s server on, from the server too.

[Open Conversions in OpenAI Ads Manager](https://ads.openai.com/settings/conversions)

## Google Tag Manager

Each event is pushed to your page’s data layer, so Tag Manager can fire any tag on it.

1. Variables › New › Data Layer Variable. Set Data Layer Variable Name to: `chatquote_event_id`
2. Triggers › New › Custom Event, one per event. Set Event name to: `chatquote_first_message`, `chatquote_contact_provided`, `chatquote_lead_completed`
3. In your conversion tag, add the trigger under Triggering, and select the event ID variable as its Transaction ID or Event ID.
4. Select Preview, connect your website and chat with your assistant: each event shows in Tag Assistant.
5. Select Submit, then Publish.

- Google Ads Conversion Tracking tag: your container also needs a Conversion Linker tag.
- Meta Pixel template: put the event ID variable in More settings › Event ID.
- For a platform you send through Tag Manager, keep its website tag off in ChatQuote, or each event is sent twice.

## JavaScript

Any script on your page can listen for these events, before or after the widget loads.

```js
window.addEventListener("chatquote:contact_provided", (event) => {
  const { eventId } = event.detail;
  // Your code: for example, report the conversion with its eventId
});

// Or, once the widget has loaded:
// window.ChatQuote.on("contact_provided", ({ event, eventId }) => {
//   // Your code: for example, report the conversion with its eventId
// });
```

## Consent

If your admin turns on Wait for the visitor’s consent in ChatQuote, nothing is tracked until your site calls `ChatQuote.setConsent(true)`. This code passes the visitor’s answer on.

```js
// Tells the widget whether the visitor accepts ad tracking, before or after it loads
function chatQuoteConsent(granted) {
  if (window.ChatQuote && window.ChatQuote.setConsent) window.ChatQuote.setConsent(granted);
  else window.ChatQuote = Object.assign(window.ChatQuote || {}, { consent: granted });
}

// For example, once the visitor accepts:
// chatQuoteConsent(true);
```

- When the visitor accepts ad tracking, call `chatQuoteConsent(true)`.
- When they decline or withdraw it, call `chatQuoteConsent(false)`.
- `ChatQuote.setConsent(true | false)`: Pass true when the visitor accepts ad tracking and false when they decline. Call it again if they change their mind.
- `window.ChatQuote = { consent: true }`: The same, set before the widget loads. The code above handles both.

Your Tag Manager and scripts still receive the events: they hold no personal data.

You’re responsible for getting your visitors’ consent where the law requires it.

## Check it works

Confirm the events reach your page.

1. Open your website in a desktop browser, then its developer console (F12, or Option + ⌘ + J in Chrome on a Mac).
2. Paste this code and press Enter:

```js
["chatquote:first_message", "chatquote:contact_provided", "chatquote:lead_completed"].forEach((name) =>
  window.addEventListener(name, (event) => console.log(name, event.detail)),
);
```

Chat with your assistant: each event prints as it happens.

## Troubleshooting

- Nothing reaches the page: check the assistant is live in ChatQuote. While it’s off, the widget reports nothing.
- Events reach the page but no platform: if your admin turned on Wait for the visitor’s consent, call `ChatQuote.setConsent(true)` once the visitor accepts.
- One platform gets nothing: its base tag must be loaded and initialised before the chat. For the Meta Pixel, `fbq.getState().pixels` lists your pixel ID once it is.
- A platform counts each chat twice: send each event one way only, from ChatQuote or from your own Tag Manager tags.
- If Google Ads imports your key events, don’t import `generate_lead` while ChatQuote sends to Google Ads too: each chat would count twice.
- Google Ads can say No tag found even when your tag works: Tag Assistant shows what your site really sends.
- Google Ads counts only chats that came from an ad click, and can take a day to report them.
