# Deals

Count HubSpot closed-won deals as sales in campaign results and ad rules, or send them to your ad platforms as purchases.

Two settings read the portal's closed-won deals. Each works on its own, and you can turn on both.

| | `useDealsAsResults` | `reportDeals` |
|---|---|---|
| What it does | Counts each deal as a sale with its amount, on the campaign that brought the contact | Sends each new deal as a `Purchase` to your ad platforms |
| Who uses it | Zernio [campaign results](/guides/campaign-results) and [ad rules](/guides/ad-rules) | Meta, Google and your other [event destinations](/conversions/create-event-destination) |
| Earlier deals | The last 90 days are filled in | None, only deals won after you turn it on |
| Edited or lost deal | Updated, or stops counting | Sent once, never changed |

## Before you start

Both settings need deal access, which the portal grants when it installs the app. Without it, turning either one on returns `400`. To grant it:

1. If the deals option shows locked when connecting, a HubSpot admin turns it on first: **Settings > Integrations > Connected Apps > Approved apps > Zernio > Manage access > Data Permissions**, then enables **View properties and other details about deals** and saves.
2. Reconnect HubSpot and approve deals on the consent screen.

Portals that approved the app before deals existed in Zernio start without deal access.

## Use closed deals in ad results

Turn on `useDealsAsResults` and each closed-won deal counts as one sale, with its amount as revenue, on the ad campaign that brought its contact:

```bash
curl -X PATCH "https://zernio.com/api/v1/accounts/ACCOUNT_ID/hubspot-settings" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "useDealsAsResults": true }'
```

The sales and revenue show in campaign results and in ad rules, so formulas such as cost per sale or %CAC use them. Nothing is sent to the ad platforms.

Turning it on also fills in the deals won in the last 90 days, starting at the next hourly check.

## What counts

Each matched deal adds to two result metrics, which [formulas](/guides/campaign-results#compute-metrics-with-formulas) and ad rules read by key:

| Metric | Per deal |
|---|---|
| `sales` | 1 |
| `revenue` | The deal amount, in the ad account's currency |

A deal in another currency is converted at that day's ECB rate. Without a rate for the currency, or without an amount, the deal adds a sale with no revenue.

With spend from the ad platform, that gives cost per sale (`spend / sales`), %CAC (`spend / revenue * 100`) or ROAS (`revenue / spend`).

Leads, qualified leads, other deal stages and custom HubSpot properties do not come from HubSpot. Send leads with [`POST /v1/events`](/guides/campaign-results#or-send-each-sale-as-an-event).

## Find the campaign of a deal

Zernio reads the deal's first contact and uses HubSpot's own attribution of that contact:

1. Its latest visit from a paid ad, when HubSpot names the campaign.
2. Otherwise its first visit from a paid ad, with the campaign or UTM tags of its first page.

That value is matched, as a campaign name or a `utm_campaign` tag, to the campaigns of the ad accounts the HubSpot profile can see.

A deal with no paid visit, or whose campaign matches none or several, counts on no campaign.

For paid search, HubSpot keeps the campaign in its first drill-down and the keyword in its second. For paid social, the campaign is in the second drill-down.

## Report closed-won deals

Turn on `reportDeals` and every deal that becomes closed won goes to the profile's [event destinations](/conversions/create-event-destination) as a `Purchase` event, so your ad platforms see real revenue:

```bash
curl -X PATCH "https://zernio.com/api/v1/accounts/ACCOUNT_ID/hubspot-settings" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reportDeals": true }'
```

| Purchase field | From the deal |
|----------------|---------------|
| `value`, `currency` | Deal amount and currency, or the portal's company currency |
| `eventTime` | Close date |
| `eventId` | `hubspot_deal_{portalId}_{dealId}`, so a platform never counts it twice |
| `user` | The deal's first contact: email, phone, name and address |

## Turn them on from the dashboard

On **Connections**, open the HubSpot account's menu and click **Settings**. Both deal switches are there, next to contact sync and message logging. They stay off until the portal grants deal access.

## How it behaves

- Deals are checked once an hour. A won deal shows in results, or reaches the ad platforms, within about an hour.
- The 90-day fill reads up to 2,000 deals per hour, so a large portal takes a few hours. Those older deals are never sent to the ad platforms.
- With `useDealsAsResults` on, an edited amount or close date replaces the earlier sale, and a deal moved out of closed won stops counting.
- With `reportDeals` on, each deal goes to the ad platforms once. They never see a later change or a lost deal.

## If it fails

| Error | Cause | Fix |
|-------|-------|-----|
| `400` with `param: "useDealsAsResults"` or `"reportDeals"` | The portal did not grant deal access | Grant it as in [Before you start](#before-you-start), then turn the setting on again. |
| Deals count, but on no campaign | The contact had no paid visit, or the ad account is on a profile the HubSpot profile cannot see | Connect the ad account on the same profile as HubSpot. |
| Switches greyed out in the dashboard | Same as the first row | Same as the first row. |

## Related

- [Update HubSpot settings](/accounts/update-hub-spot-settings)
- [Campaign results](/guides/campaign-results)
- [Ad rules](/guides/ad-rules)
- [Create event destination](/conversions/create-event-destination)