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

# Salesforce and ClickFlare Integration Guide

> Track Salesforce leads and won deals in ClickFlare: save the click ID on the lead, then send each stage from a Flow HTTP callout.

![Salesforce and ClickFlare Integration](https://mintcdn.com/clickflare/gS923ib4WFySqxSL/images/integrations/covers/salesforce.png?fit=max\&auto=format\&n=gS923ib4WFySqxSL\&q=85\&s=09adf540a38814e9cf65f0b13fa1cd52)

Salesforce is a CRM. Your forms create leads in it, your team qualifies them, converts them and closes opportunities. The revenue that matters is recorded there, often weeks after the ad click.

This guide sends those stages back to ClickFlare so you can judge ads on pipeline, not on form fills:

* **ClickFlare → Salesforce:** ClickFlare passes its click ID to your page, and your form saves it in a custom field on the lead.
* **Salesforce → ClickFlare:** when the lead or opportunity reaches the stage you choose, a flow with an HTTP Callout action sends the conversion to ClickFlare with that click ID.

Each stage arrives as its own custom conversion, so leads, qualified leads and won deals show as separate columns, and won deals can carry the opportunity amount as payout. An optional last section covers the reverse direction.

***

## At a glance

To set up Salesforce with ClickFlare:

1. Create conversions, campaign and offer.
2. Add a click ID field and save it.
3. Create a Named Credential.
4. Create the record-triggered flow.
5. Add the HTTP Callout.

Each step is explained in [Setup](#setup).

| | Salesforce + ClickFlare |
| - | - |
| **How it connects** | Record-triggered flow, HTTP Callout GET to /cf/cv |
| **What reaches ClickFlare** | Leads, qualified leads, won deals, opportunity Amount |
| **Timing** | Real time, per conversion |
| **Key parameters** | `click_id`, `ct`, `payout`, `txid`, param1 to param20 |
| **Works with** | Web-to-Lead or form tools with a hidden field |
| **Good to know** | Callouts must run on the flow's asynchronous path. |

***

## How the data flows

```text theme={null}
Ad click
  → https://trk.yourdomain.com/cf/r/CAMPAIGN?...
     (ClickFlare records the click and generates the click ID)
  → https://yourpage.com/?cf_click_id=CF_CLICK_ID
     (your form copies the click ID into a hidden field)
  → Visitor submits the form
     (Salesforce creates a lead with the click ID in a custom field)
  → Lead is qualified, converted, opportunity is Closed Won
  → Record-triggered flow: HTTP Callout
     GET https://trk.yourdomain.com/cf/cv?click_id=CF_CLICK_ID&ct=won&payout=AMOUNT&txid=OPPORTUNITY_ID
     (ClickFlare matches the conversion to the original click)
```

| Piece | Where | Value |
| - | - | - |
| **Offer URL** (in ClickFlare) | Your parameter + ClickFlare token | `cf_click_id={cf_click_id}` |
| **Custom field** (in Salesforce) | Lead, mapped to the opportunity | Holds the click ID |
| **Named Credential** (in Salesforce) | Base URL of the callout | `https://trk.yourdomain.com` |
| **HTTP Callout** (in a flow) | Path + query parameter keys | `/cf/cv`, `click_id`, `ct`, `payout`, `txid` |

***

## What you'll need

* A ClickFlare account with your **own tracking domain**, ideally with SSL. See [Tracking domains](/docs/en/settings/tracking-domains.md).
* A Salesforce org where you can create custom fields, Named Credentials and flows in Flow Builder. Which editions include HTTP callouts from Flow isn't covered here: check with your Salesforce admin or Salesforce's documentation for your edition.
* A form that creates leads in Salesforce, such as Web-to-Lead or a form tool connected to Salesforce, and that can include a hidden field.

***

## Setup

**1. Set up your own tracking domain**

Add a custom tracking domain, for example `trk.yourdomain.com`, under [Tracking domains](/docs/en/settings/tracking-domains.md). The Named Credential points at it, so changing it later means updating Salesforce too.

**2. Create a custom conversion for each stage**

In ClickFlare, go to **Settings → Custom Conversions** and create one per stage:

| Stage in Salesforce | `ct` value |
| - | - |
| Lead created | `lead` |
| Lead qualified | `qualified` |
| Opportunity Closed Won | `won` |

The parameter of each custom conversion is the `ct` value the flow sends. It must match exactly. See [Custom conversions](/docs/en/settings/custom-conversions.md).

**3. Create the campaign and add your page as the offer**

Go to **Campaigns → New Campaign** and pick your traffic source and tracking domain. See [Creating a campaign](/docs/en/campaigns/creating-a-campaign-in-click-flare.md).

In the campaign path, create a new offer inline with the page that holds your form:

```text theme={null}
https://yourpage.com/?cf_click_id={cf_click_id}
```

Keep the braces. Set the offer payout to **Auto** so ClickFlare uses the payout Salesforce sends. Save the campaign and copy the campaign URL for your ads.

**4. Add a click ID field to the lead**

In Salesforce Setup, create a custom text field on the **Lead** object, for example **ClickFlare Click ID**.

If you track opportunities, create the same field on the **Opportunity** (and **Contact** if useful) and map the lead field to it in the lead field mapping, so the click ID follows the record when the lead is converted. Without it, the opportunity has no click ID to send.

**5. Save the click ID from your form**

Your form needs a hidden field that takes `cf_click_id` from the page URL and writes it into the custom field.

* **Web-to-Lead:** include the custom field when you generate the form HTML, change that input to a hidden one, and fill its value from the `cf_click_id` URL parameter with a short script on the page. The generated HTML names custom fields by their field ID, so check it rather than guessing the name.
* **A form tool connected to Salesforce:** add a hidden field that reads the URL parameter, and map it to the custom lead field.

Test with one lead before you go further.

**6. Create a Named Credential for your tracking domain**

In Setup, create a Named Credential whose URL is `https://trk.yourdomain.com`. The HTTP callout uses it as its base URL.

ClickFlare's postback needs no authentication. How you set that up depends on whether your org uses legacy Named Credentials or the newer type with an External Credential, so follow Salesforce's steps for your org.

**7. Create the record-triggered flow**

In Flow Builder, create a record-triggered flow:

* **Object:** Opportunity. **Condition:** **Stage** equals **Closed Won**, only when the record is updated to meet the condition.
* For the `qualified` stage, build a second flow on **Lead** with your qualified status as the condition.

Salesforce doesn't allow a callout on a record-triggered flow's immediate path. Add the callout on an asynchronous path. Flow Builder warns you if you put it in the wrong place.

**8. Add the HTTP Callout**

On the asynchronous path, add an **Action** and click **Create HTTP Callout**:

1. Name the external service and select your **Named Credential**. Click **Next**.
2. Set **Method** to **GET** and **Set URL Path** to `/cf/cv`.
3. Add query parameter keys `click_id`, `ct`, `payout` and `txid`.
4. For the sample response, enter an example instead of connecting, since ClickFlare's postback doesn't return data you need. Save.

Back in the action, set the values:

| Key | Value |
| - | - |
| `click_id` | The record's **ClickFlare Click ID** field |
| `ct` | `won` |
| `payout` | The opportunity **Amount** |
| `txid` | The opportunity record ID |

Activate the flow. Repeat for each stage with its own `ct`.

***

## Option: JSON POST callout

HTTP callouts can also send POST requests. Instead of query parameter keys, you give a sample request body, and Flow Builder creates a data structure from it that you fill with an **Assignment** before the callout. Use this sample:

```json theme={null}
{"cf_click_id": "abc", "ct": "won", "payout": 1, "txid": "OPPORTUNITY_ID"}
```

Then assign the record's click ID field to `cf_click_id`, `won` to `ct`, the **Amount** to `payout` and the opportunity record ID to `txid`. ClickFlare accepts this JSON at the same `/cf/cv` endpoint.

Both callouts carry the same values, `txid` included. The GET callout is simpler to build. Use POST when your org's policy requires request bodies over query strings.

***

## Stages, payout and duplicates

**One stage, one `ct`.** A conversion with a different `ct` on the same click is added as a new conversion. A lead that qualifies and later closes shows once under `lead`, once under `qualified` and once under `won`.

**Payout from the amount.** Map `payout` to the opportunity **Amount** on the `won` callout. Send `0`, or leave `payout` out, on earlier stages so revenue isn't counted twice.

**Use `txid` for repeat business.** With the opportunity ID as `txid`, a second closed opportunity on the same click counts as its own conversion. If a flow fires twice for the same opportunity, the same `txid` means ClickFlare keeps one conversion.

**Choose what the ad platform sees.** Each custom conversion is mapped to the traffic source postback separately, so you can send only `qualified` or `won` to the ad platform to optimize on.

**Bulk updates.** A record-triggered flow runs once per record. A mass update of opportunities to Closed Won fires one callout per record, which is what you want, but avoid test mass updates on live data.

***

## Verify the setup

**1. Click through the campaign**

Open your ClickFlare campaign URL. The page URL should contain `cf_click_id=` and a real click ID.

**2. Submit the form**

Check that the new lead has the click ID in the custom field.

**3. Run the flow**

Move the record to the stage, or use **Debug** in Flow Builder on that record and check the run for errors.

**4. Check ClickFlare**

In **Logs → Event Logs**, the conversion should appear with your `ct`, payout and `txid`. A conversion only registers when `click_id` holds a real ClickFlare click ID.

To test the ClickFlare side alone, send the postback by hand with a click ID from your test click:

```bash theme={null}
curl 'https://trk.yourdomain.com/cf/cv?click_id=CF_CLICK_ID&ct=won&payout=1&txid=test-1'
```

***

## Send ClickFlare conversions to Salesforce (optional)

To go the other way, for example to update a Salesforce record when ClickFlare records a sale from your store, use the [Custom Webhook integration](/docs/en/integrations/custom-webhook-integration.md). Go to **Integrations → Conversion API → New integration**, choose **Webhooks**, map the event, choose **POST** and put macros such as `{cf_click_id}` and `{payout}` in the body.

Salesforce has to find the record by the click ID before it can update it. A relay such as [Zapier](/docs/en/integrations/zapier-click-flare-integration-guide.md), [Make](/docs/en/integrations/make-click-flare-integration-guide.md) or [n8n](/docs/en/integrations/n8n-click-flare-integration-guide.md) can receive the webhook, search for the lead by the click ID field and update it, without code in your org.

***

## Troubleshooting

> [accordion] The click ID field is empty on new leads
>
> * The page URL has `{cf_click_id}` as text, or no parameter at all. Traffic must come through the ClickFlare campaign URL, and a lander's CTA must use the ClickFlare click URL.
> * The hidden input's name doesn't match the custom field's ID in the Web-to-Lead HTML.
> * The script that copies the URL parameter runs after the form is submitted, or not at all.
> * The campaign uses direct tracking, so the click ID isn't in the URL. See [Direct tracking](/docs/en/tracking/direct-tracking-clickflare.md).

> [accordion] Opportunities have no click ID
>
> The lead field isn't mapped to the opportunity field. Map it, then convert a new test lead. Opportunities converted before the mapping won't have it.

> [accordion] The flow fails at the callout
>
> * The callout is on the immediate path. Move it to the asynchronous path.
> * The Named Credential URL isn't your tracking domain, or includes the path. The path `/cf/cv` goes in the callout, not the credential.
> * The flow has no fault path, so a timeout fails the whole interview. Add a fault path that records the error.

> [accordion] The callout ran but no conversion shows
>
> * GET uses `click_id`, JSON uses `cf_click_id`. Check you used the right one.
> * The `ct` value doesn't match a custom conversion's parameter exactly.
>
> See [Troubleshooting S2S postbacks](/docs/en/tracking/troubleshooting-s2s-postback-url-in-clickflare.md).

***

## FAQ

> [accordion] Does ClickFlare integrate with Salesforce?
>
> Yes. Your form saves the ClickFlare click ID on the lead, and a record-triggered flow's HTTP Callout sends it to ClickFlare's postback when the lead qualifies or the opportunity is Closed Won.

> [accordion] Can I track the form fill without a flow?
>
> Yes. Place the [conversion tracking pixel](/docs/en/settings/conversion-tracking-pixel.md) on the thank-you page with `ct=lead` and use flows only for later stages.

> [accordion] Can I avoid flows altogether?
>
> Yes. Export closed opportunities with their click IDs and import them with [Conversion Upload](/docs/en/settings/conversion-upload.md). It isn't real time, but needs no setup in Salesforce beyond the click ID field.

> [accordion] Can I send more fields, like the product or the sales rep?
>
> Yes. Add `param1` to `param20` as extra query parameter keys and map them to fields. ClickFlare stores them with the conversion.

> [accordion] Does the currency matter?
>
> `payout` is a plain number. Send it in the currency your ClickFlare reports use, or convert it in the flow first.

***

## Related

> [card] [Custom conversions](/docs/en/settings/custom-conversions.md)
>
> One ct per stage

> [card] [Postback parameters](/docs/en/tracking/click-flare-parameters-in-postback-urls.md)
>
> click\_id, txid, ct

> [card] [HubSpot](/docs/en/integrations/hubspot-click-flare-integration-guide.md)
>
> The same flow in HubSpot


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.