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

# Click Tracking

> Record clicks and generate transaction IDs using the Everflow JavaScript SDK.

The `EF.click()` method records a click event and returns a Promise that resolves with the transaction ID. This transaction ID can then be used for conversion attribution.

## Basic Usage

```javascript theme={null}
EF.click({
  offer_id: 1,
  affiliate_id: 1
});
```

## Parameters

Which fields are required depends on how the click is identified — see [How a click is identified](#how-a-click-is-identified) below. All other fields are optional.

| Parameter         | Type    | Required    | Description                                                                                                                                    |
| ----------------- | ------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `offer_id`        | integer | Conditional | The offer identifier — required to record a **new** click (direct linking)                                                                     |
| `affiliate_id`    | integer | Conditional | Required to record a **new** click — unless the affiliate is supplied by a `coupon_code`, or an existing click is matched via `transaction_id` |
| `uid`             | integer | No          | Offer URL ID (extra destination URL)                                                                                                           |
| `creative_id`     | integer | No          | Creative identifier                                                                                                                            |
| `sub1` – `sub10`  | string  | No          | Affiliate sub-placement tracking values                                                                                                        |
| `adv1` – `adv10`  | string  | No          | Advertiser sub-parameter values                                                                                                                |
| `source_id`       | string  | No          | Traffic source identifier                                                                                                                      |
| `coupon_code`     | string  | Conditional | A coupon code — records a click attributed via the coupon's offer and affiliate                                                                |
| `cost`            | number  | No          | Media-buying cost to attribute to this click                                                                                                   |
| `fbclid`          | string  | No          | Facebook click ID (auto-detected from the URL if omitted)                                                                                      |
| `gclid`           | string  | No          | Google click ID (auto-detected from the URL if omitted)                                                                                        |
| `ttclid`          | string  | No          | TikTok click ID (auto-detected from the URL if omitted)                                                                                        |
| `sccid`           | string  | No          | Snapchat click ID (auto-detected from the URL if omitted)                                                                                      |
| `transaction_id`  | string  | Conditional | A 32-character transaction ID — matches an **existing** click instead of creating one (ITP workaround)                                         |
| `tracking_domain` | string  | No          | Tracking domain override (for multi-tenant setups — see [Configuration](/sdk/configuration#multi-account-tracking-tracking_domain))            |
| `parameters`      | object  | No          | Free-form custom key–value parameters                                                                                                          |
| `do_not_track`    | boolean | No          | When `true`, the call resolves immediately without recording a click                                                                           |

### How a click is identified

`EF.click()` resolves to one of three behaviors depending on which identifier you pass. Provide the fields for the mode you need:

* **New click (direct linking)** — requires **both** `offer_id` and an affiliate identity (`affiliate_id`). If either is missing, the server records the click with an error code and returns no transaction ID — the promise resolves with an empty string. This is what most recipes do.
* **Existing click (ITP workaround)** — pass a valid **32-character** `transaction_id` (typically read from `_ef_transaction_id` after a redirect tracking link). The SDK matches the click that already exists and reinforces its first-party cookie; `offer_id` and `affiliate_id` are not needed and are ignored in this mode. If the ID is missing, malformed, or not found, the call falls back to recording a new click — which then requires `offer_id`.
* **Coupon attribution** — pass `coupon_code`; the offer and affiliate are resolved from the coupon assignment.

<Note>
  The 32-character length matters: a `transaction_id` that isn't exactly 32 characters is treated as absent, and the call falls through to new-click behavior.
</Note>

<Note>
  **Coupon code takes precedence.** If a valid `coupon_code` arrives alongside `offer_id` and `affiliate_id`, the click is attributed to the **coupon's** offer and affiliate — not the passed `affiliate_id`. Only send a `coupon_code` when you intend coupon-based attribution.
</Note>

## Return Value

`EF.click()` returns a Promise that resolves with the transaction ID:

```javascript theme={null}
EF.click({
  offer_id: 1,
  affiliate_id: 1
}).then(function(transactionId) {
  console.log('Transaction ID:', transactionId);
});
```

<Note>
  The promise **always resolves and never rejects**. On success it resolves with the 32-character transaction ID; when nothing could be tracked — `do_not_track`, no valid identifier, or a server/validation error — it resolves with an **empty string** instead. This is why patterns that chain off the result (cross-site link decoration, the EF-to-EF chain) test `if (transactionId)` and supply a fallback rather than relying on `.catch()`.
</Note>

## Examples

**With sub-placements and URL parameters:**

```javascript theme={null}
EF.click({
  offer_id: EF.urlParameter('oid'),
  affiliate_id: EF.urlParameter('affid'),
  sub1: EF.urlParameter('sub1'),
  sub2: EF.urlParameter('sub2'),
  source_id: EF.urlParameter('source')
});
```

<Note>
  `EF.urlParameter()` returns `null` when the parameter is not present in the URL. The SDK skips any optional field whose value is `null` or `undefined`, so a missing URL parameter is simply omitted from the click rather than sent as an empty value.
</Note>

<Warning>
  **Parameters after a `#` in the URL are not readable.** `EF.urlParameter()` reads from the URL's query string (`?…`), so anything in the fragment — e.g. `https://example.com/#/path?oid=1&affid=2` — is invisible to it, and the click will be missing those values. This is common with hash-routed single-page apps. If your parameters live after the `#`, move them before it, or read them from `window.location.href` directly instead of `EF.urlParameter()`.
</Warning>

**With custom parameters:**

```javascript theme={null}
EF.click({
  offer_id: 1,
  affiliate_id: 1,
  parameters: {
    campaign_name: 'summer_sale',
    landing_page: 'variant_b'
  }
});
```

**All parameters:**

A reference call listing every parameter `EF.click()` accepts. In practice you only pass the ones relevant to your setup — optional fields with a `null`/`undefined` value are omitted automatically.

```javascript theme={null}
EF.click({
  // Core attribution — provide at least one of offer_id, transaction_id, or coupon_code
  offer_id: EF.urlParameter('oid'),
  affiliate_id: EF.urlParameter('affid'),
  transaction_id: EF.urlParameter('_ef_transaction_id'),
  coupon_code: EF.urlParameter('__cc'),

  // Optional attribution context
  uid: EF.urlParameter('uid'),
  creative_id: EF.urlParameter('creative_id'),
  source_id: EF.urlParameter('source_id'),

  // Affiliate sub-parameters (sub1–sub10)
  sub1: EF.urlParameter('sub1'),
  sub2: EF.urlParameter('sub2'),
  sub3: EF.urlParameter('sub3'),
  sub4: EF.urlParameter('sub4'),
  sub5: EF.urlParameter('sub5'),
  sub6: EF.urlParameter('sub6'),
  sub7: EF.urlParameter('sub7'),
  sub8: EF.urlParameter('sub8'),
  sub9: EF.urlParameter('sub9'),
  sub10: EF.urlParameter('sub10'),

  // Advertiser sub-parameters (adv1–adv10)
  adv1: EF.urlParameter('adv1'),
  adv2: EF.urlParameter('adv2'),
  adv3: EF.urlParameter('adv3'),
  adv4: EF.urlParameter('adv4'),
  adv5: EF.urlParameter('adv5'),
  adv6: EF.urlParameter('adv6'),
  adv7: EF.urlParameter('adv7'),
  adv8: EF.urlParameter('adv8'),
  adv9: EF.urlParameter('adv9'),
  adv10: EF.urlParameter('adv10'),

  // Media-buying cost
  cost: EF.urlParameter('cost'),

  // Paid-channel click IDs (auto-detected from the URL if omitted)
  fbclid: EF.urlParameter('fbclid'),
  gclid: EF.urlParameter('gclid'),
  ttclid: EF.urlParameter('ttclid'),
  sccid: EF.urlParameter('sccid'),

  // Route this click to a specific Everflow account (overrides the SDK script's domain)
  tracking_domain: 'www.your-tracking-domain.com',

  // Free-form custom query parameters
  parameters: {
    my_custom_key: 'my_custom_value'
  },

  // Behavior flag
  do_not_track: false
});
```

## ITP Workaround and First-Party Cookie Tracking

You can combine the SDK with traditional redirect tracking links to enhance attribution on browsers that restrict third-party cookies (Safari ITP, etc.). When a user lands on your owned landing page after going through a redirect link, fire `EF.click()` with the `transaction_id` extracted from the URL — the SDK will set a first-party cookie on your landing-page domain, making subsequent conversion attribution more reliable.

Configure your tracking link's destination URL to include the `transaction_id`, `offer_id`, and `affiliate_id` macros. For a destination URL like:

```
https://destination-url.com?transaction_id=af189e77650e4e908af797b61b03ac0b&oid=1&affid=5
```

fire the SDK click with the extracted values:

```javascript theme={null}
EF.click({
  offer_id: EF.urlParameter('oid'),
  affiliate_id: EF.urlParameter('affid'),
  transaction_id: EF.urlParameter('transaction_id')
});
```

The SDK recognizes the existing `transaction_id` and enhances attribution without creating a duplicate click.

## Advanced Usage

### Preventing duplicate clicks

Use `EF.getTransactionId()` to check whether a transaction already exists for the offer before firing a new click — useful when the same page may be loaded multiple times for a returning user:

```javascript theme={null}
var offerId = 3;
var previousTransactionId = EF.getTransactionId(offerId);

if (!previousTransactionId) {
  EF.click({
    offer_id: offerId,
    affiliate_id: EF.urlParameter('affid')
  });
} else {
  // The user already has a transaction for this offer — skip firing a new click
}
```

### Falling back to default values

When the URL may not always contain `offer_id` or `affiliate_id` parameters, you can supply default values rather than letting the click fail:

```javascript theme={null}
var DEFAULT_OFFER_ID = 1;
var DEFAULT_AFFILIATE_ID = 10;

var offerId = EF.urlParameter('oid') || DEFAULT_OFFER_ID;
var affiliateId = EF.urlParameter('affid') || DEFAULT_AFFILIATE_ID;

EF.click({
  offer_id: offerId,
  affiliate_id: affiliateId
});
```

<Tip>
  For fleet-wide organic fallback (applied automatically to every SDK call on the page), use [`EF.configure({ organic: {...} })`](/sdk/configuration#organic-tracking) instead of per-call defaults.
</Tip>

<a id="multiple-everflow-accounts" />

### Multi-tenant attribution (multiple Everflow accounts)

When multiple Everflow accounts fire clicks on the same page, pass `tracking_domain` per call to route each click to the correct account. See [Multi-account tracking](/sdk/configuration#multi-account-tracking-tracking_domain) for the full pattern and caveats.
