# Embed the Dashboard & Auto-Login Promoters
Source: https://docs.firstpromoter.com/advanced/embed-dashboard-login
Embed the full promoter dashboard inside your own app as an iframe and automatically sign promoters in — no separate URL, no credentials.
FirstPromoter lets you embed the complete promoter dashboard inside your own app and automatically log the visiting promoter in, so they never have to leave your app or enter credentials manually. Your backend requests a short-lived access token for the promoter, and you pass that token to the iframe.
**Requirements**
* A custom domain configured on your FirstPromoter account
* Business plan or higher
* Server-side access to make authenticated API requests — the access token must always be generated on your backend. Never call this endpoint or expose your API key from the browser.
## How it works
They're already authenticated in your product, and you know their FirstPromoter promoter ID (or the `cust_id` you assigned them).
Your server calls the `iframe_login` endpoint with that promoter's ID. FirstPromoter returns a bearer token scoped to that promoter and your account.
Pass the token as the `tk` query parameter on the iframe `src`. FirstPromoter validates it and loads the dashboard already signed in.
## Step 1 — Get your API credentials
Go to **Settings → Integrations → Manage API Keys** and note two values:
* **Account ID** — identifies your FirstPromoter account
* **API Key** — used to authenticate the server-side request (use a v2 key)
Keep both server-side only.
## Step 2 — Generate an access token
From your backend, make a `POST` request to the iframe login endpoint:
```
POST https://v2.firstpromoter.com/api/v2/promoters/iframe_login
```
The FirstPromoter promoter ID. Provide this or `cust_id`.
The external customer ID you assigned this promoter when they signed up. Provide this or `promoter_id`.
`Bearer {your_api_key}`
`{your_account_id}`
The request body is empty. On success you get back a bearer token:
Short-lived bearer token for this promoter, scoped to your account.
Token lifetime in seconds. Defaults to `86400` (24 hours).
```json theme={null}
{
"access_token": "xxxxxxxxxxxxxxx",
"expires_in": 86400
}
```
Generate a fresh token on every page load — don't cache or reuse tokens across sessions or share one token between promoters.
## Step 3 — Find the promoter's ID
You need the FirstPromoter `promoter_id` (not your own internal user ID) — or the `cust_id` you gave them. Get it from:
* The API response when the promoter was originally created
* The [Promoters API](/api-reference-v2/api-admin/promoters/get-available-promoters) filtered by `cust_id`
* The `promoter_accepted` webhook payload
## Step 4 — Embed the iframe
Use the access token as the `tk` query parameter on the iframe `src`:
```html theme={null}
```
`allow="clipboard-write"` is required for the copy-to-clipboard buttons inside the dashboard (referral links, promo codes, etc.).
### Targeting a specific campaign
If a promoter belongs to more than one campaign and you want the dashboard to open directly on a particular one, append `campaign_id`:
```
/iframe?tk={access_token}&campaign_id={campaign_id}
```
You can also pass a comma-separated list — the dashboard opens on the first matching campaign the promoter belongs to:
```
/iframe?tk={access_token}&campaign_id={id1},{id2}
```
## Code examples
```js Node.js (Express) theme={null}
const express = require("express");
const app = express();
app.get("/dashboard", async (req, res) => {
const promoterId = req.user.firstpromoterPromoterId; // your stored promoter ID
const response = await fetch(
`https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=${promoterId}`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FP_API_KEY}`,
"Account-Id": process.env.FP_ACCOUNT_ID,
},
}
);
const { access_token } = await response.json();
res.render("dashboard", { accessToken: access_token });
});
```
```php PHP theme={null}
firstpromoter_promoter_id;
$ch = curl_init(
"https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=" . urlencode($promoterId)
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $_ENV["FP_API_KEY"],
"Account-Id: " . $_ENV["FP_ACCOUNT_ID"],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
$accessToken = $response["access_token"];
?>
```
```sh cURL theme={null}
curl --request POST \
--url 'https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=12345' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Account-Id: YOUR_ACCOUNT_ID'
```
Then render the iframe once you have the token:
```jsx React theme={null}
import { useEffect, useState } from "react";
export function PromoterDashboard() {
const [token, setToken] = useState(null);
useEffect(() => {
fetch("/api/fp-token")
.then((res) => res.json())
.then((data) => setToken(data.token));
}, []);
if (!token) return Loading dashboard…
;
return (
);
}
```
```vue Vue theme={null}
Loading dashboard…
```
```html Vanilla JS theme={null}
```
`/api/fp-token` above is your own protected backend route that performs the Step 2 request and returns `{ token: access_token }` — the same pattern as the Node.js example.
## Security considerations
* **Never call `iframe_login` from the browser.** Your API key must stay server-side behind a route that requires the visitor to already be authenticated in your app.
* **Only embed the iframe on authenticated, non-public pages.** The token grants full dashboard access for that promoter.
* **Generate a fresh token on every page load.** Tokens expire after `expires_in` seconds (24 hours by default) — don't cache or share them between users.
## Related
* [Log promoters out of the embedded dashboard](/advanced/embed-dashboard-logout)
* [Promoters API reference](/api-reference-v2/api-admin/promoters/get-available-promoters)
# Log Promoters Out of the Embedded Dashboard
Source: https://docs.firstpromoter.com/advanced/embed-dashboard-logout
End a specific promoter's embedded dashboard session from your backend, or let promoters sign out from inside the iframe itself.
If you [embed the promoter dashboard and auto-login promoters](/advanced/embed-dashboard-login), you'll also want a way to end that session — either because the promoter logged out of your app, or because you want to immediately cut off a specific promoter's access instead of waiting for their token to expire.
There are two independent ways a promoter's embedded session ends:
The promoter clicks **Log out** inside the embedded dashboard itself. No API call needed — this happens automatically.
Your backend calls `iframe_logout` for a specific promoter, revoking their access immediately — for example when the corresponding user logs out of your app.
## Self-service logout
When a promoter clicks **Log out** from the account menu inside the embedded dashboard, FirstPromoter revokes **every active session that promoter currently has under your account** — not just the tab or page they clicked logout from — and returns them to a signed-out state within the iframe. This requires no setup and no API call on your side — it's built into the dashboard.
Because every session is revoked, this also signs the promoter out of any other tab where you've embedded their dashboard. If your app issues a fresh token on every page load (as recommended in the [login guide](/advanced/embed-dashboard-login)), reloading the page after this will silently log the promoter back in. If you want the logout to stick, pair it with the targeted logout below, triggered from your own app's logout flow.
## Targeted logout (from your backend)
Call this whenever you want to end a **specific promoter's** embedded session from your side — typically when that user logs out of your app, or when you need to immediately revoke their access (e.g. they were suspended). It targets one promoter at a time by `promoter_id` or `cust_id`, so it never affects any other promoter's session.
```
POST https://v2.firstpromoter.com/api/v2/promoters/iframe_logout
```
The FirstPromoter promoter ID whose session to end. Provide this or `cust_id`.
The external customer ID you assigned this promoter. Provide this or `promoter_id`.
Optional. The `access_token` value returned by a specific [`iframe_login`](/advanced/embed-dashboard-login) call. Pass this to revoke **only that one session** instead of every active session — see [Ending a single session](#ending-a-single-session) below. If provided, this takes priority over `promoter_id`/`cust_id`; if left blank, the request falls back to revoking all of the promoter's sessions.
`Bearer {your_api_key}`
`{your_account_id}`
The request body is empty. A `200 OK` with no body confirms the session was revoked; a `404` means no promoter matched the `promoter_id`/`cust_id` you passed (or, when using `session_token`, that the token doesn't exist, is already revoked, belongs to a different account, or doesn't belong to a promoter).
Without `session_token`, this revokes **every currently active access token that promoter has under your account** — including any not-yet-expired tokens from earlier `iframe_login` calls (e.g. from other tabs or an earlier page load). It does not touch that same person's sessions under any other FirstPromoter account they may also be a promoter for.
### Ending a single session
If you embed the dashboard in multiple places at once for the same promoter (e.g. several open tabs, or a mobile and web session) and only want to end one of them, pass `session_token` instead of `promoter_id`/`cust_id`. Its value is the `access_token` your backend received from the corresponding `iframe_login` call — so you'll need to have stored that value per-session in order to target it later.
```sh cURL theme={null}
curl --request POST \
--url 'https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?session_token=THE_ACCESS_TOKEN_FROM_IFRAME_LOGIN' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Account-Id: YOUR_ACCOUNT_ID'
```
All of the promoter's other active sessions remain untouched.
### Example
```js Node.js (Express) theme={null}
app.post("/logout", async (req, res) => {
const promoterId = req.user.firstpromoterPromoterId;
await fetch(
`https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?promoter_id=${promoterId}`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FP_API_KEY}`,
"Account-Id": process.env.FP_ACCOUNT_ID,
},
}
);
// ...continue your own app's logout flow
res.redirect("/login");
});
```
```php PHP theme={null}
firstpromoter_promoter_id;
$ch = curl_init(
"https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?promoter_id=" . urlencode($promoterId)
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $_ENV["FP_API_KEY"],
"Account-Id: " . $_ENV["FP_ACCOUNT_ID"],
]);
curl_exec($ch);
curl_close($ch);
?>
```
```sh cURL theme={null}
curl --request POST \
--url 'https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?promoter_id=12345' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Account-Id: YOUR_ACCOUNT_ID'
```
### When to call this
* **On your app's own logout action** — call it alongside your normal sign-out logic so the dashboard doesn't silently re-authenticate on the next page load.
* **When suspending or deactivating a user** — revoke dashboard access immediately rather than waiting up to 24 hours for their last token to expire.
* **Before switching which promoter is shown in the same embedded iframe** — e.g. an admin view of your app that lets staff preview different promoters' dashboards.
## Related
* [Embed the dashboard & auto-login promoters](/advanced/embed-dashboard-login)
* [Promoters API reference](/api-reference-v2/api-admin/promoters/get-available-promoters)
# Authentication
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/authentication
How to authenticate your API
## Authentication
### Obtaining Your Credentials
FirstPromoter uses two key credentials to authorize API requests:
1. **API Key**: A unique token that authenticates your application
2. **Account ID**: Identifies your specific FirstPromoter account
To locate these credentials:
1. Log in to your FirstPromoter Dashboard
2. Navigate to **Settings** → **Integrations** → **Manage API Keys** → **Add new Key** if you don't have one already.
3. Set a descriptive key name (e.g., `My Application Key`) and click **Create**
4. Immediately copy and securely store your newly generated API key.
5. You will find your **Account ID** in the same API integrations panel under **Settings** → **Integrations**
### Making Authenticated Requests
All API requests must include both credentials in your request headers:
```
Authorization: Bearer {your_api_key}
ACCOUNT-ID: {your_account_id}
```
#### Example Request
```
GET https://api.firstpromoter.com/api/v2/company/referrals
Authorization: Bearer 01234567890abcdef
ACCOUNT-ID: 123456
```
You must replace `{apikey}` with your account API key and `{account_id}` with your account ID
### Security Best Practices
* Keep your API key secure and never expose it in client-side code
* Consider implementing IP restrictions for API access
* Regularly audit your API usage and rotate keys if suspicious activity occurs
* Use HTTPS for all API communications
# List in progress batch processes.
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/batches/list-inprogress-batch-processes
openapi-v2-batches get /batch_processes
List batch processes that are in progress
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/batch_processes`
# Show batch process
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/batches/show-batch-process
openapi-v2-batches get /batch_processes/{id}
Show details of a specific batch process
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/batch_processes/{id}`
# Show progress
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/batches/show-progress
openapi-v2-batches get /batch_processes/progress
Show progress of batch process.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/batch_processes/progress`
# Approve commissions
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/approve-commissions
openapi-v2-commissions post /commissions/approve
With this endpoint you can approve commissions.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/commissions/approve`
# Create a commission
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/create-a-commission
openapi-v2-commissions post /commissions
With this endpoint you can create a commission.
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/commissions`
# Deny commissions
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/deny-commissions
openapi-v2-commissions post /commissions/deny
With this endpoint you can deny commissions.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/commissions/deny`
# Get all commissions
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/get-all-commissions
openapi-v2-commissions get /commissions
With this endpoint you can list all rewards and commissions assigned to a promotion, promoter, campaign or entire account using the API.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/commissions`
# Mark nonmonetary commissions as fulfilled
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/mark-nonmonetary-commissions-as-fulfilled
openapi-v2-commissions post /commissions/mark_fulfilled
With this endpoint you can mark nonmonetary commissions as fulfilled.
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/commissions/mark_fulfilled`
# Mark nonmonetary commissions as unfulfilled
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/mark-nonmonetary-commissions-as-unfulfilled
openapi-v2-commissions post /commissions/mark_unfulfilled
With this endpoint you can mark nonmonetary commissions as unfulfilled.
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/commissions/mark_unfulfilled`
# Update a commission
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/commissions/update-a-commission
openapi-v2-commissions put /commissions/{id}
With this endpoint you can update a commission.
**HTTP Request**
`PUT https://api.firstpromoter.com/api/v2/company/commissions/{id}`
# Introduction
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/introduction
This is the public API documentation for FirstPromoter V2.
Welcome to the FirstPromoter API! This documentation will guide you through the process of integrating with our platform programmatically, allowing you to leverage the full power of FirstPromoter's affiliate and referral tracking capabilities in your own applications.
### Why Use Our API?
**Automation:** Streamline your workflow by automating repetitive tasks\
**Integration:** Seamlessly incorporate FirstPromoter's capabilities into your existing systems **Customization:** Build custom solutions tailored to your specific business needs
### Who Should Use This API?
Due to the technical nature of API integrations, this documentation is designed for developers and any other technical individual who want to:
* Integrate FirstPromoter with their existing tools and platforms
* Create custom dashboards or reporting systems
* Automate affiliate management processes
* Build specialized applications leveraging FirstPromoter's functionality
### Getting Started
To begin using the FirstPromoter API, you'll need:
1. A FirstPromoter account
2. Your account id and an API key
3. Basic knowledge of REST API principles
### Rate Limits
To ensure fair usage and system stability, FirstPromoter implements the following rate limits:
* 400 requests per minute per account
Exceeding these limits will result in a `429 Too Many Requests` response.
### Pagination
When retrieving multiple affiliates, the API uses pagination to limit the number of records returned in a single response. This ensures optimal performance for both the API and your application.
### Pagination Parameters
| Parameter | Type | Description |
| - | - | - |
| `page` | Integer | The page number to retrieve (default: 1) |
| `per_page` | Integer | Number of records per page (default: 25 for most endpoints, with no enforced maximum) |
Pagination defaults can vary by endpoint. The campaigns list endpoint is a notable exception: it defaults to `10` per page and caps at a maximum of `50`. Check each endpoint's own documentation if you need its exact behavior.
# Get available promoter campaigns
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoter-campaigns/get-available-promoter-campaigns
openapi-v2-promoter-campaigns get /promoter_campaigns
With this endpoint you can list all promoter campaigns.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoter_campaigns`
# Update promoter campaign
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoter-campaigns/update-promoter-campaign
openapi-v2-promoter-campaigns put /promoter_campaigns/{id}
With this endpoint you can update a promoter campaign.
**HTTP Request**
`PUT https://api.firstpromoter.com/api/v2/company/promoter_campaigns/{id}`
# Accept promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/accept-promoters
openapi-v2-promoters post /promoters/accept
With this endpoint you can accept promoters.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/accept`
# Add promoters to campaign
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/add-promoter-to-campaign
openapi-v2-promoters post /promoters/add_to_campaign
With this endpoint you can add promoters to a campaign.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/add_to_campaign`
# Archive promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/archive-promoters
openapi-v2-promoters post /promoters/archive
With this endpoint you can archive promoters.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/archive`
# Assign a parent promoter
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/assign-parent-promoter
openapi-v2-promoters post /promoters/assign_parent
With this endpoint you can assign a parent promoter to your promoters.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/assign_parent`
# Block promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/block-promoters
openapi-v2-promoters post /promoters/block
With this endpoint you can block promoters.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/block`
# Create promoter
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/create-promoter
openapi-v2-promoters post /promoters
With this endpoint you can create a promoter.
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters`
# Get available promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-available-promoters
openapi-v2-promoters get /promoters
With this endpoint you can list all promoters.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters`
# Get data used for chart
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-data-used-for-chart
openapi-v2-promoters get /promoters/{id}/chart_data
With this endpoint you can get the data used for charts.**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters/{id}/chart_data`
# Get promoter details
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-promoter-details
openapi-v2-promoters get /promoters/{id}
With this endpoint you can get the details of a promoter.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters/{id}`
# Get promoter referral links
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-promoter-referral-links
openapi-v2-promoters get /promoters/{id}/referral_links
With this endpoint you can get the list of referral links for a single promoter (their default link plus any campaign or custom links).
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters/{id}/referral_links`
# Get reports for promoter overview
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-reports-for-promoter-overview
openapi-v2-promoters get /promoters/{id}/overview_report
With this endpoint you can get the overview report for a single promoter, grouped over time.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters/{id}/overview_report`
# Get reports for promoter traffic sources
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-reports-for-promoter-traffic-sources
openapi-v2-promoters get /promoters/{id}/traffic_sources_report
With this endpoint you can get the traffic sources report for a single promoter, broken down by source and grouped over time.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters/{id}/traffic_sources_report`
# Get reports for promoter URLs
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/get-reports-for-promoter-urls
openapi-v2-promoters get /promoters/{id}/urls_report
With this endpoint you can get the report data for a single promoter, grouped by URL.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promoters/{id}/urls_report`
# Move promoters to campaign
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/move-promoter-to-campaign
openapi-v2-promoters post /promoters/move_to_campaign
With this endpoint you can move promoters from one campaign to another.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/move_to_campaign`
# Reject promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/reject-promoters
openapi-v2-promoters post /promoters/reject
With this endpoint you can reject promoters.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/reject`
# Restore promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/restore-unarchived-promoters
openapi-v2-promoters post /promoters/restore
With this endpoint you can restore promoters.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promoters/restore`
# Update promoter
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promoters/update-promoter
openapi-v2-promoters put /promoters/{id}
With this endpoint you can update a promoter.
**HTTP Request**
`PUT https://api.firstpromoter.com/api/v2/company/promoters/{id}`
# Delete referrals
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/referrals/delete-referrals
openapi-v2-referrals delete /referrals
With this endpoint you can delete referrals.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`DELETE https://api.firstpromoter.com/api/v2/company/referrals`
# Get referral
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/referrals/get-referral
openapi-v2-referrals get /referrals/{id}
Get a specific referral
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/referrals/{id}`
# Get available referrals
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/referrals/get-referrals
openapi-v2-referrals get /referrals
Get available referrals
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/referrals`
# Move referrals to promoter
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/referrals/move-referrals-to-promoter
openapi-v2-referrals post /referrals/move_to_promoter
With this endpoint you can move referrals to another promoter.
If there are more than __5__ ids on the __ids__ param/field, the action will be processed asynchronously. The response for the batch status will most likely be `in_progress`. The available statuses are `pending`, `in_progress`, `completed`, `failed` and `stopped`
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/referrals/move_to_promoter`
# Update referral
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/referrals/update-referral
openapi-v2-referrals put /referrals/{id}
Update a specific referral. The id can be a referral ID, email, uid, or username when used with the find_by parameter in the request body.
**HTTP Request**
`PUT https://api.firstpromoter.com/api/v2/company/referrals/{id}`
# Tracking cancellations
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/cancellation
openapi-v2-tracking POST /cancellation
This call will mark the customer as cancelled and will decrease the MRR generated by them. **HTTP Request**
`POST https://api.firstpromoter.com/api/v2/track/cancellation`
# Tracking leads and sign-ups
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/leads-and-signups
openapi-v2-tracking POST /signup
Capture a lead when they sign-up or fill an optin form. This endpoint is used to track leads and sign-ups. It's not for tracking the actual sales and commissions.
Sign-ups are tracked as leads in FirstPromoter so when a person referred by the promoter/affiliate signs up, a new referral should be added inside FirstPromoter **(you can see them inside the `Referrals` section as `Leads`)**.
Using sub IDs, postbacks or ad tracking? Install the tracking script so it sets the `_fprom_tid` cookie when a visitor clicks a referral link, then send that cookie's value in the `tid` parameter.**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/track/signup`
# Tracking refunds and negative commissions
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/refund
openapi-v2-tracking POST /refund
The refund call is similar to the sale call. It works the same way, except that it generates negative commissions. **HTTP Request**
`POST https://api.firstpromoter.com/api/v2/track/refund`
# Tracking sales and commissions
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/sales
openapi-v2-tracking POST /sale
Assign sales and commissions to your promoters. To track sales and generate commissions correctly, you need to use this API call each time a non-zero amount sale is processed in your system, even if it comes from a recurring charge or one-time charge. To avoid fraudulent sales, we don't use JS conversion pixels to track sales, which are very unreliable and can be easily faked. Instead, we use server-side tracking for all sales to ensure that a sale is tracked only when you actually receive money in your billing account.
To maintain the same standards with the API, we recommend making the sale API call (this call) only when you receive confirmation of the sale from your billing provider, such as from a webhook, an IPN, or a success response from an API charge call.
You just need to pass the sale amount (before taxes) and we'll take care of the rest. The commissions/rewards will be calculated based on that amount and the plan ID, in case you use the plan-level rewards feature. Using email or UID parameters, we identify the lead/customer who generated the sale, which also helps us determine the promoter who owns the reward/commission.
The lead is added to our system either by the client signup tracking script when the user signs up or by calling the signup API endpoint. There is also the option to bypass the signup tracking by using TID or ref_id parameters, which will create the lead and assign the sale in one go.
**If we don't find the lead in our system, then it means that the sale is not a referral sale, you'll get a 404 response. Also, if the promoter is banned, you'll get a 404 response. You don't have to identify which sale is from referrals and which is not; we'll take care of that.** **For zero-decimal** currencies like `JPY`, `amount` and `mrr` parameters should be sent as **whole values**.
**For other currencies**, `amount` and `mrr` parameter values should be in cents, i.e., you will need to **multiply the value by 100** before sending the request.**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/track/sale`
# Make.com
Source: https://docs.firstpromoter.com/automation/make
Integrate FirstPromoter v2 with Make (formerly Integromat) to automate your affiliate program alongside thousands of other apps.
# What is Make?
[Make](https://www.make.com/) (formerly Integromat) is a visual, no-code automation platform. You build "scenarios" that connect FirstPromoter to other apps using modules — triggers that watch for events, and actions that perform tasks — without writing any code.
The FirstPromoter app is available in Make's app directory at [apps.make.com/firstpromoter](https://www.make.com/en/integrations/firstpromoter).
# Requirements
* A Make account
* Authentication credentials — v2 API key and Account ID. See [Setting up a connection](#setting-up-a-connection) below.
# Available modules
## Triggers
| Trigger | Description |
| - | - |
| Watch Campaigns | Fires when a webhook event for a campaign is received |
| Watch NMI | Fires when a transaction is refunded, voided, or sold |
Both triggers are instant (webhook-based) — Make gives you a webhook URL to register in your FirstPromoter account, the same way it works with [Zapier](/automation/zapier#registering-the-webhook-in-firstpromoter).
## Actions
| Action | Description |
| - | - |
| Create a Lead | Assigns a new lead to an affiliate/promoter |
| Create a Promoter | Creates a new promoter account |
| Track a Sale and Commission | Records a sale and generates the resulting commission |
| Track a Refund | Creates a negative commission for an existing sale |
| Cancel a Tracked Sale | Marks a customer as cancelled and adjusts MRR |
| Make an API Call | Performs a custom authenticated request against any FirstPromoter v2 API endpoint |
**Make an API Call** is useful for any FirstPromoter v2 endpoint that doesn't have a dedicated module yet — see the [API Reference](/api-reference-v2/api-admin/introduction) for available endpoints.
# Setting up a connection
Like every FirstPromoter v2 integration, Make connects using your Account ID and a v2 API key.
| Field | Required | Description |
| - | - | - |
| Account ID | yes | FirstPromoter Account ID |
| API Key | yes | v2 API key |
**Get your credentials on FirstPromoter**
1. Log in to your **FirstPromoter** dashboard.
2. Go to **Settings → Integrations → API integration** section.
* Copy your **Account id**.
3. Click **Manage API keys**
* Add a new API key or copy an existing one.
# Building a scenario
In Make, create a new scenario and click the **+** button to add a module.
Search for **FirstPromoter** and select the trigger or action module you want to use.
Click **Add** next to the connection field to create a new FirstPromoter connection.
Enter your **Account ID** and **v2 API key**, then click **Save**.
If you're adding a trigger module (**Watch Campaigns** or **Watch NMI**), copy the webhook URL Make generates for that module.
In FirstPromoter, go to **Settings → Integrations → Webhooks**, click **Add new webhook**, paste the URL, select the matching event and campaign(s), then save. See [Webhooks overview](/webhooks-v2/overview) for details.
Map the module's fields to data from earlier steps in your scenario — for sale tracking, either **Email** or **UID** is required to identify the customer.
Run the scenario once to test, then turn scheduling on to activate it.
# Related
* [Set up webhooks in FirstPromoter](/webhooks-v2/overview)
* [Zapier integration](/automation/zapier)
* [n8n node](/automation/n8n-node)
# n8n node
Source: https://docs.firstpromoter.com/automation/n8n-node
Integrate FirstPromoter n8n node in your workflow.
# What is n8n?
[n8n](https://n8n.io/) is a workflow automation platform that lets you connect FirstPromoter to hundreds of other services.
The [FirstPromoter](https://www.npmjs.com/package/@firstpromoter/n8n-nodes-firstpromoter) n8n node lets you start a workflow when a webhook event is received or use the FirstPromoter v2 API to perform many actions or operations.
# Requirements
* n8n instance — self host(local machine or docker-based) or n8n-cloud based. [See n8n docs](https://docs.n8n.io/hosting/)
* Authentication credentials — API key and Account ID. See [Setting up credentials](#-setting-up-credentials) for details on generating/accessing API keys and Account ID.
# Installation
To install the [FirstPromoter](https://www.npmjs.com/package/@firstpromoter/n8n-nodes-firstpromoter) n8n node, make sure the n8n instance is already running. See the [official n8n docs](https://docs.n8n.io/hosting/) if you need to install it first.
## Install FirstPromoter n8n node
The [FirstPromoter](https://www.npmjs.com/package/@firstpromoter/n8n-nodes-firstpromoter) n8n node can be installed through the local self-hosted n8n instance or the n8n Cloud-based instance. [See n8n docs](https://docs.n8n.io/hosting/)
Community nodes require N8N\_COMMUNITY\_PACKAGES\_ENABLED=true in your n8n environment. Most installations have this enabled by default. If you cannot access the Community Nodes section in Settings, set this variable before starting n8n.
### Self Hosted
For self-hosted n8n instances, you can install the FirstPromoter node directly via the web interface by following the steps below:
Open n8n in your browser (typically `http://localhost:5678`)
Navigate to **Settings** → **Community Nodes**
Click "**Install a community node**"
Enter package name: `@firstpromoter/n8n-nodes-firstpromoter`
Click **Install** and wait for the installation to complete
Refresh your browser and [set up credentials](#-setting-up-credentials)
### n8n Cloud
The [FirstPromoter](https://www.npmjs.com/package/@firstpromoter/n8n-nodes-firstpromoter) n8n node requires verification to be available on the n8n Cloud. n8n Cloud supports a select group of verified community nodes included in their official catalog.
**Current Status**: Until the [FirstPromoter](https://www.npmjs.com/package/@firstpromoter/n8n-nodes-firstpromoter) n8n node is verified and included in the Cloud-available catalog, use self-hosted n8n (local or Docker) with any of the installation methods above.
# 🔑 Setting Up Credentials
Before using the [FirstPromoter](https://www.npmjs.com/package/@firstpromoter/n8n-nodes-firstpromoter) n8n node, configure your connection credentials:
| Field | Required | Description |
| - | - | - |
| Account ID | yes | FirstPromoter Account ID |
| API Key | yes | v2 API key |
**Get your credentials on FirstPromoter**
1. Log in to your **FirstPromoter** dashboard.
2. Go to **Settings → Integrations → API integration** section.
* Copy your **Account id**.
3. Click **Manage API keys**
* Add New API key or copy existing API key
**Tip:** If you rotate keys, update the n8n credential and re-run affected workflows
To add credentials in the n8n instance via the web interface, follow the steps below:
Click the plus icon **+** on the top-left
Click **New Credential**
Search for **FirstPromoter API**
Fill in the required fields.
* Account ID
* API Key
Click **Save**
Click the close icon "**x"** or click anywhere outside of the modal to close
Create a new workflow or open an existing workflow and add the **FirstPromoter** n8n node.
# Related
* [Zapier integration](/automation/zapier)
* [Make.com integration](/automation/make)
# Zapier
Source: https://docs.firstpromoter.com/automation/zapier
Integrate FirstPromoter v2 with Zapier to connect your affiliate program to thousands of other apps.
# What is Zapier?
[Zapier](https://zapier.com/) is a no-code automation platform that connects FirstPromoter to thousands of other apps — Slack, Gmail, Salesforce, Shopify, and more — so data and actions move between them automatically, without writing any code.
Each automation ("Zap") has two parts:
* **Trigger** — an event in FirstPromoter (or another app) that starts the workflow, e.g. a new referral or a new commission.
* **Action** — the task Zapier performs automatically in response, e.g. tracking a sale or creating a promoter.
# Requirements
* A Zapier account
* Authentication credentials — v2 API key and Account ID. See [Setting up credentials](#setting-up-credentials) below.
# Installing the FirstPromoter app
The FirstPromoter v2 app on Zapier is installed via invite link rather than the public Zapier directory.
Make sure you're logged into Zapier.
Open the [FirstPromoter v2 app invite link](https://zapier.com/developer/public-invite/215402/39aea398460ea85023d7fa0799366cc6/).
Click **Accept invite & Build a Zap**.
# Available triggers
Triggers fire when something happens in FirstPromoter — commonly used ones include:
| Trigger | Fires when |
| - | - |
| Referral Created | A new referral/lead is recorded |
| Referral Converted | A referral converts into a paying customer |
| Referral Cancelled | A referral's subscription is cancelled |
| Promoter Created | A new promoter signs up |
| Promoter Updated | A promoter's details change |
| Promoter Balance Updated | A promoter's payable balance changes |
| Promoter Campaign Created | A promoter is added to a campaign |
| Promoter Campaign Accepted | A promoter's campaign application is accepted |
| Promoter Campaign Pending | A promoter applies to a campaign |
| Commission Created | A new commission is generated |
| Commission Pending | A commission enters pending status |
| Commission Approved | A commission is approved for payout |
This is not exhaustive — the FirstPromoter v2 Zapier app exposes triggers for most events FirstPromoter can emit. Search the full list from within the trigger picker when building your Zap.
# Available actions
Actions perform a task in FirstPromoter from another app's event — commonly used ones include:
* Track a sale and commission
* Track a refund (creates a negative commission)
* Track a signup/lead
* Create a promoter
# Setting up credentials
Both triggers and actions connect using the same FirstPromoter account credentials:
| Field | Required | Description |
| - | - | - |
| Account ID | yes | FirstPromoter Account ID |
| API Key | yes | v2 API key |
**Get your credentials on FirstPromoter**
1. Log in to your **FirstPromoter** dashboard.
2. Go to **Settings → Integrations → API integration** section.
* Copy your **Account id**.
3. Click **Manage API keys**
* Add a new API key or copy an existing one.
# Configuring a trigger
Create or open a Zap and click the **Trigger** step.
Search for and select **FirstPromoter v2 with triggers**.
Choose the trigger event (e.g. **Referral Created**), then click **Sign in**.
Enter your **v2 API key** and **Account ID**, then click **Connect**. Click **Continue** once the connection is established.
Copy the webhook URL Zapier generates — you'll paste this into FirstPromoter in the next section.
After creating the matching webhook in FirstPromoter (below), come back and click **Test trigger**.
Select the received sample record and click **Continue**.
## Registering the webhook in FirstPromoter
FirstPromoter triggers are webhook-based — Zapier gives you a URL, and you register that URL as a webhook in your FirstPromoter account so events actually get sent to it.
In FirstPromoter, go to **Settings → Integrations → Webhooks** and click **Add new webhook**.
Paste the webhook URL you copied from Zapier.
Select the event that matches the trigger you chose in Zapier, then click **Apply**.
Select which campaign(s) should send data through this webhook.
Click **Select event**, choose an event to send, and click **Run test** to confirm delivery.
Once the test succeeds, click **Add webhook**.
See [Webhooks overview](/webhooks-v2/overview) for more on setting up and managing webhooks.
# Configuring an action
Open your Zap and click the **Action** step.
Search for and select **FirstPromoter v2 with triggers**.
Choose the action event (e.g. **Track a sale and commission**).
Select your existing connected account, or sign in with your **v2 API key** and **Account ID** if this is a new connection.
Map the fields using data from your trigger step. For sale tracking, either **Email** or **UID** is required to identify the customer.
Test the action, then publish your Zap.
# Related
* [Set up webhooks in FirstPromoter](/webhooks-v2/overview)
* [n8n node](/automation/n8n-node)
* [Make.com integration](/automation/make)
# Integrate Your Website
Source: https://docs.firstpromoter.com/guides/integrate-your-website
Connect your website to FirstPromoter so clicks, sign-ups, and sales are tracked and attributed to the right affiliate.
Website integration is what makes FirstPromoter actually work. Without it, FirstPromoter cannot tell which affiliate sent a visitor, whether that visitor signed up, or whether they made a purchase.
The full integration has three parts:
| Part | What it does | Required? |
| - | - | - |
| **Click tracking** | Detects when a visitor arrives through an affiliate link | Yes |
| **Referral tracking** | Records who signed up or filled a form | Yes |
| **Sales tracking** | Attributes purchases to the right affiliate | Yes (to generate commissions) |
Before you start, find your **Account ID** in your FirstPromoter dashboard under **Settings → Integrations**. You'll need it in the steps below.
***
## Step 1 — Choose your integration path
Pick the option that matches your website setup:
Use our WordPress plugin for click tracking, referral tracking, and WooCommerce / MemberPress sales — no custom code needed.
Using Kajabi, HighLevel, ClickFunnels, Ghost, Thinkific, SamCart, or similar? We have ready-made guides for each.
Any other website, SaaS app, or JavaScript framework. Requires adding a script tag and one function call.
***
## Platform integrations
If you use one of the platforms below, follow the dedicated guide — it handles click and referral tracking for that platform's specific forms and checkout flows.
After completing the platform guide, jump to [Step 3 — Sales tracking](#step-3--sales-tracking) to finish your setup.
***
## Custom website or app
### Step 2a — Add the click tracking script
Add the following snippet to the `
` section of every public-facing page on your website. Replace `YOUR_ACCOUNT_ID` with the Account ID from your FirstPromoter dashboard.
```html theme={null}
```
Adding this to every page (not just the homepage) ensures clicks are tracked no matter which page an affiliate links to. The script loads asynchronously and will not slow down your site.
Add the script to your `header.php` file before the closing `` tag, or use a plugin like **Insert Headers and Footers** to paste it into the head section without editing theme files.
Add the script tags to your `public/index.html` file inside the `` section.
1. Create `/public/fprmain.js` and paste the `fpr("init", ...)` and `fpr("click")` lines into it.
2. In `_document.tsx`, load both `/fprmain.js` and `https://cdn.firstpromoter.com/fpr.js` inside the `` component.
See the [full Next.js example](/integrations/tracking/custom/js) for a working code snippet.
Create `/public/fprmain.js` with the init and click lines, then use the `useHead` composable on your marketing pages to load it alongside `fpr.js`.
Follow the [GTM integration guide](/integrations/tracking/custom/gtm) to add the scripts through a custom HTML tag.
***
### Step 2b — Add referral tracking
When a visitor signs up or submits a form, you need to send their email (or user ID) to FirstPromoter. This is what creates the referral record and links the sign-up to the affiliate.
Call the following **after** the main script and **after** you have the user's email — typically on your sign-up success callback or thank-you page:
```html theme={null}
```
Replace `"actual_user@email.com"` with the real email of the user who just signed up. You can also pass a `uid` (user ID from your database) instead of or in addition to the email:
```javascript theme={null}
fpr("referral", {email: "actual_user@email.com", uid: "cus_12345"});
```
The `fpr("referral", ...)` call must run **after** the user has successfully signed up — not before. If you redirect immediately after the call, the request may be cancelled by the browser. In that case, place the script on the thank-you/confirmation page instead.
**Where to place this call:**
* **Simple HTML form** — listen for the form submit event, read the email input value, and call `fpr("referral", {email: emailValue})`.
* **React / Vue / Angular** — call it inside the success callback of your registration API request.
* **Thank-you page with email in the URL** — read the email from the URL and pass it directly: `fpr("referral", {email: new URLSearchParams(location.search).get("email")})`.
* **Server-side only** — use the [Tracking API](/integrations/tracking/custom/api) to make the call from your backend instead.
For detailed examples per framework, see the [JavaScript integration guide](/integrations/tracking/custom/js).
***
## Step 3 — Sales tracking
Sales tracking tells FirstPromoter which purchases to credit to which affiliate and triggers commission creation.
### Option A — Connect a billing provider (recommended)
If you use one of the following billing providers, connect it directly in FirstPromoter and sales are tracked automatically:
Go to **Settings → Integrations** in your FirstPromoter dashboard to connect your billing provider.
For Stripe-specific checkout setups, see also:
* [Stripe Checkout](/integrations/tracking/custom/stripe-checkout)
* [Stripe Payment Links](/integrations/tracking/platform/stripe/payment-links)
* [Stripe Pricing Table](/integrations/tracking/platform/stripe/pricing-table)
### Option B — Use the Tracking API
If you use a different billing provider or have a custom payment flow, send a sale event to FirstPromoter from your backend whenever a payment is confirmed:
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/sale \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"sale_amount": 4900,
"currency": "usd",
"order_id": "order_001"
}'
```
See the full [Sales Tracking API reference](/api-reference-v2/api-admin/tracking-api/sales) for all available parameters.
`sale_amount` is in **cents** (e.g. `4900` = \$49.00).
***
## Step 4 — Test your integration
Before going live, verify each part is working:
Copy an affiliate's referral link from the FirstPromoter dashboard and visit it in your browser. A click should appear on that affiliate's record within a few seconds.
After visiting via the referral link, sign up as a test user on your website. Check the **Referrals** tab in FirstPromoter — a new lead should appear linked to the affiliate.
Complete a test purchase (use a Stripe test card if on Stripe). A new sale and commission should appear in FirstPromoter.
Check your browser console for errors after adding the scripts. Common issues are a wrong Account ID or calling `fpr("referral", ...)` before the main script has loaded.
***
## Need help?
* [Full fpr.js script reference](/script-docs/fpr-js-docs) — every method and option explained
* [Tracking without fpr.js (API only)](/guides/tracking-without-fprjs) — pure API approach with no frontend script
* [Proxy setup](/guides/proxy-setup) — keep tracking working when ad-blockers are active
* [Support](mailto:support@firstpromoter.com) — reach the team if you're still stuck
# Mobile Attribution Providers (Branch.io, AppsFlyer, Adjust)
Source: https://docs.firstpromoter.com/guides/mobile-attribution-providers
Use a deep linking/attribution provider to solve new-install (deferred) referral tracking on iOS and Android, and report the result to FirstPromoter.
[Deep Linking for Mobile Apps](/guides/mobile-deep-linking) covers tracking referrals when the user **already has your app installed**. This guide solves the harder case: **the user doesn't have your app yet.**
When someone taps an affiliate link without your app installed, iOS and Android route them to the App Store / Play Store. Neither platform passes the original link's query parameters through that install — by the time the app opens for the first time, the referral ID (`fpr=joe13`) is gone. This is why "deferred deep linking" tools exist. FirstPromoter doesn't run its own — instead, you point one of these providers at your app and forward whatever referral ID it recovers into FirstPromoter's Tracking API, the same way as the direct-install case.
This guide uses **Branch.io** as the worked example since it's the most commonly used for this pattern, but **AppsFlyer** (OneLink) and **Adjust** solve the same problem the same way — a redirect link with custom data, an SDK that reads that data back on first open, and an attribution callback in your app code. If you're already using one of those for ad attribution, reuse it here instead of adding Branch.
***
## How it works end to end
| Step | What happens |
| - | - |
| 1 | Affiliate's FirstPromoter referral ID (`ref_id`) is embedded as custom data on a Branch link |
| 2 | Affiliate shares the **Branch link** instead of the raw FirstPromoter link |
| 3 | No app installed → Branch redirects to the App Store / Play Store |
| 4 | App installed → opened for the first time → Branch SDK resolves the original link's custom data |
| 5 | Already installed → tapping the link opens the app directly with the same custom data |
| 6 | Your app reads the `ref_id` out of Branch's session params and reports it to FirstPromoter |
***
## Step 1 — Generate a Branch link carrying the FirstPromoter referral ID
For each affiliate, once you have their FirstPromoter referral link (e.g. `https://yourapp.com/r?fpr=joe13`), create a corresponding Branch link with the `ref_id` stored as custom data, and the FirstPromoter link set as the desktop/web fallback so anyone opening it on desktop still lands on your normal site:
```sh theme={null}
curl -X POST https://api2.branch.io/v1/url \
-H 'Content-Type: application/json' \
-d '{
"branch_key": "key_live_YOUR_BRANCH_KEY",
"channel": "affiliate",
"feature": "referral",
"data": {
"fpr_ref_id": "joe13",
"$desktop_url": "https://yourapp.com/r?fpr=joe13",
"$fallback_url": "https://yourapp.com/r?fpr=joe13"
}
}'
```
Share the resulting `https://yourapp.app.link/...` URL as the affiliate's mobile referral link (in addition to, or instead of, the plain FirstPromoter one, depending on where you expect it to be shared).
You can automate this: whenever FirstPromoter creates or returns a promoter's referral link (via the dashboard, or the [Promoter API](/api-reference-v2/api-admin)), call the Branch URL API from your backend to mint the matching Branch link, and show that to the affiliate instead.
***
## Step 2 — Initialize the Branch SDK and read the referral ID
```dart Flutter (flutter_branch_sdk) theme={null}
import 'package:flutter_branch_sdk/flutter_branch_sdk.dart';
Future initBranch() async {
await FlutterBranchSdk.init(enableLogging: true);
FlutterBranchSdk.listSession().listen((data) {
if (data.containsKey('+clicked_branch_link') && data['+clicked_branch_link'] == true) {
final refId = data['fpr_ref_id'] as String?;
if (refId != null) storeReferralId(refId);
}
});
}
```
```swift iOS (Branch native SDK) theme={null}
// AppDelegate.swift — application(_:didFinishLaunchingWithOptions:)
Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
if let refId = params?["fpr_ref_id"] as? String {
UserDefaults.standard.set(refId, forKey: "fpr_ref_id")
}
}
```
```kotlin Android (Branch native SDK) theme={null}
// In onStart() of your launcher Activity
Branch.sessionBuilder(this).withCallback { referringParams, error ->
if (error == null) {
val refId = referringParams?.optString("fpr_ref_id")
if (!refId.isNullOrEmpty()) {
getSharedPreferences("fpr", MODE_PRIVATE).edit()
.putString("fpr_ref_id", refId)
.apply()
}
}
}.withData(intent?.data).init()
```
```javascript React Native (react-native-branch) theme={null}
import branch from 'react-native-branch';
import AsyncStorage from '@react-native-async-storage/async-storage';
branch.subscribe(({ error, params }) => {
if (error) return;
if (params?.['+clicked_branch_link']) {
const refId = params.fpr_ref_id;
if (refId) AsyncStorage.setItem('fpr_ref_id', refId);
}
});
```
Branch returns the same `fpr_ref_id` custom data key whether the link was opened directly (app already installed) or resolved after a fresh install (deferred) — your app doesn't need separate logic for the two cases. That's the problem Branch (or an equivalent provider) is solving for you.
***
## Step 3 — Report the referral ID to FirstPromoter
Once `fpr_ref_id` is captured, the rest is identical to the direct deep-linking flow — send it to your backend, and have your backend call the FirstPromoter Tracking API:
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"ref_id": "joe13"
}'
```
As with direct deep linking, keep your FirstPromoter API key on your backend only — never call this endpoint directly from the mobile app. See [Deep Linking for Mobile Apps → Step 3](/guides/mobile-deep-linking#step-3-report-the-referral-to-firstpromoter) for the sales-tracking call and full parameter list.
***
## Using AppsFlyer or Adjust instead
The pattern is the same; only the SDK callback differs:
| Provider | Where you set the custom data | Where you read it back |
| - | - | - |
| **Branch.io** | `data` object on link creation | `initSession`/`listSession` callback params |
| **AppsFlyer (OneLink)** | deep link value / OneLink template parameters | `onAppOpenAttribution` / `onConversionDataSuccess` callback |
| **Adjust** | `deep_link_value` on the tracker/link | `attributionCallback` on the `Adjust` instance |
Whichever you use, the goal is the same: get the FirstPromoter `ref_id` out of the provider's attribution payload, then make the same two Tracking API calls (`/track/signup`, `/track/sale`) from your backend described in Step 3 above and in the [Deep Linking guide](/guides/mobile-deep-linking).
***
## Choosing whether you need this at all
Adding an attribution provider is real integration work and (beyond free tiers) an ongoing cost. Consider whether you need it:
* If your affiliates mostly share links in **contexts where the app is very likely already installed** (e.g. existing customers referring other existing users of the same category of app), the direct deep-linking flow in the [previous guide](/guides/mobile-deep-linking) may be enough on its own.
* If a meaningful share of referred signups are **brand-new users installing your app for the first time**, you need deferred deep linking to avoid losing that attribution — this guide's approach (or the Android-only Play Install Referrer API from the previous guide) is required.
***
## Need help?
* [Deep Linking for Mobile Apps](/guides/mobile-deep-linking) — the direct-install flow and full Tracking API parameter reference
* [Tracking API reference](/api-reference-v2/api-admin/tracking-api/leads-and-signups)
* [Support](mailto:support@firstpromoter.com) — reach the team if you're still stuck
# Deep Linking for Mobile Apps (Flutter, iOS, Android, React Native)
Source: https://docs.firstpromoter.com/guides/mobile-deep-linking
Track affiliate referrals inside native mobile apps by capturing the referral ID from a deep link and reporting it to FirstPromoter's Tracking API.
FirstPromoter's standard integration (`fpr.js` + cookies) is built for browsers. A native mobile app has no cookies and no `document`, so referral tracking has to be done a different way: **capture the referral ID from the incoming link, then report it to FirstPromoter yourself via the Tracking API.**
This guide covers the case where the user **already has your app installed** — tapping the affiliate's link opens the app directly and the referral data survives the trip. If the user does **not** have the app installed yet, the link has to go through the App Store / Play Store first, and standard deep links **lose the referral data** in that round-trip. That "deferred deep linking" problem is covered separately in [Mobile Attribution Providers](/guides/mobile-attribution-providers) — read this guide first, since the concepts (extracting the ref ID, calling the Tracking API) are the same either way.
***
## How it works
| Step | What happens |
| - | - |
| 1. Affiliate shares their link | The same referral link FirstPromoter already generates, e.g. `https://yourapp.com/r?fpr=joe13` |
| 2. Link opens your app | Configured as a Universal Link (iOS) / App Link (Android) so it opens the app instead of a browser, if installed |
| 3. App reads the referral ID | Your app extracts `fpr` (or whichever parameter is used) from the incoming URL |
| 4. App stores it | Persist it locally until the user signs up — this replaces the `_fprom_ref` cookie a website would use |
| 5. Your backend reports it | On signup/purchase, your backend calls FirstPromoter's [Tracking API](/api-reference-v2/api-admin/tracking-api/leads-and-signups) with the referral ID |
The supported query parameters for a referral link are `fpr`, `via`, `fp_ref`, `deal`, `ref`, `_from`, `_by`, `_go`. Pick one and use it consistently — `fpr` is the default used throughout this guide.
***
## Step 1 — Make your referral link open the app
For the link to open your app directly (instead of a mobile browser) when the app is already installed, register your domain as:
* **iOS — Universal Links**: host an `apple-app-site-association` file at `https://yourapp.com/.well-known/apple-app-site-association` and enable the **Associated Domains** capability (`applinks:yourapp.com`) in Xcode.
* **Android — App Links**: host an `assetlinks.json` file at `https://yourapp.com/.well-known/assetlinks.json` and add an `` in your `AndroidManifest.xml` matching your domain.
A misconfigured `apple-app-site-association` or `assetlinks.json` is the most common reason deep links silently fall back to the browser instead of opening the app. Verify both files are served over HTTPS with no redirects and a `Content-Type` of `application/json`.
If you don't want to set up Universal/App Links yet, a custom URL scheme (`yourapp://ref?fpr=joe13`) works too, but it can't be used as the affiliate-facing link on its own (it won't resolve in a browser or `sms`/social share preview) — pair it with a normal `https://` fallback link that redirects to it, or use one of the frameworks below which handle both.
***
## Step 2 — Capture the referral ID on app open
```dart Flutter (app_links package) theme={null}
import 'package:app_links/app_links.dart';
final _appLinks = AppLinks();
Future initDeepLinkListener() async {
// Handles the link that launched the app (cold start)
final initialUri = await _appLinks.getInitialLink();
_handleIncomingLink(initialUri);
// Handles links received while the app is already running
_appLinks.uriLinkStream.listen(_handleIncomingLink);
}
void _handleIncomingLink(Uri? uri) {
if (uri == null) return;
final refId = uri.queryParameters['fpr'];
if (refId != null) {
storeReferralId(refId); // persist with shared_preferences / secure storage
}
}
```
```swift iOS (Universal Links, SceneDelegate/AppDelegate) theme={null}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
if let refId = components.queryItems?.first(where: { $0.name == "fpr" })?.value {
UserDefaults.standard.set(refId, forKey: "fpr_ref_id")
}
}
```
```kotlin Android (App Links) theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
val data: Uri? = intent.data
val refId = data?.getQueryParameter("fpr")
if (refId != null) {
getSharedPreferences("fpr", MODE_PRIVATE).edit()
.putString("fpr_ref_id", refId)
.apply()
}
}
```
```javascript React Native (Linking API) theme={null}
import { Linking } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
function extractRefId(url) {
if (!url) return null;
const { queryParams } = Linking.parse(url); // or new URL(url).searchParams
return queryParams?.fpr ?? null;
}
// Cold start
Linking.getInitialURL().then((url) => {
const refId = extractRefId(url);
if (refId) AsyncStorage.setItem('fpr_ref_id', refId);
});
// While app is running
Linking.addEventListener('url', ({ url }) => {
const refId = extractRefId(url);
if (refId) AsyncStorage.setItem('fpr_ref_id', refId);
});
```
If you use React Navigation, wire this into its own [deep linking config](https://reactnavigation.org/docs/deep-linking/) `getStateFromPath`/`subscribe` instead of a second parallel `Linking` listener, to avoid handling the same URL twice.
***
## Step 3 — Report the referral to FirstPromoter
Never embed your FirstPromoter API key in the mobile app. The Tracking API requires a `Bearer` API key that can create signups and sales on your account — anyone who decompiles your app binary would be able to extract it. Send the stored referral ID from the app to **your own backend**, and make the FirstPromoter API call from there.
**When the user signs up** (client → your backend → FirstPromoter):
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"ref_id": "joe13",
"skip_email_notification": true
}'
```
* Send either `email` or `uid` (or both) — whichever you have at signup time.
* `ref_id` is the value you captured from the `fpr` parameter in Step 2.
See the full [Leads & Sign-ups API reference](/api-reference-v2/api-admin/tracking-api/leads-and-signups) for all parameters.
**When the user makes a purchase** (in-app purchase confirmed server-side, subscription webhook, etc.):
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/sale \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"event_id": "txn_00123",
"amount": 4900
}'
```
* `amount` is in **cents** (`4900` = \$49.00), except for zero-decimal currencies (e.g. `JPY`), which are sent as whole values.
* `event_id` must be unique per transaction — it's how FirstPromoter deduplicates retried webhook/receipt calls.
* If you already reported the signup with a `ref_id`, you don't need to pass it again on the sale call — FirstPromoter matches the sale to the lead by `email`/`uid`.
See the full [Sales Tracking API reference](/api-reference-v2/api-admin/tracking-api/sales).
***
## Limitations of direct deep linking
This approach only works when **the app is already installed**. If it isn't:
* Tapping the link opens the App Store / Play Store listing (or a fallback web page) instead of the app.
* The `fpr` parameter is **not** carried through the install — the app has no way to read it on first open, because the OS doesn't pass launch parameters from an unrelated store install.
This is a limitation of iOS/Android themselves, not FirstPromoter — every affiliate/attribution tool runs into it. There is one native, first-party workaround on Android only:
* **Google Play Install Referrer API** lets you append a referrer string to the Play Store URL (`&referrer=fpr%3Djoe13`), which Google stores and your app can read via the `com.android.installreferrer` library on first open after install — no third-party SDK required. There is no iOS equivalent.
If you need reliable new-install attribution on **both** iOS and Android, see [Mobile Attribution Providers](/guides/mobile-attribution-providers), which covers using a service like Branch.io to bridge that gap and still report into FirstPromoter using the same API calls from Step 3.
***
## Need help?
* [Tracking API reference](/api-reference-v2/api-admin/tracking-api/leads-and-signups) — full parameter documentation
* [Mobile Attribution Providers](/guides/mobile-attribution-providers) — solving new-install (deferred) attribution with Branch.io or similar
* [Tracking without fpr.js](/guides/tracking-without-fprjs) — the same API-only pattern used here, written for websites
* [Support](mailto:support@firstpromoter.com) — reach the team if you're still stuck
# Proxy Setup (Optional)
Source: https://docs.firstpromoter.com/guides/proxy-setup
FirstPromoter Proxy Integration Guide for Bypassing Ad Blockers
## Overview
This document outlines how to implement proxy integrations with FirstPromoter to ensure reliable tracking even when ad blockers are present. By leveraging a proxy setup, you can maintain accurate affiliate tracking and conversion attribution while minimizing the impact of ad blocking technologies.
## The Challenge with Ad Blockers
Ad blockers and privacy tools can interfere with affiliate tracking in several ways:
* Blocking tracking scripts from loading
* Preventing cookies from being set
* Blocking HTTP requests to domains identified as tracking services
* Stripping tracking parameters from URLs
FirstPromoter, like many affiliate platforms, can be affected by these measures, resulting in lost attribution data and commission tracking failures.
## Proxy Integration Solution
A proxy integration routes tracking requests through your own domain or a custom domain instead of directly to FirstPromoter's tracking domain.
This approach has several advantages:
* **Improved Deliverability**: Requests appear to come from your trusted domain, not a third-party tracking service
* **Reduced Blocking**: Most ad blockers don't block first-party requests
* **Enhanced Privacy**: User data stays within your domain ecosystem
* **Better Performance**: Removes additional DNS lookups to third-party domains
### Implementation Methods
#### Method 1: Vercel redirect setup
If your service is hosted by Vercel, they provide an option to reroute your requests.
To set up a Vercel redirect, follow these steps:
1. Find your vercel.json file. This is usually in your root directory.
2. Add the following lines to your vercel.json file:
```json theme={null}
{
"rewrites": [
{
"source": "/get_details",
"destination": "https://t.firstpromoter.com/get_details"
},
{
"source": "/tr",
"destination": "https://t.firstpromoter.com/tr"
}
]
}
```
You can change the source paths to anything that you like. However you will need to update the URL's in the tracking scripts as well.
For these we provide the following variables which you will use when setting up your scripts : `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url`
3. Download the tracking scripts from here (Click here) and add it to your main website's public directory.
This will allow it to be fetched from your website. You can change the name of the file to anything but remember to rename it in the main tracking code below.
4. For your main tracking scripts, add the following code. Please replace `` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard. If you changed the urls to something more custom you can uncomment the `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url` variables and update them to match your proxy urls.
```html theme={null}
```
6. Deploy your changes and test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected
#### Method 2: Cloudflare workers setup
Cloudflare provides a free plan with up to 100,000 requests per day, making it a good choice for a reverse proxy setup.
To set up a Cloudflare worker, follow these steps:
1. Set up a Cloudflare Worker
Navigate to the Cloudflare dashboard, select `Compute (Workers)` > `Workers & Pages` > `Create`.
You can choose a custom name for your worker or use the default one. Click "Deploy" when ready.\
Please take note of the url of your worker as this will be needed in your setup of the tracking scripts.
2. Modify the Worker for Proxy Functionality
After deploying your new worker, click "Edit code". If you're already on the worker's page, select "Quick edit". This will open a code editor where you should replace the existing code with the following proxy code:
```javascript theme={null}
const FP_CDN_HOST = "https://cdn.firstpromoter.com/fpr-proxy.js";
const FP_HOST = "https://t.firstpromoter.com";
async function handleRequest(request, ctx) {
const url = new URL(request.url)
const pathname = url.pathname
const search = url.search
const pathWithParams = pathname + search
return forwardRequest(request, pathWithParams)
}
async function forwardRequest(request, pathWithSearch) {
const originRequest = new Request(request)
originRequest.headers.delete("cookie")
return await fetch(`${FP_HOST}${pathWithSearch}`, originRequest)
}
export default {
async fetch(request, env, ctx) {
return handleRequest(request, ctx);
}
};
```
3. When done, click "Save and deploy".
4. Download the tracking scripts from here (Click here) and add it to your main website's public directory.
This will allow it to be fetched from your website. You can change the name of the file to anything but remember to rename it in the main tracking code below.
5. For your main tracking scripts, add the following code. Please replace `` with the url of your worker and `` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
6. Test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected
#### Method 3: Apache setup
1. Find your apache config. Depending on your setup you may need to put the below in your default-ssl.conf file.
`yourdomain.com/tr` will be pointed to `https://t.firstpromoter.com/tr` and `yourdomain.com/tr/get_details` will point to `https://t.firstpromoter.com/get_details`.
Feel free to change `/tr` to anything you want on your domain if you do, you will be required to set the following in your script `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url`
```apache theme={null}
#your other configs
ProxyPass /tr/get_details https://t.firstpromoter.com/get_details
ProxyPassReverse /tr/get_details https://t.firstpromoter.com/get_details
ProxyPass /tr https://t.firstpromoter.com/tr
ProxyPassReverse /tr https://t.firstpromoter.com/tr
```
Feel free to change `/tr` and `/tr/get_details` to anything you want on your domain if you do, you will be required to set the following in your script `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url`
2. Restart your server. `sudo service apache2 restart`
3. Download the FirstPromoter scripts from here (Click here) and add it to your main websites public directory.
This will allow it to be fetched from your website.
4. Add the scripts below directly to your website. Replace `` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
5. Deploy and test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected.
#### Method 4: NGINX setup
1. Find your NGINX config file. This is typically at:
`/etc/nginx/sites-available/yourdomain.com` Or if using a default site: `/etc/nginx/sites-available/default`
Then within the server block, add the proxy rules like this:
```nginx theme={null}
location /tr/get_details {
proxy_pass https://t.firstpromoter.com/get_details;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
location /tr {
proxy_pass https://t.firstpromoter.com/tr;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
```
The contents of your file should look like the following:
```
server {
listen 80;
server_name yourdomain.com;
location /tr/get_details {
proxy_pass https://t.firstpromoter.com/get_details;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
location /tr {
proxy_pass https://t.firstpromoter.com/tr;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
# other configs here
}
```
2. Restart your server. `sudo service nginx restart`
3. Download the FirstPromoter scripts from here (Click here) and add it to your main website's public directory.
This will allow it to be fetched from your website.
4. Add the scripts below directly to your website. Replace `your-account-id-here` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
5. Deploy and test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected
# Tracking with fpr.js
Source: https://docs.firstpromoter.com/guides/tracking-with-fprjs
Track clicks and referrals using the fpr.js scripts
## Installation
First, add the main tracking scripts to your website.
Replace `` with your **actual account id** found in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
## Tracking Flow
### 1. Click Tracking
The main tracking script automatically tracks visitors that come through your affiliate links:
* When a visitor arrives on your website using a referral link the main tracking script will automatically track the click.
* The click sets 2 cookies in the browser - `_fprom_ref` and `_fprom_tid`
* These cookies are used for tracking in future without the need for a referral link.
### 2. Referral Tracking
When a visitor signs up or fills an opt-in form, convert them to a referral by using the signup function:
```html theme={null}
```
You can send only the email or only the uid or both. You need to ensure that the actual visitor data is passed to the function.
### 3. Sales Tracking
If you are using [Stripe](https://login.firstpromoter.com?redirect=%2Fintegration%2Fstripe), [Chargebee](https://login.firstpromoter.com?redirect=%2Fintegration%2Fchargebee), [Braintree](https://login.firstpromoter.com?redirect=%2Fintegration%2Fbraintree), [Paddle](https://login.firstpromoter.com?redirect=%2Fintegration%2Fpaddle) or [Recurly](https://login.firstpromoter.com?redirect=%2Fintegration%2Frecurly) we can track sales automatically on our end. You will only need to connect your billing provider to FirstPromoter.
If you use any other billing provider you will need to track sales using the tracking [API](https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/sales). For more information on sales tracking API, see documentation [here](/api-reference-v2/api-admin/tracking-api/sales)
When a sale event is received, FirstPromoter will automatically:
* Identify the corresponding affiliate to assign the sale to.
* Assign the corresponding reward/commission to the promoter.
With this in place you have completed the basic tracking flow. From tracking of clicks through to assigning the corresponding commissions to the affiliates.
# Tracking without fpr.js
Source: https://docs.firstpromoter.com/guides/tracking-without-fprjs
Track affiliate leads and sales/payments using API calls
Planning to use sub IDs, postbacks or ad tracking? You still need the tracking script for clicks. See [Using sub IDs, postbacks or ad tracking with the API](#using-sub-ids%2C-postbacks-or-ad-tracking-with-the-api) below.
# Tracking Flow
## 1. Store and retrieve link token (Referral ID):
When a visitor arrives through a referral link (e.g., [https://yourdomain.com?fpr=joe13](https://yourdomain.com?fpr=joe13), where `fpr` is the affiliate's Referral ID parameter and `joe13` is the value), retrieve the referral link token (Referral ID) from the referral link, store it in the browser's localStorage or as cookie for later use.
The available query parameters are `?fpr`, `?via`, `?fp_ref`, `?deal`, `?ref`, `?_from`, `?_by`, `?_go` .
### I. Store referral link token implementation
```javascript client side (localStorage implementation) theme={null}
```
```javascript client side (cookie implementation) theme={null}
```
### II. Retrieve referral ID/token
```javascript client-side (localStorage implementation) theme={null}
```
```javascript client side (cookie retrieval implementation) theme={null}
```
```javascript Server Side (cookie retrieval implementation) theme={null}
// backend.js
// this code is just a demonstration of how to retrieve the referral ID/token stored in the cookie.
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.post('/signup', (req, res) => {
// retrieve the referral ID/token (_fprom_ref) from server-side.
const ref_id = req.cookies['_fprom_ref'];
// make API call with ref_id to track referral
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
```
## 2. Lead/Referral tracking
When a visitor signs up or fills an opt-in form, convert them to a referral by using the [track/signup](/api-reference-v2/api-admin/tracking-api/leads-and-signups) endpoint.
You can send only the email or only the uid or both. You need to ensure that the actual visitor data is passed in the API call.
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: ' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer1@gmail.com",
"uid": "cus_000001",
"ref_id": "joe13",
"skip_email_notification": true
}'
```
## Using sub IDs, postbacks or ad tracking with the API
If you want to use **sub IDs**, **postbacks** or **ad tracking**, sending `ref_id` to `track/signup` is not enough. These features rely on data captured when the visitor clicks the referral link: the sub ID (`fp_sid`) from the link, the landing page URL with any ad click IDs, and the visit itself. FirstPromoter only records that data when the click is tracked by the tracking script, and only links it to the referral when you send the visit's `tid`.
A signup tracked with only `ref_id` is credited to the right affiliate, but it has no click attached. Its sub ID will be empty, postback values that come from the visit will be blank, and ad traffic can't be detected.
To keep this data, use the tracking script for clicks and the API for signups:
Add the [main tracking script](/guides/tracking-with-fprjs#installation) to every page a referral link can land on. When a visitor arrives through a referral link, the script tracks the click and sets the `_fprom_ref` and `_fprom_tid` cookies.
If visitors land on one domain and sign up on another, set up [cross-domain tracking](/script-docs/fpr-js-docs) so the cookies are available where the signup happens.
When the visitor signs up, read the `_fprom_tid` cookie on your server (or in the browser and send it to your server with the signup form).
Pass the cookie value in the `tid` parameter of [track/signup](/api-reference-v2/api-admin/tracking-api/leads-and-signups). FirstPromoter uses it to find the tracked click, credit the right affiliate, and attach the sub ID, landing URL and ad data to the referral.
```javascript Server side (Express) theme={null}
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(express.json());
app.post('/signup', async (req, res) => {
// Set by the FirstPromoter tracking script when the visitor clicked a referral link
const tid = req.cookies['_fprom_tid'];
// ...create the user in your app...
if (tid) {
await fetch('https://api.firstpromoter.com/api/v2/track/signup', {
method: 'POST',
headers: {
'Account-ID': '',
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: req.body.email, uid: req.body.uid, tid }),
});
}
res.sendStatus(201);
});
```
```sh cURL theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: ' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer1@gmail.com",
"uid": "cus_000001",
"tid": ""
}'
```
If there is no `_fprom_tid` cookie, the visitor didn't arrive through a tracked referral link (or their browser blocked the cookie), so don't send an empty `tid`. If you still know the referral ID, you can send it as `ref_id` instead, but sub IDs, postback visit data and ad tracking won't be available for that referral.
## 3. Sales Tracking
If you are using [Stripe](https://login.firstpromoter.com?redirect=%2Fintegration%2Fstripe), [Chargebee](https://login.firstpromoter.com?redirect=%2Fintegration%2Fchargebee), [Braintree](https://login.firstpromoter.com?redirect=%2Fintegration%2Fbraintree), [Paddle](https://login.firstpromoter.com?redirect=%2Fintegration%2Fpaddle) or [Recurly](https://login.firstpromoter.com?redirect=%2Fintegration%2Frecurly) we can track sales automatically on our end. You will only need to connect your billing provider to FirstPromoter.
If you use any other billing provider you will need to track sales using the tracking [API](https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/sales). For more information on sales tracking API, see documentation [here](/api-reference-v2/api-admin/tracking-api/sales)
When a sale event is received, FirstPromoter will automatically:
* Identify the corresponding affiliate to assign the sale to.
* Assign the corresponding reward/commission to the promoter.
With this in place, you have completed the basic tracking flow. From storing and retrieval of affiliate referral link token (Referral ID) through to assigning the corresponding commissions to the affiliates.
# How FirstPromoter works
Source: https://docs.firstpromoter.com/how-it-works
Set up and manage your own affiliate program, no matter how simple or complex your affiliate scheme is.
## Setting Up a Campaign
Setting up a campaign with FirstPromoter is seamless and can be done in just a few clicks. During the onboarding process, you will create your first campaign. Each campaign generates a unique signup link that can be shared with your affiliates. When they sign up, FirstPromoter creates a unique referral link using the website URL you provide. Affiliates can then share their referral link with potential customers.
## Click Tracking
Click tracking on FirstPromoter works after adding the main tracking script to your website. It works only once when a user visits a referral link by sending a `click` event to FirstPromoter.
## Referral Tracking
Referral tracking occurs when a lead is captured on your website and sent to FirstPromoter after they sign up or fill out a form. This is achieved via the referral tracking script or API, which requires you to send the referral email address or UID to FirstPromoter.
When a lead visits with a referral link, two cookies, `_fprom_tid` and `_fprom_ref` are set in their browser. These cookies have a default lifespan of 60 days (adjustable in the Admin panel) and are essential for the referral tracking script to function.
## Sales Tracking
Sales tracking is crucial for calculating commissions for affiliates. By default, FirstPromoter automatically tracks sales from providers like `Stripe`, `Chargebee`, `Braintree (subscriptions)`, `Recurly`, `Paddle` by listening to and cross-referencing events sent from the billing provider.
For other billing providers or custom setups, we provide an API to send sales events to FirstPromoter.
# API
Source: https://docs.firstpromoter.com/integrations/billing/api
Tracking sales with API
`Difficulty: Intermediate`
`Developer Required: Yes`
Our API allows you to track sales, refunds, upgrades and cancellations even if you have a billing provider we do not support.
**Precondition**:
You will need to set up an endpoint on your server for which you will receive webhook events from your billing provider.
Once you are receiving webhook events on your server from your billing provider, you can then make a request to FirstPromoter to track sales when events are received.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fcustom) to view the guilde.
# Braintree
Source: https://docs.firstpromoter.com/integrations/billing/braintree
Connecting FirstPromoter with Braintree
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales and cancellations by connecting your Braintree account.
Refund tracking is not currently supported for Braintree. Only successful subscription charges and cancellations are tracked.
**Tracked webhook events:**
| Braintree Event | What FirstPromoter tracks |
| - | - |
| `SubscriptionChargedSuccessfully` | Sale / commission |
| `SubscriptionCanceled` | Cancellation |
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fbraintree) to view the setup guide.
# Chargebee
Source: https://docs.firstpromoter.com/integrations/billing/chargebee
Connecting FirstPromoter with Chargebee
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales, refunds, and cancellations by connecting your Chargebee account.
**Tracked webhook events:**
| Chargebee Event | What FirstPromoter tracks |
| - | - |
| `customer_created` | Signup (only when a tracking ID or referral ID is present) |
| `subscription_created` | Signup (including when a 100% discount is applied and no payment event fires) |
| `payment_succeeded` | Sale / commission |
| `payment_refunded` | Refund |
| `subscription_cancelled` | Cancellation |
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fchargebee) to view the setup guide.
# Paddle
Source: https://docs.firstpromoter.com/integrations/billing/paddle
Connecting FirstPromoter with Paddle
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter supports both **Paddle Classic** (v1 webhooks) and **Paddle Billing** (v2 webhooks), and automatically tracks sales, refunds, and cancellations from your Paddle account.
**Paddle Classic (v1) — tracked webhook events:**
| Paddle Event | What FirstPromoter tracks |
| - | - |
| `payment_succeeded` | Sale / commission |
| `subscription_payment_succeeded` | Sale / commission (recurring) |
| `payment_refunded` | Refund |
| `subscription_payment_refunded` | Refund (recurring) |
| `subscription_cancelled` | Cancellation |
VAT-only refunds (`refund_type` of `vat`) are ignored.
**Paddle Billing (v2) — tracked webhook events:**
| Paddle Event | What FirstPromoter tracks |
| - | - |
| `transaction.completed` | Sale / commission |
| `adjustment.created` | Refund — only when the adjustment's `action` is `chargeback` |
| `adjustment.updated` | Refund — only when the adjustment's `action` is `refund` |
| `subscription.canceled` | Cancellation |
Sales with a zero or negative amount are ignored, as are refunds and chargebacks that resolve to a zero amount.
## Paddle fees and commission amounts
The Paddle integration form has an **Exclude Paddle's fees** toggle that controls the amount commissions are calculated on:
| Toggle | Commission is calculated on |
| - | - |
| Off | Your earnings **plus** Paddle's fee |
| On | Your net earnings, after Paddle's fee is deducted |
This applies to both Paddle Classic and Paddle Billing, and it affects refund amounts as well as sales.
Changing this toggle only affects sales and refunds tracked from that point on. Commissions already recorded are not recalculated.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fpaddle) to view the setup guide.
# Recurly
Source: https://docs.firstpromoter.com/integrations/billing/recurly
Connecting FirstPromoter with Recurly
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales, refunds, and cancellations from your Recurly account.
**Tracked webhook events:**
| Recurly Event | What FirstPromoter tracks |
| - | - |
| `closed_invoice_notification` | Sale / commission |
| `paid_charge_invoice_notification` | Sale / commission |
| `successful_refund_notification` | Refund |
| `void_payment_notification` | Refund (voided payment) |
| `canceled_subscription_notification` | Cancellation |
Only invoices with a positive amount and a status of `collected` or `paid` are tracked as sales.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Frecurly) to view the setup guide.
# Stripe
Source: https://docs.firstpromoter.com/integrations/billing/stripe
Connecting FirstPromoter with Stripe
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales, refunds, and cancellations by connecting your Stripe account in Test or Live mode.
**Tracked webhook events:**
| Stripe Event | What FirstPromoter tracks |
| - | - |
| `invoice.payment_succeeded` | Sale / commission |
| `charge.succeeded` | Sale / commission (one-time charges) |
| `charge.refunded` | Refund |
| `charge.dispute.created` | Refund (disputed charge) |
| `customer.subscription.deleted` | Cancellation |
| `checkout.session.completed` | Signup |
| `customer.discount.created` | Signup (100% discount applied) |
Charges with an amount of zero, or with no associated customer email, are ignored. Invoices with `amount_paid` of zero are also skipped.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fstripe) to view the setup guide.
# API Integration
Source: https://docs.firstpromoter.com/integrations/tracking/custom/api
Track referrals server-side with the FirstPromoter Tracking API
`Difficulty: Intermediate`
`Developer Required: Yes`
With the FirstPromoter Tracking API you can track signups, sales, refunds, and cancellations directly from your backend — no JavaScript required.
**Available endpoints:**
| Endpoint | Purpose |
| - | - |
| `POST /api/v1/track/signup` | Track a lead sign-up |
| `POST /api/v1/track/sale` | Track a sale and generate a commission |
| `POST /api/v1/track/refund` | Track a refund and reverse a commission |
| `POST /api/v1/track/cancellation` | Track a subscription cancellation |
See the [Tracking API reference](/api-reference-v1/tracking-api/leads-and-signups) for full parameter documentation including deduplication via `event_id`, recurring commission scheduling, and custom fields.
## Using sub IDs, postbacks or ad tracking with the API
If you want to use **sub IDs**, **postbacks** or **ad tracking**, sending `ref_id` to `track/signup` is not enough. These features rely on data captured when the visitor clicks the referral link: the sub ID (`fp_sid`) from the link, the landing page URL with any ad click IDs, and the visit itself. FirstPromoter only records that data when the click is tracked by the tracking script, and only links it to the referral when you send the visit's `tid`.
A signup tracked with only `ref_id` is credited to the right affiliate, but it has no click attached. Its sub ID will be empty, postback values that come from the visit will be blank, and ad traffic can't be detected.
To keep this data, use the tracking script for clicks and the API for signups:
Add the [main tracking script](/guides/tracking-with-fprjs#installation) to every page a referral link can land on. When a visitor arrives through a referral link, the script tracks the click and sets the `_fprom_ref` and `_fprom_tid` cookies.
If visitors land on one domain and sign up on another, set up [cross-domain tracking](/script-docs/fpr-js-docs) so the cookies are available where the signup happens.
When the visitor signs up, read the `_fprom_tid` cookie on your server (or in the browser and send it to your server with the signup form).
Pass the cookie value in the `tid` parameter of [track/signup](/api-reference-v2/api-admin/tracking-api/leads-and-signups). FirstPromoter uses it to find the tracked click, credit the right affiliate, and attach the sub ID, landing URL and ad data to the referral.
```javascript Server side (Express) theme={null}
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(express.json());
app.post('/signup', async (req, res) => {
// Set by the FirstPromoter tracking script when the visitor clicked a referral link
const tid = req.cookies['_fprom_tid'];
// ...create the user in your app...
if (tid) {
await fetch('https://api.firstpromoter.com/api/v2/track/signup', {
method: 'POST',
headers: {
'Account-ID': '',
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: req.body.email, uid: req.body.uid, tid }),
});
}
res.sendStatus(201);
});
```
```sh cURL theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: ' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer1@gmail.com",
"uid": "cus_000001",
"tid": ""
}'
```
If there is no `_fprom_tid` cookie, the visitor didn't arrive through a tracked referral link (or their browser blocked the cookie), so don't send an empty `tid`. If you still know the referral ID, you can send it as `ref_id` instead, but sub IDs, postback visit data and ad tracking won't be available for that referral.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fapi) to view the in-app setup guide.
# Django
Source: https://docs.firstpromoter.com/integrations/tracking/custom/django
Adding FirstPromoter to your Django website
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our Django integration option.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fdjango) to view the guide.
# Google Tag Manager
Source: https://docs.firstpromoter.com/integrations/tracking/custom/gtm
Setting up your Main tracking script in Google Tag Manager (GTM)
`Difficulty: Intermediate`
`Developer Required: Yes`
With FirstPromoter you can setup click and signup tracking using our Google Tag Manager option.
This setup mainly requires you to add tracking scripts into your Google Tag Manager and sending details about the referrals using the script.
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
This procedure assumes you have already set up GTM to work on your website.
1. To get started on FirstPromoter:
* [Login](https://login.firstpromoter.com/) to your admin account.
* Navigate to Settings > Integrations > Integrate your website section of your dashboard.
* Click on the `Integrate` button.
* Click on the `setup` button or click on the `change` link for a new setup instructions.
* Under `Custom integration`, select the `JS` option.
* Copy the `Main tracking script` under the `JavaScript` tab.
2. Log in to Google Tag Manager:
* Navigate to your `Tags` section
* Click on `New` button (at top right corner)
* Click on the `Tag configuration` panel to open the TAG type selection panel.
* Scroll down and select the `Custom HTML` option
* Add/paste the `Main tracking script` copied from FirstPromoter into the `HTML` Section. As shown in the screenshot below:
* Now, you need to select when Google Tag Manager should trigger the script. To do this, scroll down to the `triggering` section, click on it and choose when to trigger the tag. We recommend selecting the `pages trigger` to load the `Main tracking script` on all your landing pages.
* Rename/change the name to `FirstPromoter Main Tracking Script`
* Save and publish your changes.
# JavaScript Tracking
Source: https://docs.firstpromoter.com/integrations/tracking/custom/js
Use our Javascript option to track clicks and sign-ups
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our JavaScript integration.
This setup mainly requires you to add tracking scripts into your website or web application integrating it at a code level.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fjavascript) to view the guide.
# Paddle Checkout
Source: https://docs.firstpromoter.com/integrations/tracking/custom/paddle-checkout
Tracking using Paddle Checkout
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
If you are using the paddle checkout feature on your website you can integrate with FirstPromoter.
This setup mainly requires you to add tracking scripts into your website and setting extra configurations on your paddle billing/classic checkout function `Paddle.Checkout.open()` or `Paddle.Initialize()`.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fpaddle-checkout) to view the guide.
# PHP
Source: https://docs.firstpromoter.com/integrations/tracking/custom/php
Adding FirstPromoter to your custom PHP website
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our PHP integration option.
This setup mainly requires you to add tracking scripts into your website or web application integrating it at a code level and sending details about the referrals using the script.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fphp) to view the guide.
# Ruby on Rails
Source: https://docs.firstpromoter.com/integrations/tracking/custom/rails
Adding FirstPromoter to your Rails website
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our Rails integration option.
This setup mainly requires you to add tracking scripts into your website or web application integrating it at a code level and sending details about the referrals using the script.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Frails) to view the guide.
# Stripe Checkout
Source: https://docs.firstpromoter.com/integrations/tracking/custom/stripe-checkout
Tracking using Stripe Checkout
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
If you are using the [stripe checkout feature](https://stripe.com/en-ro/payments/checkout) on your website you can integrate with FirstPromoter.
You should have a checkout page similar to this. Otherwise we suggest you use our JavaScript option instead.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fstripe-checkout) to view the guide.
# Calendly
Source: https://docs.firstpromoter.com/integrations/tracking/platform/calendly
Working with FirstPromoter and Calendly
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our calendly integration option. This integration is for users who have custom websites and have Calendly added.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fcalendly) to view the guide.
# Drop-in Scripts
Source: https://docs.firstpromoter.com/integrations/tracking/platform/chargebee/drop-in-scripts
Integrating FirstPromoter with Chargebee Drop-in Scripts
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our `Chargebee Drop-in Scripts` integration option.
This setup mainly requires you to add/insert our ready made scripts into your website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fchargebee-drop-in-script) to view the guide.
# Hosted Pages
Source: https://docs.firstpromoter.com/integrations/tracking/platform/chargebee/hosted-pages
Integrating FirstPromoter with Chargebee Hosted pages
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our `Chargebee Hosted Pages` integration option.
This setup mainly requires you to add/insert our ready made scripts into your website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fchargebee-hosted-pages) to view the guide.
# ClickFunnels
Source: https://docs.firstpromoter.com/integrations/tracking/platform/clickfunnels
Adding FirstPromoter to your ClickFunnels website
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our ClickFunnels integration option.
This setup mainly requires you to add/insert our ready made scripts into your ClickFunnels website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fclickfunnels) to view the guide.
# Demio
Source: https://docs.firstpromoter.com/integrations/tracking/platform/demio
Adding FirstPromoter to Demio
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our Demio integration option.
This setup mainly requires you to add/insert our ready made scripts into your Demio registration page or your website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fdemio) to view the guide.
# DropFunnels
Source: https://docs.firstpromoter.com/integrations/tracking/platform/dropfunnels
Adding FirstPromoter to your DropFunnels website
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our DropFunnels integration option.
This setup mainly requires you to add/insert our ready made scripts into your DropFunnels website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fdropfunnels) to view the guide.
# Ghost
Source: https://docs.firstpromoter.com/integrations/tracking/platform/ghost
Adding FirstPromoter to your Ghost Website
`Difficulty: Easy`
`Developer Required: No`
The integration between FirstPromoter and Ghost is fully automated and does not require any additional scripts to be added.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fghost) to view the guide.
# Highlevel
Source: https://docs.firstpromoter.com/integrations/tracking/platform/highlevel
Adding FirstPromoter to Highlevel
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Highlevel integration option.
This setup mainly requires you to add/insert our ready made scripts into your Highlevel website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fhighlevel)
# HubSpot
Source: https://docs.firstpromoter.com/integrations/tracking/platform/hubspot
Adding FirstPromoter to your HubSpot form
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking for websites that use HubSpot forms.
This setup mainly requires you to add/insert our ready made scripts into your website or HubSpot-hosted page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fhubspot) to view the guide.
# Jotform
Source: https://docs.firstpromoter.com/integrations/tracking/platform/jotform
Tracking with FirstPromoter when using Jotform
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking using our Jotform integration option.
This setup requires adding our ready made scripts to your landing and thank-you pages, along with a redirect in Jotform to pass the submitted email to your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fjotform) to view the guide.
# Kajabi
Source: https://docs.firstpromoter.com/integrations/tracking/platform/kajabi
Adding FirstPromoter to Kajabi
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Kajabi integration option.
This setup mainly requires you to add/insert our ready made scripts into your Kajabi website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fkajabi) to view the guide.
# Kartra
Source: https://docs.firstpromoter.com/integrations/tracking/platform/kartra
Adding FirstPromoter to Kartra
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Kartra integration option.
This setup mainly requires you to add/insert our ready made scripts into your Kartra website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fkartra) to view the guide.
# Kickpages
Source: https://docs.firstpromoter.com/integrations/tracking/platform/kickpages
Adding FirstPromoter to Kickpages
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Kickpages integration option.
This setup mainly requires you to add/insert our ready made scripts into your Kickpages website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fkickpages) to view the guide.
# Recurly Hosted Pages
Source: https://docs.firstpromoter.com/integrations/tracking/platform/recurly-hosted-pages
Integrating FirstPromoter with Recurly Hosted pages
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup referral tracking using our `Recurly Hosted Pages` integration option. This is only needed if you use Recurly's hosted checkout pages — this setup mainly requires you to add/insert our ready made script into your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Frecurly-hosted-pages) to view the guide.
# Samcart
Source: https://docs.firstpromoter.com/integrations/tracking/platform/samcart
Adding FirstPromoter to Samcart
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Samcart integration option.
This setup mainly requires you to add/insert our ready made scripts into your Samcart website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fsamcart) to view the guide.
# Payment Links
Source: https://docs.firstpromoter.com/integrations/tracking/platform/stripe/payment-links
Adding FirstPromoter when using Stripe payment links
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our `Stripe Payment Links` integration option. This setup mainly requires you to add/insert our ready made scripts into your website pages where you have buy/payment checkout links such as `https://buy.stripe.com/xxxxx`
NB: If you are using your custom domain with stripe, you will need to change the link in the code that will be provided in your FirstPromoter dashboard from `https://buy.stripe.com/` to your checkout page's custom domain.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fstripe-payment-links) to view the guide.
# Pricing Table
Source: https://docs.firstpromoter.com/integrations/tracking/platform/stripe/pricing-table
Adding FirstPromoter when using Stripe pricing table
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our `Stripe Pricing Table` integration option. This setup mainly requires you to add/insert our ready made scripts into your website pages where you have `` html tag.
To get the best results for tracking when using Stripe pricing tables, add the scripts to all pages where `` html tags are available.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fstripe-pricing-table) to view the guide.
# Thinkific
Source: https://docs.firstpromoter.com/integrations/tracking/platform/thinkific
Adding FirstPromoter to Thinkific
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Thinkific integration option.
This setup mainly requires you to add/insert our ready made scripts into your Thinkific website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fthinkific) to view the guide.
# ThriveCart
Source: https://docs.firstpromoter.com/integrations/tracking/platform/thrivecart
Adding FirstPromoter to ThriveCart
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our ThriveCart integration option.
This setup mainly requires you to add/insert our ready made scripts into your ThriveCart website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fthrivecart) to view the guide.
# Typeform
Source: https://docs.firstpromoter.com/integrations/tracking/platform/typeform
Tracking with FirstPromoter when using Typeform
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking using our Typeform integration option.
This setup requires adding our ready made scripts to your landing and thank-you pages, along with a redirect in Typeform to pass the submitted email to your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Ftypeform) to view the guide.
# WebinarJam
Source: https://docs.firstpromoter.com/integrations/tracking/platform/webinarjam
Tracking with FirstPromoter when using WebinarJam registration form
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking using our WebinarJam integration option.
This setup requires adding our ready made scripts to your landing and thank-you/confirmation pages, along with a custom confirmation page redirect in WebinarJam to pass the registrant's email to your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fwebinar-jam) to view the guide.
# WordPress
Source: https://docs.firstpromoter.com/integrations/tracking/platform/wordpress
Add FirstPromoter affiliate tracking to your WordPress website using our dedicated plugin.
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter has a dedicated WordPress plugin that handles click tracking, referral tracking, and sales tracking with built-in support for WooCommerce, MemberPress, Contact Form 7, OptimizePress, custom forms, URL-based email capture, and payment links.
***
## Installing the plugin
1. Log in to your WordPress admin dashboard.
2. Go to **Plugins → Add New**.
3. Search for **"FirstPromoter"** in the search bar.
4. Click **Install Now**, then **Activate**.
Alternatively, download the plugin directly from the WordPress Plugin Directory and upload it manually via **Plugins → Add New → Upload Plugin**.
***
## Base configuration
Once activated, go to **FirstPromoter** in the WordPress admin sidebar.
### Account ID
Required for the tracking script to work on your site.
1. In your FirstPromoter dashboard, go to **Settings → Integrations**.
2. Copy your **Account ID** and paste it into the **Account ID** field in the plugin settings.
### API Key
Required for sale tracking (WooCommerce, MemberPress, Contact Form 7).
1. In your FirstPromoter dashboard, go to **Settings → Integrations → Manage API keys**.
2. Copy your **API key** and paste it into the **API Key** field in the plugin settings.
### Cross-domain tracking *(optional)*
If you have multiple domains that need to share tracking data, enter them as a comma-separated list in the **Cross-domain tracking** field.
```
example.com, shop.example.com
```
Not needed if you are only using subdomains of the same root domain.
### Force tracking for ad-blockers *(optional)*
Enable **Force tracking even in privacy browsers or with ad-blockers** to use a server-side fallback that keeps referral attribution working when the client-side script is blocked.
***
## Integrations
### WooCommerce
The plugin automatically tracks WooCommerce account registrations, checkouts, refunds, and cancellations.
**Signup tracking** — Enable **Capture email on new account creation** and/or **Capture email on checkout** to record the customer's email when they register or complete a purchase. No API key required.
**Sale tracking** — Enable **Send sale to FirstPromoter on checkout** to send order data (amount, order ID, coupon codes) to FirstPromoter when an order is marked as processing or completed. Requires an API key.
The plugin also handles:
* **Refunds** — automatically generates a negative commission when an order is refunded.
* **Cancellations** — updates the customer's status in FirstPromoter when an order is cancelled.
***
### MemberPress
**Signup tracking** — Member registrations are captured automatically when the integration is enabled. No API key required.
**Sale tracking** — Enable **Track sales/transactions via API** to send transaction data to FirstPromoter. Requires an API key.
Enable **Track recurring payments via API** to track subscription renewals. Requires an API key.
If you are already using FirstPromoter's native Stripe integration to track payments, leave MemberPress sale tracking **disabled** to avoid duplicate commissions being recorded.
***
### Contact Form 7
Enable Contact Form 7 tracking to automatically capture form submissions and send them to FirstPromoter. The plugin auto-detects email fields — any field with "email" in its name is captured. Requires an API key.
***
### OptimizePress
Enable OptimizePress tracking to capture form submissions from OptimizePress pages. No API key required.
***
### Custom form tracking
Track email submissions from any form on your site using CSS selectors.
1. Enable **Custom Form Tracking** in the plugin settings.
2. For each form, enter:
* **Email input selector** — CSS selector for the email field (e.g. `input[name="email"]`).
* **Submit selector** — CSS selector for the submit button or form element (e.g. `button[type="submit"]`).
3. To track multiple forms, check **I have multiple forms to track** and add additional selector pairs.
The plugin uses a MutationObserver to detect dynamically loaded forms, including popups and AJAX-injected content. A server-side AJAX fallback is included for cases where ad-blockers interfere (requires **Force tracking** to be enabled).
***
### URL email capture
Useful when an external checkout or funnel redirects back to your WordPress site with the customer's email in the URL (e.g. a thank-you page).
1. Enable **URL Email Capture** in the plugin settings.
2. Enter the **Email URL Parameter Key** — the query parameter name that contains the email.
* Example: for `/thank-you?email=user@example.com`, enter `email`.
3. *(Optional)* Enter the **UID URL Parameter Key** if your platform also passes a user ID.
* Example: for `/thank-you?email=user@example.com&uid=12345`, enter `uid`.
No API key required.
***
### Payment links
Automatically appends the FirstPromoter tracking ID to payment links on your pages as the `client_reference_id` parameter, so conversions through direct payment links are attributed to the right affiliate.
1. Enable **Payment Links** in the plugin settings.
2. Enter the **Payment Link URL Prefix** — links starting with this value will be updated automatically. Defaults to `https://buy.stripe.com/`. Use a comma to separate multiple prefixes.
```
https://buy.stripe.com/, https://checkout.mybrand.com/
```
This integration is for direct payment links embedded on your WordPress pages. If you are not placing `buy.stripe.com` links (or equivalent) directly on your site, this integration is not needed.
# Introduction
Source: https://docs.firstpromoter.com/introduction
Turn Affiliate Marketing into Your Competitive Advantage
## What is FirstPromoter
FirstPromoter is a modern and reliable affiliate tool for subscription-based/SaaS companies that enables you to track, manage and optimize referral-based marketing programs. It is easy to set up, yet powerful to scale with your growing needs.
Instead of coding your own affiliate programs, you can simply integrate with FirstPromoter to handle your affiliate programs for you with a few lines of code.
### Benefits of using FirstPromoter
Set your own domain (with SSL encryption support) for affiliate dashboard and sign up pages.
Give performance bonuses and personalize the commissions and rewards scheme for each affiliate individually.
Oversee the performance of your affiliate program across 18 data points.
Affiliates get commissions only when the purchase is confirmed by your billing provider. We also have algorithms to identify suspicious leads.
No redirects. No ugly short-links. Get the maximum SEO juice with referral links in 8 formats.
Get your teammates inside FirstPromoter. You can set 4 different user roles ( `Manager`, `Admin`, `Admin Plus`, `Super Admin`) and restrict access to certain campaigns.
We support 190 currencies and can do conversions in 170. We use daily updated exchange rates and you can apply your own exchange fee.
Get unlimited flexibility on your affiliates' dashboard. From enabling services like live-chat, surveys or analytics to changing the design completely.
You can embed the affiliate dashboard inside your application and log your users in automatically, without asking them to enter a password or email.
### Key Features
Follow the step-by-step setup to start your first affiliate program, no matter how simple or complex your affiliate scheme is.
Edit the affiliate dashboard to make it yours. Add your colors, logo, and choose the layout that suits you.
Track sales by discount coupon codes alone, email or personalized referral links.
Oversee the performance of your affiliate program across 18 data points.
Pay hundreds of affiliates at once, directly from the FirstPromoter dashboard.
# MCP Server
Source: https://docs.firstpromoter.com/mcp/overview
Connect AI tools like Claude and ChatGPT directly to your FirstPromoter account.
The FirstPromoter MCP server is experimental. The tool surface and authentication flow may change without notice.
The FirstPromoter MCP server lets AI clients like Claude and ChatGPT query your affiliate program and take actions on your behalf — without copying data in and out.
## Example prompts
* "Help me create a new campaign with a 20% sale reward."
* "How are my campaigns performing this month?"
* "Show me pending commissions."
* "Who are my top promoters by revenue?"
* "Find any promoter with 'gmail' in their email."
* "Block promoter Alice on the X campaign."
* "Draft a 3-email onboarding sequence for newly accepted promoters."
## Core capabilities
53 tools covering reads, mutations, and destructive operations across your entire affiliate program. All mutating tools require explicit user approval through a confirmation card — it resolves IDs to human-readable names and shows a field-level diff before applying any change.
Money-movement operations (payouts, invoices, commission creation, payment batches) are intentionally not exposed — they remain dashboard-only. The AI helps you draft and configure; the human commits the money decisions.
## Connect
### Claude (Desktop or Web)
Adding custom connectors requires a paid Claude plan.
1. Navigate to **Customize** and click the **+** icon.
2. Select **Add custom connector**.
3. Fill in the connector details:
* **Name**: FirstPromoter
* **URL**: `https://mcp.firstpromoter.com`
4. Submit. Claude will automatically start the OAuth flow. If it doesn't, click **Connect** on the FirstPromoter tool and try again.
5. Log in with your FirstPromoter account and select the account you want to connect.
### ChatGPT
Adding custom connectors requires Developer Mode to be enabled.
1. Open ChatGPT, click your profile picture, then go to **Settings**.
2. Navigate to **Apps**.
3. Click **Advanced Settings** and toggle **Developer Mode** to ON.
4. Go back to the Apps or Connectors page and click **Create**.
5. Fill in the connector details:
* **Name**: FirstPromoter
* **MCP Server URL**: `https://mcp.firstpromoter.com`
6. Submit. ChatGPT will automatically start the OAuth flow. If it doesn't, click **Connect** and try again.
7. Log in and select the FirstPromoter account to connect.
### Claude Code (CLI)
```bash theme={null}
claude mcp add firstpromoter --transport http https://mcp.firstpromoter.com
```
Run `/mcp` inside a session to verify the connection and browse available tools.
### Cursor / other MCP clients
Add a server entry pointing to `https://mcp.firstpromoter.com` with transport `http`. The client will handle the OAuth flow the first time you use it.
# Available Tools
Source: https://docs.firstpromoter.com/mcp/tools
Full reference for every tool exposed by the FirstPromoter MCP server.
The FirstPromoter MCP server is experimental. Tool names and parameters may change without notice.
## Reports & analytics
| Tool | Description |
| - | - |
| `get_company_context` | Campaigns, currency, active/pending promoter counts. The "what is this company?" entry point. |
| `get_dashboard_stats` | Revenue, referrals, customers, accepted/pending promoters, pending commissions. |
| `get_dashboard_trending` | Top 3 trending promoters and campaigns over the last 30 days. |
| `get_overview_report` | Revenue, referrals, customers, clicks, sales, refunds, and earnings grouped by day, week, month, or year. |
| `get_promoters_report` | Performance ranking per promoter for a date range. |
| `get_campaigns_report` | Performance ranking per campaign for a date range. |
| `get_urls_report` | Landing-page traffic broken down by clicks, customers, sales, and revenue. |
| `get_traffic_sources_report` | Where referral traffic comes from — direct, organic, social, paid. |
## Campaigns
| Tool | Description |
| - | - |
| `list_campaigns` | Every campaign with key metrics. |
| `get_campaign` | Full detail for one campaign by ID. |
| `create_campaign` | New campaign in the company's default program; attach rewards in the same call. |
| `update_campaign` | Change name, landing URL, cookie life, referral param, visibility, attached rewards. |
## Promoters
| Tool | Description |
| - | - |
| `list_promoters` | Filterable by status, signup/approval date, campaign, revenue. Supports a `q` parameter for fuzzy search across email, first/last name, and website. |
| `get_promoter` | Detailed profile, balances, campaign membership, and all profile fields (name, country, address, social URLs, business details). |
| `create_promoter` | New promoter on an initial campaign with profile data. |
| `update_promoter` | Every field the admin Edit modal exposes: email, name, website, company name and number, VAT ID, phone, address, country, PayPal email, social URLs (Facebook, Twitter, Instagram, YouTube, LinkedIn, Twitch, TikTok), admin note, custom fields, and behaviour flags. |
| `accept_promoter` | State change scoped to a single campaign. Verifies the per-campaign state actually persisted before reporting success. |
| `reject_promoter` | State change scoped to a single campaign. |
| `block_promoter` | State change scoped to a single campaign. |
| `add_promoter_to_campaign` | Enrol in an additional campaign without affecting existing memberships. |
| `move_promoter_to_campaign` | Move between campaigns; optionally soft-move existing referrals. |
| `assign_parent_promoter` | Set or remove the parent in a sub-affiliate hierarchy. |
| `restore_promoter` | Bring an archived promoter back — history and referrals preserved. |
| `update_promoter_campaign` | Per-promoter overrides on a specific campaign: ref token, coupon, display coupon, direct URL, state, and reward override. |
## Referrals
| Tool | Description |
| - | - |
| `list_referrals` | Filter by state, date range, campaign, promoter; sorted newest first. |
| `get_referral` | Single referral with promoter, campaign, customer email, and the full event log. |
## Commissions & payouts
| Tool | Description |
| - | - |
| `list_commissions` | Filter by status, date, campaign, promoter. |
| `list_payouts` | Cash rewards paid to promoters; amounts in cents. |
| `mark_commission_fulfilled` | For non-monetary commissions only (badges, points, free months). |
| `mark_commission_unfulfilled` | Revert a fulfilled non-monetary commission. |
## Rewards
| Tool | Description |
| - | - |
| `list_rewards` | All reward rules defined in the company. |
| `get_reward` | Single reward with name, type, schemas, tier level, and coupon. |
| `create_reward` | New commission or discount rule. |
| `update_reward` | Change name, type, schemas, coupon, tier. |
| `hide_reward` | Soft-delete a reward. Existing attachments and pending commissions keep working, but it can no longer be attached to new campaigns or promoters. |
## Promo codes
| Tool | Description |
| - | - |
| `list_promo_codes` | Codes attached to promoters or campaigns. Optionally filter by promoter campaign or include archived. |
| `get_promo_code` | Single code with reward and scope details. |
| `create_promo_code` | New code attached to a reward, optionally scoped to a specific promoter and campaign. |
| `update_promo_code` | Change code, description, reward, scope. |
| `archive_promo_code` | Soft-delete. Preserved for historical reporting; new redemptions are rejected. |
## Products
| Tool | Description |
| - | - |
| `list_products` | SKUs that can have product-specific commission rules attached. |
| `get_product` | Single product detail. |
| `create_product` | New product with name, external billing-provider ID, and prices. |
| `update_product` | Update name, external billing-provider ID, and prices. |
| `delete_product` | Permanent delete. Historical sales referencing the product keep the name as a snapshot. |
## Assets
| Tool | Description |
| - | - |
| `list_assets` | Marketing assets (banners, swipe copy, images) promoters can download. |
| `get_asset` | Single asset detail. |
## Contracts
| Tool | Description |
| - | - |
| `list_contracts` | Affiliate program contracts (Terms of Service, NDAs) that promoters agree to. |
| `get_contract` | Single contract detail. |
## Emails
| Tool | Description |
| - | - |
| `list_emails` | Filter by status (`draft`, `scheduled`, `sent`, `failed`) and trigger event (`promoter_accepted`, `lead_signup`, `reward_created`, etc.). Use this to map an existing onboarding sequence. |
| `get_email` | Full HTML body and trigger configuration for a single email. |
| `create_email` | Draft a new transactional email tied to a trigger event. Created in draft status with the trigger disabled — an admin must review and enable it from the dashboard before anything sends. Merge tags like `{{promoter.first_name}}` and `{{promoter.email}}` are supported in the body. |
| `update_email` | Edit name, subject, body, or trigger on a non-sent email. Cannot touch emails already in sent status, and cannot flip a draft into a scheduled send. |
Broadcast emails and send-now actions are not exposed via MCP — those remain dashboard-only.
# Quickstart
Source: https://docs.firstpromoter.com/quickstart
Start building your awesome affiliate or referral program in minutes.
### Steps
[Click here](https://firstpromoter.com/company/signup) to create an Admin account. If you already have an account, [Login here](https://login.firstpromoter.com/)
If you are a new user, you will need to complete the onboarding process, which involves creating a campaign, connecting your billing provider, and integrating your website.
Connect your billing provider to FirstPromoter. This will enable FirstPromoter to automatically track sales, refunds, upgrades or upsells and cancellations data/record from any of the [supported billing providers](/integrations/billing).
**NB:** For a billing provider that is not supported by default, there is an option to use our [API](/integrations/billing/api)
Install or add our ready-made scripts/pixels to your website or [platform](/integrations/tracking/platform). We also provide [universal scripts and an API for custom-built websites or apps](/integrations/tracking/custom).
Integrating the tracking script into your website enables you to track clicks and referrals (thus, it allows you to send the lead's or referral's details such as the `email` or `uid` to FirstPromoter).
When combined with the billing provider integration, this setup enables FirstPromoter to track sales by linking referral information with transaction data from your billing provider. [Learn more about our tracking script here](/script-docs/fpr-js-docs)
You can also track sales using `Coupon Codes`. This option is available for users who want `No-Code` or `No-Scripts` integration or want an alternative to traditional referral links. [Learn more](https://help.firstpromoter.com/en/articles/8971002-how-to-track-sales-with-coupon-codes-in-firstpromoter)
Test all parts of your integration to make sure everything is tracking.
* Clicks tracking
* Referral tracking
* Sales tracking
# Advanced use cases & examples
Source: https://docs.firstpromoter.com/script-docs/advanced
## Passing the ref id programmatically
`fpr("init",{cid:"...",ref_id:"..."})`
Getting the ref id from the url and passing it to fpr init
```html Custom query parameter theme={null}
```
```html Custom hash theme={null}
```
## Passing the ref id programmatically from a query string
```html theme={null}
```
## Forcing a new tid to be created or reinitializing the FirstPromoter cookies
You can force a new tid to be created by invalidating the old one. This can be done by passing cookie\_ref\_id: 'xxx' as shown in the example below
```js theme={null}
fpr("referral",{email: getParam("wj_lead_email")}, function(){
window.fpr("click",{cookie_ref_id: 'xxx'});
});
```
It can also be used to force new emails to be collected on page refresh
```html theme={null}
```
## Setting a default Promoter
```html theme={null}
```
# Concepts & Key Terminologies
Source: https://docs.firstpromoter.com/script-docs/concepts
List of concepts and key terminologies used in the documentation
## Promoter
Promoters/Affiliates are individuals or companies who drive traffic to a company’s website, products, or services through referral links and earn a commission when that traffic converts.
## Clicks
Clicks are the number of unique visits to your website via the referral link. **NB:** The user's first click on your website via the referral link is what is counted.
## Referral
A referral is an individual or business that signs up for or purchases a service using a referral link. A referral can either be a lead or a customer.
## Lead
A lead is an individual or business that signs up on your website using a referral link but hasn't purchased from your website.
## Customer
A customer is an individual or business that signed up on your website using a referral link and has made at least one purchase from your website.
## Sale
A sale occurs when a customer makes a purchase using a referral link. We generate rewards or commissions only for sales.
## Referral Tracking
This refers to when the referral details (email address/UID) are sent to FirstPromoter from your website after they sign up or fill out a form. This can be done using the referral tracking script or API.
## Sale Tracking
This refers to when payments are tracked from your billing provider, allowing commissions to be generated for your affiliates.
## ref\_id
This is the referral id/token assigned to an affiliate/promoter once they signup or are added to a campaign. It is generated by FirstPromoter by default and can be set using our API as well. If a referral link is used it is set as a cookie `_fprom_ref` in your browser
## tid
This is a tracking ID that is dynamically generated by FirstPromoter when someone visits a referral link. This ID is set as a cookie called `_fprom_tid` in your browser.
# FirstPromoter JavaScript Library (fpr.js)
Source: https://docs.firstpromoter.com/script-docs/fpr-js-docs
This is a reference document for all the methods available in FirstPromoter's browser-side JavaScript Library, fpr.js
# Including fpr.js
On your FirstPromoter dashboard, under the Settings> Integrations> Integrate your website section, based on the selections you make, you are provided with some scripts which are to be added to your website.
It is ideal that the script is added globally on the HEAD section of every marketing or public page of your website.
```html theme={null}
```
For JavaScript frameworks, you can simply insert the script on the public index.html page so it will be available when the framework loads.
For WordPress websites, you can add the scripts to your header.php file before the closing head tag.
To get the best performance, it is ideal that you have the scripts added to all the pages where you need tracking to take place. Also, the Scripts are loaded asynchronously and will not affect the website loading speed.
# Functions
## fpr("init",options, callback?)
This method initializes FirstPromoter with the provided options. Most of these options are loaded automatically when the script loads, but they can be overwritten by passing different ones to the method. The most used one is "ref\_id" which forces the script to track a specific promoter.
### Parameters
#### Available keys
| Property | Description |
| - | - |
| cid | FirstPromoter Company Id (required) |
| ref\_id | Referral id/token of the promoter |
| tid | Tracking ID, value stored in fprom\_tid cookie |
| url | Current URL |
| domain | Current domain |
| referrer | Browser referrer/ domain of the previous visited website |
Setting properties that are not in the list above will be ignored.
A function that will be called after the init function is triggered.
## fpr("click",payload?, callback?)
This method is responsible for click tracking.
### Parameters
This overwrites the stored data exactly like the fpr("init"…) function does before tracking the click.
#### Available keys
| Property | Description |
| - | - |
| cid | FirstPromoter Company Id |
| ref\_id | Referral id/token of the promoter |
| tid | Tracking ID, value stored in fprom\_tid cookie |
| url | Current URL |
| domain | Current domain |
| referrer | Browser referrer/ domain of the previous visited website |
Setting properties that are not in the list above will be ignored.
The callback function receives the response data object and can then be extracted and used
### Example
```javascript click theme={null}
fpr("click")
```
```javascript click_with_referral_id theme={null}
fpr("click", {ref_id: 'xxx'})
```
***
## fpr("onReady",callback)
This method checks if the tracking script is initialized and fully loaded on the page.
### Parameters
The callback function receives the response data object and can then be extracted and used
### Example
```javascript click theme={null}
fpr("onReady", function(data){
console.log(data)
})
```
***
## fpr("referral",payload, callback?)
This method is used primarily to send the referral details to FirstPromoter. It takes as its payload the email of the referral/lead
### Parameters
The callback function receives the response data object and can then be extracted and used
#### Available keys
| Property | Description |
| - | - |
| email | actual email of the user |
| uid | user id of the user |
Setting properties that are not in the list above will be ignored.
### Example
```javascript referral theme={null}
fpr('referral',{email:actual_user_email@email.com, uid: 123456})
```
```javascript referral_with_callback theme={null}
fpr('referral',{email:actual_user_email@email.com, uid: 123456},
function(){console.log("referral submitted")
})
```
***
## fpr("details",callback)
This method is used in getting the details of the promotion and the promoter. **To avoid making multiple requests, it is important to note that the details are stored in a cookie called "fprom\_details" and is available for a day.**
### Parameters
The callback function receives the response data object and can then be extracted and used
### Response Format
```javascript theme={null}
{
ref_id:
promo_code:
campaign_id:
customer_promo_code:
offer:
promoter: {
id:
first_name:
last_name:
}
}
```
### Example
```javascript click theme={null}
fpr("details", function(data){
console.log(data)
})
```
***
## fpr("crossDomain",domains)
This method is used when attempting to track across multiple domains. It mainly appends the tracking details to all links to the domain provided. Note: this works with only direct links and should be added preferably to the footer section or called when the whole page is loaded
The crossDomain(s) you want to track
### Example
```javascript one domain theme={null}
fpr('crossDomain','newwebsite.com')
```
```javascript multiple domains theme={null}
fpr('crossDomain',['newwebsite.com', 'newwebsite1.com', 'newwebsite2.com'])
```
## fpr("urlTracking")
This method is used for Direct URL tracking, thus, if you have landing pages for your affiliates/promoters, you can use the method on those pages if you don't want the affiliates/promoters "Referral ID" to be part of their referral links.
For this method to work, you will have to first add FirstPromoter's main tracking scripts to the landing page(s) and also enable "Direct URL tracking" on FirstPromoter. To do so, please check out this article: [How to enable direct URL tracking in FirstPromoter](https://help.firstpromoter.com/en/articles/8971394-how-to-enable-direct-url-tracking-in-firstpromoter)
Please note that the method **should not** be used on your homepage, but instead should only be used on all landing pages of your affiliates/promoters.
```js theme={null}
```
# Delivery Tracking & Retries
Source: https://docs.firstpromoter.com/webhooks-v2/deliveries
Monitor delivery attempts, understand retry behaviour, and manually retry failed deliveries.
Every time FirstPromoter attempts to send a webhook, a delivery record is created and tracked. You can inspect these records via the dashboard to debug failed deliveries.
## Delivery statuses
| Status | Meaning |
| - | - |
| `pending` | Delivery has been queued but not yet attempted. |
| `delivered` | Your endpoint returned a `2xx` response. |
| `retrying` | A delivery attempt failed; more retries are scheduled. |
| `failed` | All retry attempts were exhausted without a successful response. |
## Retry behaviour
When a delivery attempt fails (non-`2xx` response, timeout, or network error), FirstPromoter waits before retrying. The delay uses exponential backoff, roughly doubling with each attempt:
| Attempt | Delay before retry |
| - | - |
| 1st retry | \~2 minutes |
| 2nd retry | \~4 minutes |
| 3rd retry | \~8 minutes |
| 4th retry | \~16 minutes |
| 5th retry | \~32 minutes |
| 6th retry | \~1 hour |
| 7th retry | \~2 hours |
| 8th retry | \~4 hours |
| 9th retry | \~8.5 hours |
Retries stop when the number of failed attempts reaches the `max_retries` value configured on the subscription (default: `10`, configurable from `0`–`10`). After that, the delivery is marked `failed`. At the default of `10`, retries span roughly 17 hours from the first failure.
Set `max_retries` to `0` on a subscription to disable retries entirely.
## Delivery record fields
Internal ID of the delivery record.
The UUID of the event. Matches `event_id` in the payload.
The event type string, e.g. `commission.updated`.
`created`, `updated`, or `deleted`.
The type of the resource, e.g. `referral`.
The ID of the resource.
Current status: `pending`, `delivered`, `retrying`, or `failed`.
How many delivery attempts have been made so far.
The HTTP status code returned by your endpoint on the last attempt.
The first 1,000 characters of your endpoint's response body.
A description of the last error (e.g., timeout message, HTTP error). Up to 1,000 characters.
For `updated` events, the fields that changed (same as `changes` in the payload).
The full JSON payload that was (or will be) sent to your endpoint.
ISO 8601 timestamp of the successful delivery. `null` until delivered.
When the delivery record was created.
## Viewing deliveries
You can view delivery history for any subscription from the **Settings → Integrations → Webhooks** page in the dashboard. Click into a subscription to see all delivery attempts, their status, response codes, and error details.
## Manually retrying a failed delivery
You can re-attempt a delivery directly from the dashboard without waiting for the automatic retry schedule, as long as it still has retry budget remaining (its `attempts` count is below the subscription's `max_retries`). Navigate to the subscription's delivery history and click **Retry** on the delivery.
A delivery only reaches `failed` status once it has exhausted the subscription's `max_retries`, so a delivery that is already `failed` cannot be retried as-is — increase `max_retries` on the subscription first to free up retry budget, then retry the delivery.
## Sending a test delivery
When setting up a new subscription you can send a test payload to your endpoint from the dashboard without needing to trigger a real event. Navigate to the subscription and click **Send test**. The test payload has `"data": { "test": true }` just like a real delivery.
# Event Types
Source: https://docs.firstpromoter.com/webhooks-v2/event-types
All event types available for webhooks v2 subscriptions.
Event types follow the format `{entity}.{action}` (e.g., `promoter.created`). When subscribing, you provide the exact event type strings you want to receive.
## Promoters
| Event type | Description |
| - | - |
| `promoter.created` | A new promoter signed up or was created via the API. |
| `promoter.updated` | A promoter's account details were changed. |
| `promoter.deleted` | A promoter was deleted. |
| `promoter.balance.updated` | A promoter's earnings, current, or paid balance changed. |
## Promoter campaigns
| Event type | Description |
| - | - |
| `promoter_campaign.created` | A promoter was added to a campaign. |
| `promoter_campaign.updated` | A promoter's participation in a campaign was changed (e.g., status, ref\_token). |
| `promoter_campaign.deleted` | A promoter was removed from a campaign. |
| `promoter_campaign.accepted` | A promoter's campaign application was accepted. |
| `promoter_campaign.pending` | A promoter's campaign participation was set to pending review. |
| `promoter_campaign.rejected` | A promoter's campaign application was rejected. |
| `promoter_campaign.blocked` | A promoter was blocked from a campaign. |
| `promoter_campaign.inactive` | A promoter was set to inactive in a campaign. |
## Referrals
| Event type | Description |
| - | - |
| `referral.created` | A new referral (lead or customer) was tracked. |
| `referral.updated` | A referral's details changed (e.g., state, plan, cancellation). |
| `referral.deleted` | A referral was deleted. |
| `referral.converted` | A referral (lead) was converted to a customer. |
| `referral.cancelled` | A referral was cancelled. |
| `referral.moved` | A referral was moved from one campaign to another. Only fires when an affiliate crosses a campaign upgrade/downgrade threshold and the campaign has referral moving enabled. |
## Commissions
| Event type | Description |
| - | - |
| `commission.created` | A new commission was created. |
| `commission.updated` | A commission was updated. The `changes` field in the payload contains the specific fields that changed. |
| `commission.deleted` | A commission was deleted. |
| `commission.approved` | A commission was approved. |
| `commission.pending` | A commission was set to pending. |
| `commission.denied` | A commission was denied. |
## Payouts
| Event type | Description |
| - | - |
| `payout.created` | A new payout was created. |
| `payout.updated` | A payout was updated. |
| `payout.deleted` | A payout was deleted. |
| `payout.pending` | A payout was set to pending. |
| `payout.processing` | A payout started processing. |
| `payout.completed` | A payout was completed successfully. |
| `payout.failed` | A payout failed. |
| `payout.cancelled` | A payout was cancelled. |
| `payout.commissions.added` | A commission was added to a payout. |
| `payout.commissions.removed` | A commission was removed from a payout. |
## Payout methods
| Event type | Description |
| - | - |
| `payout_method.created` | A promoter added a new payout method. |
| `payout_method.updated` | A payout method was updated. |
| `payout_method.deleted` | A payout method was removed. |
## Payments batches
| Event type | Description |
| - | - |
| `payments_batch.created` | A new payment batch was created. |
| `payments_batch.updated` | A payment batch was updated. |
| `payments_batch.deleted` | A payment batch was deleted. |
| `payments_batch.initiated` | A payment batch was initiated. |
| `payments_batch.processing` | A payment batch started processing. |
| `payments_batch.completed` | A payment batch completed successfully. |
| `payments_batch.failed` | A payment batch failed. |
## Contract documents
| Event type | Description |
| - | - |
| `contract_document.signed` | A promoter signed a contract document. |
# Non-Monetary Rewards
Source: https://docs.firstpromoter.com/webhooks-v2/non-monetary-rewards
How to listen to webhook events and use the API to fulfill non-monetary rewards such as points, credits, and free months.
Non-monetary rewards are commissions where affiliates (promoters) or referred customers earn something other than a cash payout — such as points, credits, free months, or discounts. Because there is no payment provider involved, **your system is responsible for delivering the reward**. FirstPromoter handles tracking, approval, and state management. Your integration handles the actual delivery and marks each reward as complete.
## Supported reward types
| Type | Description |
| - | - |
| `points` | Loyalty or reward points |
| `credits` | Account credits |
| `free_months` | Free subscription months |
| `mon_discount` | Fixed monetary discount |
| `discount_per` | Percentage-based discount |
These can be configured independently for **promoters** (what the affiliate earns) and **referrals** (what the referred customer receives) within a campaign.
## The complete flow
```
Sale tracked
│
▼
Commission created → status: pending
│ webhook: commission.created
▼
Commission approved → status: approved
│ webhook: commission.updated (changes.status: ["pending", "approved"])
▼
Your system delivers the reward
│ POST /commissions/mark_fulfilled
▼
Commission marked as fulfilled
```
## Webhook events to listen to
Subscribe to the following event types when creating your webhook subscription in **Settings → Integrations → Webhooks**. See [Event Types](/webhooks-v2/event-types) for the full list.
### `commission.created`
Fired when a new commission is tracked and enters `pending` status.
Use this to log or notify internally that a reward has been earned. **Do not fulfill the reward at this stage** — the commission has not been approved yet.
### `commission.updated`
Fired when a commission is updated. Filter on `changes.status` in the payload to react to specific transitions:
| `changes.status` | Meaning |
| - | - |
| `["pending", "approved"]` | Commission was approved — deliver the reward and call `mark_fulfilled` |
| `["pending", "denied"]` | Commission was denied — no reward should be issued |
**This is your trigger to act.** When `changes.status` shows `["pending", "approved"]`, deliver the reward in your system and call the `mark_fulfilled` endpoint.
## Example payloads
```json theme={null}
{
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "commission.created",
"action": "created",
"entity_type": "commission",
"entity_id": 88901,
"changes": {},
"data": {
"id": 88901,
"status": "pending",
"amount": 500,
"unit": "points",
"referral": {
"id": 55678,
"email": "user@example.com",
"uid": "user_ext_id"
},
"created_at": "2025-01-18T09:00:00Z"
},
"timestamp": "2025-01-18T09:00:01Z"
}
```
```json theme={null}
{
"event_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"event_type": "commission.updated",
"action": "updated",
"entity_type": "commission",
"entity_id": 88901,
"changes": {
"status": ["pending", "approved"]
},
"data": {
"id": 88901,
"status": "approved",
"amount": 500,
"unit": "points",
"referral": {
"id": 55678,
"email": "user@example.com",
"uid": "user_ext_id"
},
"created_at": "2025-01-18T09:00:00Z"
},
"timestamp": "2025-01-19T10:30:00Z"
}
```
## API endpoints
All requests require the `Account-ID` header. You can find your Account ID in **Settings → Integrations**.
### List commissions
Retrieve commissions filtered by status or unit type.
```bash theme={null}
GET https://api.firstpromoter.com/api/v2/company/commissions?status=approved
```
| Query parameter | Description |
| - | - |
| `status` | Filter by status: `pending`, `approved`, `denied` |
| `unit` | Filter by reward type: `points`, `credits`, `free_months`, `mon_discount`, `discount_per` |
### Approve commissions
If auto-approve is not enabled on your campaign, commissions must be approved before a payout record is created.
```bash theme={null}
POST https://api.firstpromoter.com/api/v2/company/commissions/approve
Account-ID:
Content-Type: application/json
{
"ids": [88901, 88902]
}
```
If more than 5 IDs are provided, the operation runs asynchronously and the response will have status `in_progress`. Poll or listen to `commission.updated` events to track completion.
### Mark commissions as fulfilled
Call this after you have delivered the reward in your system. This moves the linked payout to `completed` and triggers the `payout.updated` webhook.
```bash theme={null}
POST https://api.firstpromoter.com/api/v2/company/commissions/mark_fulfilled
Account-ID:
Content-Type: application/json
{
"ids": [88901, 88902]
}
```
This endpoint only works on **non-monetary commissions** that have an associated payout record. If the commission has not been approved yet, the call will return an error. Ensure the commission is in `approved` status before calling this.
### Mark commissions as unfulfilled
To reverse a fulfillment — for example if delivery failed on your end — move the payout back to `pending`:
```bash theme={null}
POST https://api.firstpromoter.com/api/v2/company/commissions/mark_unfulfilled
Account-ID:
Content-Type: application/json
{
"ids": [88901]
}
```
## Rewards for promoters vs. referrals
Both promoter rewards and referral rewards can be non-monetary and follow the same webhook and API flow. Use the payload data to distinguish which party should receive the reward.
| | Promoter reward | Referral reward |
| - | - | - |
| Who receives it | The affiliate who drove the sale | The customer who was referred |
| Configured in | Campaign → Promoter rewards | Campaign → Referral rewards |
| Webhook events | Same (`commission.*`, `payout.*`) | Same |
| API endpoints | Same | Same |
## Recommended integration pattern
When `changes.status` is `["pending", "approved"]`, read the `amount`, `unit`, and promoter or referral ID from the payload.
Apply the points, credits, or discount in your platform.
POST to `/commissions/mark_fulfilled` with the commission ID to confirm delivery and close the loop in FirstPromoter.
## Setup checklist
Campaign has a non-monetary reward type configured (points, credits, free months, or discount)
Webhook subscription created for `commission.created` and `commission.updated`
Your system calls `mark_fulfilled` after successfully delivering the reward
Auto-approve is enabled on the campaign, or you have a flow to call the approve endpoint before fulfilling
# Webhooks v2 Overview
Source: https://docs.firstpromoter.com/webhooks-v2/overview
Subscribe to real-time events from your FirstPromoter account with the new webhooks system.
Webhooks v2 is a complete rewrite of the FirstPromoter webhook system. Instead of a fixed set of webhook URLs per campaign, you can now create multiple independent subscriptions with fine-grained control over which events and campaigns trigger them.
## What's new in v2
| Feature | Legacy webhooks | Webhooks v2 |
| - | - | - |
| Subscriptions | 3 hardcoded URLs per campaign | Unlimited subscriptions per account |
| Event types | Fixed predefined list | Dynamic pattern-based selection |
| Campaign filtering | No — all events always fired | Subscribe to specific campaigns |
| Delivery tracking | Limited | Full history with status and response details |
| Retry control | Basic | 3 retries by default |
| Timeout | Fixed 15 s | 30 s by default |
| Custom headers | Not supported | Arbitrary key/value headers |
## Setting up a subscription
Navigate to **Settings → Integrations → Webhooks** and click **Add new webhook**.
### Subscription fields
The HTTPS endpoint that will receive webhook payloads. Must be a valid URL.
One or more event type strings to subscribe to. See [Event Types](/webhooks-v2/event-types) for the full list.
Limit this subscription to events from specific campaigns. Use `[1]` (the default) to receive events from all campaigns.
Optional human-readable label for this subscription.
Enable or pause delivery without deleting the subscription. Defaults to `true`.
Custom HTTP headers to include on every request. Useful for API keys or authorization tokens your endpoint requires.
```json theme={null}
{ "Authorization": "Bearer my-token", "X-My-Header": "value" }
```
## How delivery works
1. An event occurs in your account (e.g., a referral is created).
2. FirstPromoter checks your active subscriptions for matching event types and campaign filters.
3. A delivery record is created for each matching subscription and dispatched asynchronously.
4. Your endpoint receives a `POST` request with a JSON payload.
5. Respond with any `2xx` status code to acknowledge the delivery.
6. If the response is not `2xx`, the delivery is automatically retried.
# Payload Structure
Source: https://docs.firstpromoter.com/webhooks-v2/payload
The JSON payload sent to your webhook endpoint for every event.
Every webhook request is a `POST` with a `Content-Type: application/json` body. The top-level shape is the same for all event types.
## Top-level fields
A unique UUID for this event. Use this to deduplicate deliveries — if your endpoint receives the same `event_id` twice, you can safely ignore the second one.
The event type string, e.g. `referral.created`. Matches the event types listed on the [Event Types](/webhooks-v2/event-types) page.
The action that triggered the event. One of `created`, `updated`, or `deleted`.
The type of the resource that changed, e.g. `promoter`, `referral`, `commission`.
The database ID of the resource.
For `updated` events, an object containing the fields that changed. Each key maps to an array of `[old_value, new_value]`. Empty for `created` and `deleted` events (the full resource is in `data` instead).
```json theme={null}
{
"status": ["pending", "active"],
"email": ["old@example.com", "new@example.com"]
}
```
The full serialized state of the resource at the time of the event. The exact fields depend on the `entity_type`. See the examples below.
ISO 8601 timestamp of when the event occurred.
## Example payloads
```json theme={null}
{
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "promoter.created",
"action": "created",
"entity_type": "promoter",
"entity_id": 12345,
"changes": {},
"data": {
"id": 12345,
"email": "jane@example.com",
"name": "Jane Smith",
"cust_id": "cus_abc123",
"balances": {},
"joined_at": "2025-01-15T10:30:00Z",
"profile": {
"id": 98765,
"first_name": "Jane",
"last_name": "Smith",
"website": "https://janesmith.com",
"company_name": "",
"phone_number": "",
"address": "",
"country": "US",
"paypal_email": "",
"avatar": ""
}
},
"timestamp": "2025-01-15T10:30:00Z"
}
```
```json theme={null}
{
"event_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"event_type": "referral.updated",
"action": "updated",
"entity_type": "referral",
"entity_id": 55678,
"changes": {
"state": ["signup", "active"],
"customer_since": [null, "2025-01-20T14:00:00Z"]
},
"data": {
"id": 55678,
"state": "active",
"email": "user@example.com",
"uid": "user_ext_id",
"customer_since": "2025-01-20T14:00:00Z",
"fraud_check": "no_suspicion",
"created_at": "2025-01-18T09:00:00Z"
},
"timestamp": "2025-01-20T14:00:05Z"
}
```
```json theme={null}
{
"event_id": "c3d4e5f6-a7b8-9012-cdef-012345678902",
"event_type": "commission.updated",
"action": "updated",
"entity_type": "commission",
"entity_id": 88901,
"changes": {
"status": ["pending", "approved"]
},
"data": {
"id": 88901,
"status": "approved",
"amount": 2500,
"unit": "cash",
"referral": {
"id": 55678,
"email": "user@example.com",
"uid": "user_ext_id"
},
"created_at": "2025-01-18T09:00:00Z"
},
"timestamp": "2025-01-21T11:15:00Z"
}
```
```json theme={null}
{
"event_id": "d4e5f6a7-b8c9-0123-defa-123456789012",
"event_type": "contract_document.signed",
"action": "updated",
"entity_type": "contract_document",
"entity_id": 4421,
"changes": {
"signed_at": [null, "2025-01-22T08:45:00Z"]
},
"data": {
"id": 4421,
"promoter_id": 12345,
"signed_at": "2025-01-22T08:45:00Z",
"created_at": "2025-01-10T12:00:00Z"
},
"timestamp": "2025-01-22T08:45:03Z"
}
```
## Request headers
In addition to the JSON body, every request includes these headers:
| Header | Description |
| - | - |
| `Content-Type` | Always `application/json` |
| `X-Event-Id` | Same value as `event_id` in the payload. Useful for logging and deduplication at the transport layer. |
| `X-Event-Type` | Same value as `event_type` in the payload. |
Any custom headers you configured on the subscription are also included.
# Get all payouts
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/payouts/get-all-payouts
openapi-v2-payouts get /payouts
With this endpoint you can list all payouts.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/payouts`
# Get all payouts grouped by promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/payouts/get-all-payouts-grouped-by-promoters
openapi-v2-payouts get /payouts/group_by_promoters
This endpoint returns all payouts but grouped by promoters.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/payouts/group_by_promoters`
# Get due payout stats
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/payouts/get-due-payout-stats
openapi-v2-payouts get /payouts/due_stats
This endpoint returns statistics about due payouts.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/payouts/due_stats`
# Get payout stats
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/payouts/get-payout-stats
openapi-v2-payouts get /payouts/stats
This endpoint returns statistics about payouts.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/payouts/stats`
# Archive promo code by id
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promo-codes/archive-promo-code-by-id
openapi-v2-promocodes delete /promo_codes/{id}
Archive promo code by id.
**HTTP Request**
`DELETE https://api.firstpromoter.com/api/v2/company/promo_codes/{id}`
# Create promo code (Stripe Only)
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promo-codes/create-promo-code
openapi-v2-promocodes post /promo_codes
With this endpoint you can create a new promo code.
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/company/promo_codes`
# Get promo code by id
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promo-codes/get-promo-code-by-id
openapi-v2-promocodes get /promo_codes/{id}
With this endpoint you can get the details of a specific promo code.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promo_codes/{id}`
# Get promo codes
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promo-codes/get-promo-codes
openapi-v2-promocodes get /promo_codes
With this endpoint you can list all promo codes.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/promo_codes`
# Update promo code by id
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/promo-codes/update-promo-code-by-id
openapi-v2-promocodes put /promo_codes/{id}
Update promo code by id. Can not be updated if archived and ext_id present.
**HTTP Request**
`PUT https://api.firstpromoter.com/api/v2/company/promo_codes/{id}`
# Get reports for campaigns
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/reports/get-reports-for-campaigns
openapi-v2-reports get /reports/campaigns
With this endpoint you can get the report data grouped by campaigns.**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/reports/campaigns`
# Get reports for overview
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/reports/get-reports-for-overview
openapi-v2-reports get /reports/overview
Get reports for overview
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/reports/overview`
# Get reports for promoters
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/reports/get-reports-for-promoters
openapi-v2-reports get /reports/promoters
With this endpoint you can get the report data grouped by promoters.**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/reports/promoters`
# Get reports for traffic sources
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/reports/get-reports-for-traffic-sources
openapi-v2-reports get /reports/traffic_sources
With this endpoint you can get the report data grouped by traffic sources.
**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/reports/traffic_sources`
# Get reports for URLs
Source: https://docs.firstpromoter.com/api-reference-v2/api-admin/reports/get-reports-for-urls
openapi-v2-reports get /reports/urls
With this endpoint you can get the report data grouped by URLs.**HTTP Request**
`GET https://api.firstpromoter.com/api/v2/company/reports/urls`
# Embed the Dashboard & Auto-Login Promoters
Source: https://docs.firstpromoter.com/advanced/embed-dashboard-login
Embed the full promoter dashboard inside your own app as an iframe and automatically sign promoters in — no separate URL, no credentials.
FirstPromoter lets you embed the complete promoter dashboard inside your own app and automatically log the visiting promoter in, so they never have to leave your app or enter credentials manually. Your backend requests a short-lived access token for the promoter, and you pass that token to the iframe.
**Requirements**
* A custom domain configured on your FirstPromoter account
* Business plan or higher
* Server-side access to make authenticated API requests — the access token must always be generated on your backend. Never call this endpoint or expose your API key from the browser.
## How it works
They're already authenticated in your product, and you know their FirstPromoter promoter ID (or the `cust_id` you assigned them).
Your server calls the `iframe_login` endpoint with that promoter's ID. FirstPromoter returns a bearer token scoped to that promoter and your account.
Pass the token as the `tk` query parameter on the iframe `src`. FirstPromoter validates it and loads the dashboard already signed in.
## Step 1 — Get your API credentials
Go to **Settings → Integrations → Manage API Keys** and note two values:
* **Account ID** — identifies your FirstPromoter account
* **API Key** — used to authenticate the server-side request (use a v2 key)
Keep both server-side only.
## Step 2 — Generate an access token
From your backend, make a `POST` request to the iframe login endpoint:
```
POST https://v2.firstpromoter.com/api/v2/promoters/iframe_login
```
The FirstPromoter promoter ID. Provide this or `cust_id`.
The external customer ID you assigned this promoter when they signed up. Provide this or `promoter_id`.
`Bearer {your_api_key}`
`{your_account_id}`
The request body is empty. On success you get back a bearer token:
Short-lived bearer token for this promoter, scoped to your account.
Token lifetime in seconds. Defaults to `86400` (24 hours).
```json theme={null}
{
"access_token": "xxxxxxxxxxxxxxx",
"expires_in": 86400
}
```
Generate a fresh token on every page load — don't cache or reuse tokens across sessions or share one token between promoters.
## Step 3 — Find the promoter's ID
You need the FirstPromoter `promoter_id` (not your own internal user ID) — or the `cust_id` you gave them. Get it from:
* The API response when the promoter was originally created
* The [Promoters API](/api-reference-v2/api-admin/promoters/get-available-promoters) filtered by `cust_id`
* The `promoter_accepted` webhook payload
## Step 4 — Embed the iframe
Use the access token as the `tk` query parameter on the iframe `src`:
```html theme={null}
```
`allow="clipboard-write"` is required for the copy-to-clipboard buttons inside the dashboard (referral links, promo codes, etc.).
### Targeting a specific campaign
If a promoter belongs to more than one campaign and you want the dashboard to open directly on a particular one, append `campaign_id`:
```
/iframe?tk={access_token}&campaign_id={campaign_id}
```
You can also pass a comma-separated list — the dashboard opens on the first matching campaign the promoter belongs to:
```
/iframe?tk={access_token}&campaign_id={id1},{id2}
```
## Code examples
```js Node.js (Express) theme={null}
const express = require("express");
const app = express();
app.get("/dashboard", async (req, res) => {
const promoterId = req.user.firstpromoterPromoterId; // your stored promoter ID
const response = await fetch(
`https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=${promoterId}`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FP_API_KEY}`,
"Account-Id": process.env.FP_ACCOUNT_ID,
},
}
);
const { access_token } = await response.json();
res.render("dashboard", { accessToken: access_token });
});
```
```php PHP theme={null}
firstpromoter_promoter_id;
$ch = curl_init(
"https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=" . urlencode($promoterId)
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $_ENV["FP_API_KEY"],
"Account-Id: " . $_ENV["FP_ACCOUNT_ID"],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
$accessToken = $response["access_token"];
?>
```
```sh cURL theme={null}
curl --request POST \
--url 'https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=12345' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Account-Id: YOUR_ACCOUNT_ID'
```
Then render the iframe once you have the token:
```jsx React theme={null}
import { useEffect, useState } from "react";
export function PromoterDashboard() {
const [token, setToken] = useState(null);
useEffect(() => {
fetch("/api/fp-token")
.then((res) => res.json())
.then((data) => setToken(data.token));
}, []);
if (!token) return Loading dashboard…
;
return (
);
}
```
```vue Vue theme={null}
Loading dashboard…
```
```html Vanilla JS theme={null}
```
`/api/fp-token` above is your own protected backend route that performs the Step 2 request and returns `{ token: access_token }` — the same pattern as the Node.js example.
## Security considerations
* **Never call `iframe_login` from the browser.** Your API key must stay server-side behind a route that requires the visitor to already be authenticated in your app.
* **Only embed the iframe on authenticated, non-public pages.** The token grants full dashboard access for that promoter.
* **Generate a fresh token on every page load.** Tokens expire after `expires_in` seconds (24 hours by default) — don't cache or share them between users.
## Related
* [Log promoters out of the embedded dashboard](/advanced/embed-dashboard-logout)
* [Promoters API reference](/api-reference-v2/api-admin/promoters/get-available-promoters)
# Log Promoters Out of the Embedded Dashboard
Source: https://docs.firstpromoter.com/advanced/embed-dashboard-logout
End a specific promoter's embedded dashboard session from your backend, or let promoters sign out from inside the iframe itself.
If you [embed the promoter dashboard and auto-login promoters](/advanced/embed-dashboard-login), you'll also want a way to end that session — either because the promoter logged out of your app, or because you want to immediately cut off a specific promoter's access instead of waiting for their token to expire.
There are two independent ways a promoter's embedded session ends:
The promoter clicks **Log out** inside the embedded dashboard itself. No API call needed — this happens automatically.
Your backend calls `iframe_logout` for a specific promoter, revoking their access immediately — for example when the corresponding user logs out of your app.
## Self-service logout
When a promoter clicks **Log out** from the account menu inside the embedded dashboard, FirstPromoter revokes **every active session that promoter currently has under your account** — not just the tab or page they clicked logout from — and returns them to a signed-out state within the iframe. This requires no setup and no API call on your side — it's built into the dashboard.
Because every session is revoked, this also signs the promoter out of any other tab where you've embedded their dashboard. If your app issues a fresh token on every page load (as recommended in the [login guide](/advanced/embed-dashboard-login)), reloading the page after this will silently log the promoter back in. If you want the logout to stick, pair it with the targeted logout below, triggered from your own app's logout flow.
## Targeted logout (from your backend)
Call this whenever you want to end a **specific promoter's** embedded session from your side — typically when that user logs out of your app, or when you need to immediately revoke their access (e.g. they were suspended). It targets one promoter at a time by `promoter_id` or `cust_id`, so it never affects any other promoter's session.
```
POST https://v2.firstpromoter.com/api/v2/promoters/iframe_logout
```
The FirstPromoter promoter ID whose session to end. Provide this or `cust_id`.
The external customer ID you assigned this promoter. Provide this or `promoter_id`.
Optional. The `access_token` value returned by a specific [`iframe_login`](/advanced/embed-dashboard-login) call. Pass this to revoke **only that one session** instead of every active session — see [Ending a single session](#ending-a-single-session) below. If provided, this takes priority over `promoter_id`/`cust_id`; if left blank, the request falls back to revoking all of the promoter's sessions.
`Bearer {your_api_key}`
`{your_account_id}`
The request body is empty. A `200 OK` with no body confirms the session was revoked; a `404` means no promoter matched the `promoter_id`/`cust_id` you passed (or, when using `session_token`, that the token doesn't exist, is already revoked, belongs to a different account, or doesn't belong to a promoter).
Without `session_token`, this revokes **every currently active access token that promoter has under your account** — including any not-yet-expired tokens from earlier `iframe_login` calls (e.g. from other tabs or an earlier page load). It does not touch that same person's sessions under any other FirstPromoter account they may also be a promoter for.
### Ending a single session
If you embed the dashboard in multiple places at once for the same promoter (e.g. several open tabs, or a mobile and web session) and only want to end one of them, pass `session_token` instead of `promoter_id`/`cust_id`. Its value is the `access_token` your backend received from the corresponding `iframe_login` call — so you'll need to have stored that value per-session in order to target it later.
```sh cURL theme={null}
curl --request POST \
--url 'https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?session_token=THE_ACCESS_TOKEN_FROM_IFRAME_LOGIN' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Account-Id: YOUR_ACCOUNT_ID'
```
All of the promoter's other active sessions remain untouched.
### Example
```js Node.js (Express) theme={null}
app.post("/logout", async (req, res) => {
const promoterId = req.user.firstpromoterPromoterId;
await fetch(
`https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?promoter_id=${promoterId}`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FP_API_KEY}`,
"Account-Id": process.env.FP_ACCOUNT_ID,
},
}
);
// ...continue your own app's logout flow
res.redirect("/login");
});
```
```php PHP theme={null}
firstpromoter_promoter_id;
$ch = curl_init(
"https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?promoter_id=" . urlencode($promoterId)
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $_ENV["FP_API_KEY"],
"Account-Id: " . $_ENV["FP_ACCOUNT_ID"],
]);
curl_exec($ch);
curl_close($ch);
?>
```
```sh cURL theme={null}
curl --request POST \
--url 'https://v2.firstpromoter.com/api/v2/promoters/iframe_logout?promoter_id=12345' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Account-Id: YOUR_ACCOUNT_ID'
```
### When to call this
* **On your app's own logout action** — call it alongside your normal sign-out logic so the dashboard doesn't silently re-authenticate on the next page load.
* **When suspending or deactivating a user** — revoke dashboard access immediately rather than waiting up to 24 hours for their last token to expire.
* **Before switching which promoter is shown in the same embedded iframe** — e.g. an admin view of your app that lets staff preview different promoters' dashboards.
## Related
* [Embed the dashboard & auto-login promoters](/advanced/embed-dashboard-login)
* [Promoters API reference](/api-reference-v2/api-admin/promoters/get-available-promoters)
# Integrate Your Website
Source: https://docs.firstpromoter.com/guides/integrate-your-website
Connect your website to FirstPromoter so clicks, sign-ups, and sales are tracked and attributed to the right affiliate.
Website integration is what makes FirstPromoter actually work. Without it, FirstPromoter cannot tell which affiliate sent a visitor, whether that visitor signed up, or whether they made a purchase.
The full integration has three parts:
| Part | What it does | Required? |
| - | - | - |
| **Click tracking** | Detects when a visitor arrives through an affiliate link | Yes |
| **Referral tracking** | Records who signed up or filled a form | Yes |
| **Sales tracking** | Attributes purchases to the right affiliate | Yes (to generate commissions) |
Before you start, find your **Account ID** in your FirstPromoter dashboard under **Settings → Integrations**. You'll need it in the steps below.
***
## Step 1 — Choose your integration path
Pick the option that matches your website setup:
Use our WordPress plugin for click tracking, referral tracking, and WooCommerce / MemberPress sales — no custom code needed.
Using Kajabi, HighLevel, ClickFunnels, Ghost, Thinkific, SamCart, or similar? We have ready-made guides for each.
Any other website, SaaS app, or JavaScript framework. Requires adding a script tag and one function call.
***
## Platform integrations
If you use one of the platforms below, follow the dedicated guide — it handles click and referral tracking for that platform's specific forms and checkout flows.
After completing the platform guide, jump to [Step 3 — Sales tracking](#step-3--sales-tracking) to finish your setup.
***
## Custom website or app
### Step 2a — Add the click tracking script
Add the following snippet to the `` section of every public-facing page on your website. Replace `YOUR_ACCOUNT_ID` with the Account ID from your FirstPromoter dashboard.
```html theme={null}
```
Adding this to every page (not just the homepage) ensures clicks are tracked no matter which page an affiliate links to. The script loads asynchronously and will not slow down your site.
Add the script to your `header.php` file before the closing `` tag, or use a plugin like **Insert Headers and Footers** to paste it into the head section without editing theme files.
Add the script tags to your `public/index.html` file inside the `` section.
1. Create `/public/fprmain.js` and paste the `fpr("init", ...)` and `fpr("click")` lines into it.
2. In `_document.tsx`, load both `/fprmain.js` and `https://cdn.firstpromoter.com/fpr.js` inside the `` component.
See the [full Next.js example](/integrations/tracking/custom/js) for a working code snippet.
Create `/public/fprmain.js` with the init and click lines, then use the `useHead` composable on your marketing pages to load it alongside `fpr.js`.
Follow the [GTM integration guide](/integrations/tracking/custom/gtm) to add the scripts through a custom HTML tag.
***
### Step 2b — Add referral tracking
When a visitor signs up or submits a form, you need to send their email (or user ID) to FirstPromoter. This is what creates the referral record and links the sign-up to the affiliate.
Call the following **after** the main script and **after** you have the user's email — typically on your sign-up success callback or thank-you page:
```html theme={null}
```
Replace `"actual_user@email.com"` with the real email of the user who just signed up. You can also pass a `uid` (user ID from your database) instead of or in addition to the email:
```javascript theme={null}
fpr("referral", {email: "actual_user@email.com", uid: "cus_12345"});
```
The `fpr("referral", ...)` call must run **after** the user has successfully signed up — not before. If you redirect immediately after the call, the request may be cancelled by the browser. In that case, place the script on the thank-you/confirmation page instead.
**Where to place this call:**
* **Simple HTML form** — listen for the form submit event, read the email input value, and call `fpr("referral", {email: emailValue})`.
* **React / Vue / Angular** — call it inside the success callback of your registration API request.
* **Thank-you page with email in the URL** — read the email from the URL and pass it directly: `fpr("referral", {email: new URLSearchParams(location.search).get("email")})`.
* **Server-side only** — use the [Tracking API](/integrations/tracking/custom/api) to make the call from your backend instead.
For detailed examples per framework, see the [JavaScript integration guide](/integrations/tracking/custom/js).
***
## Step 3 — Sales tracking
Sales tracking tells FirstPromoter which purchases to credit to which affiliate and triggers commission creation.
### Option A — Connect a billing provider (recommended)
If you use one of the following billing providers, connect it directly in FirstPromoter and sales are tracked automatically:
Go to **Settings → Integrations** in your FirstPromoter dashboard to connect your billing provider.
For Stripe-specific checkout setups, see also:
* [Stripe Checkout](/integrations/tracking/custom/stripe-checkout)
* [Stripe Payment Links](/integrations/tracking/platform/stripe/payment-links)
* [Stripe Pricing Table](/integrations/tracking/platform/stripe/pricing-table)
### Option B — Use the Tracking API
If you use a different billing provider or have a custom payment flow, send a sale event to FirstPromoter from your backend whenever a payment is confirmed:
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/sale \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"sale_amount": 4900,
"currency": "usd",
"order_id": "order_001"
}'
```
See the full [Sales Tracking API reference](/api-reference-v2/api-admin/tracking-api/sales) for all available parameters.
`sale_amount` is in **cents** (e.g. `4900` = \$49.00).
***
## Step 4 — Test your integration
Before going live, verify each part is working:
Copy an affiliate's referral link from the FirstPromoter dashboard and visit it in your browser. A click should appear on that affiliate's record within a few seconds.
After visiting via the referral link, sign up as a test user on your website. Check the **Referrals** tab in FirstPromoter — a new lead should appear linked to the affiliate.
Complete a test purchase (use a Stripe test card if on Stripe). A new sale and commission should appear in FirstPromoter.
Check your browser console for errors after adding the scripts. Common issues are a wrong Account ID or calling `fpr("referral", ...)` before the main script has loaded.
***
## Need help?
* [Full fpr.js script reference](/script-docs/fpr-js-docs) — every method and option explained
* [Tracking without fpr.js (API only)](/guides/tracking-without-fprjs) — pure API approach with no frontend script
* [Proxy setup](/guides/proxy-setup) — keep tracking working when ad-blockers are active
* [Support](mailto:support@firstpromoter.com) — reach the team if you're still stuck
# Mobile Attribution Providers (Branch.io, AppsFlyer, Adjust)
Source: https://docs.firstpromoter.com/guides/mobile-attribution-providers
Use a deep linking/attribution provider to solve new-install (deferred) referral tracking on iOS and Android, and report the result to FirstPromoter.
[Deep Linking for Mobile Apps](/guides/mobile-deep-linking) covers tracking referrals when the user **already has your app installed**. This guide solves the harder case: **the user doesn't have your app yet.**
When someone taps an affiliate link without your app installed, iOS and Android route them to the App Store / Play Store. Neither platform passes the original link's query parameters through that install — by the time the app opens for the first time, the referral ID (`fpr=joe13`) is gone. This is why "deferred deep linking" tools exist. FirstPromoter doesn't run its own — instead, you point one of these providers at your app and forward whatever referral ID it recovers into FirstPromoter's Tracking API, the same way as the direct-install case.
This guide uses **Branch.io** as the worked example since it's the most commonly used for this pattern, but **AppsFlyer** (OneLink) and **Adjust** solve the same problem the same way — a redirect link with custom data, an SDK that reads that data back on first open, and an attribution callback in your app code. If you're already using one of those for ad attribution, reuse it here instead of adding Branch.
***
## How it works end to end
| Step | What happens |
| - | - |
| 1 | Affiliate's FirstPromoter referral ID (`ref_id`) is embedded as custom data on a Branch link |
| 2 | Affiliate shares the **Branch link** instead of the raw FirstPromoter link |
| 3 | No app installed → Branch redirects to the App Store / Play Store |
| 4 | App installed → opened for the first time → Branch SDK resolves the original link's custom data |
| 5 | Already installed → tapping the link opens the app directly with the same custom data |
| 6 | Your app reads the `ref_id` out of Branch's session params and reports it to FirstPromoter |
***
## Step 1 — Generate a Branch link carrying the FirstPromoter referral ID
For each affiliate, once you have their FirstPromoter referral link (e.g. `https://yourapp.com/r?fpr=joe13`), create a corresponding Branch link with the `ref_id` stored as custom data, and the FirstPromoter link set as the desktop/web fallback so anyone opening it on desktop still lands on your normal site:
```sh theme={null}
curl -X POST https://api2.branch.io/v1/url \
-H 'Content-Type: application/json' \
-d '{
"branch_key": "key_live_YOUR_BRANCH_KEY",
"channel": "affiliate",
"feature": "referral",
"data": {
"fpr_ref_id": "joe13",
"$desktop_url": "https://yourapp.com/r?fpr=joe13",
"$fallback_url": "https://yourapp.com/r?fpr=joe13"
}
}'
```
Share the resulting `https://yourapp.app.link/...` URL as the affiliate's mobile referral link (in addition to, or instead of, the plain FirstPromoter one, depending on where you expect it to be shared).
You can automate this: whenever FirstPromoter creates or returns a promoter's referral link (via the dashboard, or the [Promoter API](/api-reference-v2/api-admin)), call the Branch URL API from your backend to mint the matching Branch link, and show that to the affiliate instead.
***
## Step 2 — Initialize the Branch SDK and read the referral ID
```dart Flutter (flutter_branch_sdk) theme={null}
import 'package:flutter_branch_sdk/flutter_branch_sdk.dart';
Future initBranch() async {
await FlutterBranchSdk.init(enableLogging: true);
FlutterBranchSdk.listSession().listen((data) {
if (data.containsKey('+clicked_branch_link') && data['+clicked_branch_link'] == true) {
final refId = data['fpr_ref_id'] as String?;
if (refId != null) storeReferralId(refId);
}
});
}
```
```swift iOS (Branch native SDK) theme={null}
// AppDelegate.swift — application(_:didFinishLaunchingWithOptions:)
Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
if let refId = params?["fpr_ref_id"] as? String {
UserDefaults.standard.set(refId, forKey: "fpr_ref_id")
}
}
```
```kotlin Android (Branch native SDK) theme={null}
// In onStart() of your launcher Activity
Branch.sessionBuilder(this).withCallback { referringParams, error ->
if (error == null) {
val refId = referringParams?.optString("fpr_ref_id")
if (!refId.isNullOrEmpty()) {
getSharedPreferences("fpr", MODE_PRIVATE).edit()
.putString("fpr_ref_id", refId)
.apply()
}
}
}.withData(intent?.data).init()
```
```javascript React Native (react-native-branch) theme={null}
import branch from 'react-native-branch';
import AsyncStorage from '@react-native-async-storage/async-storage';
branch.subscribe(({ error, params }) => {
if (error) return;
if (params?.['+clicked_branch_link']) {
const refId = params.fpr_ref_id;
if (refId) AsyncStorage.setItem('fpr_ref_id', refId);
}
});
```
Branch returns the same `fpr_ref_id` custom data key whether the link was opened directly (app already installed) or resolved after a fresh install (deferred) — your app doesn't need separate logic for the two cases. That's the problem Branch (or an equivalent provider) is solving for you.
***
## Step 3 — Report the referral ID to FirstPromoter
Once `fpr_ref_id` is captured, the rest is identical to the direct deep-linking flow — send it to your backend, and have your backend call the FirstPromoter Tracking API:
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"ref_id": "joe13"
}'
```
As with direct deep linking, keep your FirstPromoter API key on your backend only — never call this endpoint directly from the mobile app. See [Deep Linking for Mobile Apps → Step 3](/guides/mobile-deep-linking#step-3-report-the-referral-to-firstpromoter) for the sales-tracking call and full parameter list.
***
## Using AppsFlyer or Adjust instead
The pattern is the same; only the SDK callback differs:
| Provider | Where you set the custom data | Where you read it back |
| - | - | - |
| **Branch.io** | `data` object on link creation | `initSession`/`listSession` callback params |
| **AppsFlyer (OneLink)** | deep link value / OneLink template parameters | `onAppOpenAttribution` / `onConversionDataSuccess` callback |
| **Adjust** | `deep_link_value` on the tracker/link | `attributionCallback` on the `Adjust` instance |
Whichever you use, the goal is the same: get the FirstPromoter `ref_id` out of the provider's attribution payload, then make the same two Tracking API calls (`/track/signup`, `/track/sale`) from your backend described in Step 3 above and in the [Deep Linking guide](/guides/mobile-deep-linking).
***
## Choosing whether you need this at all
Adding an attribution provider is real integration work and (beyond free tiers) an ongoing cost. Consider whether you need it:
* If your affiliates mostly share links in **contexts where the app is very likely already installed** (e.g. existing customers referring other existing users of the same category of app), the direct deep-linking flow in the [previous guide](/guides/mobile-deep-linking) may be enough on its own.
* If a meaningful share of referred signups are **brand-new users installing your app for the first time**, you need deferred deep linking to avoid losing that attribution — this guide's approach (or the Android-only Play Install Referrer API from the previous guide) is required.
***
## Need help?
* [Deep Linking for Mobile Apps](/guides/mobile-deep-linking) — the direct-install flow and full Tracking API parameter reference
* [Tracking API reference](/api-reference-v2/api-admin/tracking-api/leads-and-signups)
* [Support](mailto:support@firstpromoter.com) — reach the team if you're still stuck
# Deep Linking for Mobile Apps (Flutter, iOS, Android, React Native)
Source: https://docs.firstpromoter.com/guides/mobile-deep-linking
Track affiliate referrals inside native mobile apps by capturing the referral ID from a deep link and reporting it to FirstPromoter's Tracking API.
FirstPromoter's standard integration (`fpr.js` + cookies) is built for browsers. A native mobile app has no cookies and no `document`, so referral tracking has to be done a different way: **capture the referral ID from the incoming link, then report it to FirstPromoter yourself via the Tracking API.**
This guide covers the case where the user **already has your app installed** — tapping the affiliate's link opens the app directly and the referral data survives the trip. If the user does **not** have the app installed yet, the link has to go through the App Store / Play Store first, and standard deep links **lose the referral data** in that round-trip. That "deferred deep linking" problem is covered separately in [Mobile Attribution Providers](/guides/mobile-attribution-providers) — read this guide first, since the concepts (extracting the ref ID, calling the Tracking API) are the same either way.
***
## How it works
| Step | What happens |
| - | - |
| 1. Affiliate shares their link | The same referral link FirstPromoter already generates, e.g. `https://yourapp.com/r?fpr=joe13` |
| 2. Link opens your app | Configured as a Universal Link (iOS) / App Link (Android) so it opens the app instead of a browser, if installed |
| 3. App reads the referral ID | Your app extracts `fpr` (or whichever parameter is used) from the incoming URL |
| 4. App stores it | Persist it locally until the user signs up — this replaces the `_fprom_ref` cookie a website would use |
| 5. Your backend reports it | On signup/purchase, your backend calls FirstPromoter's [Tracking API](/api-reference-v2/api-admin/tracking-api/leads-and-signups) with the referral ID |
The supported query parameters for a referral link are `fpr`, `via`, `fp_ref`, `deal`, `ref`, `_from`, `_by`, `_go`. Pick one and use it consistently — `fpr` is the default used throughout this guide.
***
## Step 1 — Make your referral link open the app
For the link to open your app directly (instead of a mobile browser) when the app is already installed, register your domain as:
* **iOS — Universal Links**: host an `apple-app-site-association` file at `https://yourapp.com/.well-known/apple-app-site-association` and enable the **Associated Domains** capability (`applinks:yourapp.com`) in Xcode.
* **Android — App Links**: host an `assetlinks.json` file at `https://yourapp.com/.well-known/assetlinks.json` and add an `` in your `AndroidManifest.xml` matching your domain.
A misconfigured `apple-app-site-association` or `assetlinks.json` is the most common reason deep links silently fall back to the browser instead of opening the app. Verify both files are served over HTTPS with no redirects and a `Content-Type` of `application/json`.
If you don't want to set up Universal/App Links yet, a custom URL scheme (`yourapp://ref?fpr=joe13`) works too, but it can't be used as the affiliate-facing link on its own (it won't resolve in a browser or `sms`/social share preview) — pair it with a normal `https://` fallback link that redirects to it, or use one of the frameworks below which handle both.
***
## Step 2 — Capture the referral ID on app open
```dart Flutter (app_links package) theme={null}
import 'package:app_links/app_links.dart';
final _appLinks = AppLinks();
Future initDeepLinkListener() async {
// Handles the link that launched the app (cold start)
final initialUri = await _appLinks.getInitialLink();
_handleIncomingLink(initialUri);
// Handles links received while the app is already running
_appLinks.uriLinkStream.listen(_handleIncomingLink);
}
void _handleIncomingLink(Uri? uri) {
if (uri == null) return;
final refId = uri.queryParameters['fpr'];
if (refId != null) {
storeReferralId(refId); // persist with shared_preferences / secure storage
}
}
```
```swift iOS (Universal Links, SceneDelegate/AppDelegate) theme={null}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
if let refId = components.queryItems?.first(where: { $0.name == "fpr" })?.value {
UserDefaults.standard.set(refId, forKey: "fpr_ref_id")
}
}
```
```kotlin Android (App Links) theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
val data: Uri? = intent.data
val refId = data?.getQueryParameter("fpr")
if (refId != null) {
getSharedPreferences("fpr", MODE_PRIVATE).edit()
.putString("fpr_ref_id", refId)
.apply()
}
}
```
```javascript React Native (Linking API) theme={null}
import { Linking } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
function extractRefId(url) {
if (!url) return null;
const { queryParams } = Linking.parse(url); // or new URL(url).searchParams
return queryParams?.fpr ?? null;
}
// Cold start
Linking.getInitialURL().then((url) => {
const refId = extractRefId(url);
if (refId) AsyncStorage.setItem('fpr_ref_id', refId);
});
// While app is running
Linking.addEventListener('url', ({ url }) => {
const refId = extractRefId(url);
if (refId) AsyncStorage.setItem('fpr_ref_id', refId);
});
```
If you use React Navigation, wire this into its own [deep linking config](https://reactnavigation.org/docs/deep-linking/) `getStateFromPath`/`subscribe` instead of a second parallel `Linking` listener, to avoid handling the same URL twice.
***
## Step 3 — Report the referral to FirstPromoter
Never embed your FirstPromoter API key in the mobile app. The Tracking API requires a `Bearer` API key that can create signups and sales on your account — anyone who decompiles your app binary would be able to extract it. Send the stored referral ID from the app to **your own backend**, and make the FirstPromoter API call from there.
**When the user signs up** (client → your backend → FirstPromoter):
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"ref_id": "joe13",
"skip_email_notification": true
}'
```
* Send either `email` or `uid` (or both) — whichever you have at signup time.
* `ref_id` is the value you captured from the `fpr` parameter in Step 2.
See the full [Leads & Sign-ups API reference](/api-reference-v2/api-admin/tracking-api/leads-and-signups) for all parameters.
**When the user makes a purchase** (in-app purchase confirmed server-side, subscription webhook, etc.):
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/sale \
--header 'Account-ID: YOUR_ACCOUNT_ID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer@email.com",
"uid": "cus_12345",
"event_id": "txn_00123",
"amount": 4900
}'
```
* `amount` is in **cents** (`4900` = \$49.00), except for zero-decimal currencies (e.g. `JPY`), which are sent as whole values.
* `event_id` must be unique per transaction — it's how FirstPromoter deduplicates retried webhook/receipt calls.
* If you already reported the signup with a `ref_id`, you don't need to pass it again on the sale call — FirstPromoter matches the sale to the lead by `email`/`uid`.
See the full [Sales Tracking API reference](/api-reference-v2/api-admin/tracking-api/sales).
***
## Limitations of direct deep linking
This approach only works when **the app is already installed**. If it isn't:
* Tapping the link opens the App Store / Play Store listing (or a fallback web page) instead of the app.
* The `fpr` parameter is **not** carried through the install — the app has no way to read it on first open, because the OS doesn't pass launch parameters from an unrelated store install.
This is a limitation of iOS/Android themselves, not FirstPromoter — every affiliate/attribution tool runs into it. There is one native, first-party workaround on Android only:
* **Google Play Install Referrer API** lets you append a referrer string to the Play Store URL (`&referrer=fpr%3Djoe13`), which Google stores and your app can read via the `com.android.installreferrer` library on first open after install — no third-party SDK required. There is no iOS equivalent.
If you need reliable new-install attribution on **both** iOS and Android, see [Mobile Attribution Providers](/guides/mobile-attribution-providers), which covers using a service like Branch.io to bridge that gap and still report into FirstPromoter using the same API calls from Step 3.
***
## Need help?
* [Tracking API reference](/api-reference-v2/api-admin/tracking-api/leads-and-signups) — full parameter documentation
* [Mobile Attribution Providers](/guides/mobile-attribution-providers) — solving new-install (deferred) attribution with Branch.io or similar
* [Tracking without fpr.js](/guides/tracking-without-fprjs) — the same API-only pattern used here, written for websites
* [Support](mailto:support@firstpromoter.com) — reach the team if you're still stuck
# Proxy Setup (Optional)
Source: https://docs.firstpromoter.com/guides/proxy-setup
FirstPromoter Proxy Integration Guide for Bypassing Ad Blockers
## Overview
This document outlines how to implement proxy integrations with FirstPromoter to ensure reliable tracking even when ad blockers are present. By leveraging a proxy setup, you can maintain accurate affiliate tracking and conversion attribution while minimizing the impact of ad blocking technologies.
## The Challenge with Ad Blockers
Ad blockers and privacy tools can interfere with affiliate tracking in several ways:
* Blocking tracking scripts from loading
* Preventing cookies from being set
* Blocking HTTP requests to domains identified as tracking services
* Stripping tracking parameters from URLs
FirstPromoter, like many affiliate platforms, can be affected by these measures, resulting in lost attribution data and commission tracking failures.
## Proxy Integration Solution
A proxy integration routes tracking requests through your own domain or a custom domain instead of directly to FirstPromoter's tracking domain.
This approach has several advantages:
* **Improved Deliverability**: Requests appear to come from your trusted domain, not a third-party tracking service
* **Reduced Blocking**: Most ad blockers don't block first-party requests
* **Enhanced Privacy**: User data stays within your domain ecosystem
* **Better Performance**: Removes additional DNS lookups to third-party domains
### Implementation Methods
#### Method 1: Vercel redirect setup
If your service is hosted by Vercel, they provide an option to reroute your requests.
To set up a Vercel redirect, follow these steps:
1. Find your vercel.json file. This is usually in your root directory.
2. Add the following lines to your vercel.json file:
```json theme={null}
{
"rewrites": [
{
"source": "/get_details",
"destination": "https://t.firstpromoter.com/get_details"
},
{
"source": "/tr",
"destination": "https://t.firstpromoter.com/tr"
}
]
}
```
You can change the source paths to anything that you like. However you will need to update the URL's in the tracking scripts as well.
For these we provide the following variables which you will use when setting up your scripts : `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url`
3. Download the tracking scripts from here (Click here) and add it to your main website's public directory.
This will allow it to be fetched from your website. You can change the name of the file to anything but remember to rename it in the main tracking code below.
4. For your main tracking scripts, add the following code. Please replace `` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard. If you changed the urls to something more custom you can uncomment the `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url` variables and update them to match your proxy urls.
```html theme={null}
```
6. Deploy your changes and test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected
#### Method 2: Cloudflare workers setup
Cloudflare provides a free plan with up to 100,000 requests per day, making it a good choice for a reverse proxy setup.
To set up a Cloudflare worker, follow these steps:
1. Set up a Cloudflare Worker
Navigate to the Cloudflare dashboard, select `Compute (Workers)` > `Workers & Pages` > `Create`.
You can choose a custom name for your worker or use the default one. Click "Deploy" when ready.\
Please take note of the url of your worker as this will be needed in your setup of the tracking scripts.
2. Modify the Worker for Proxy Functionality
After deploying your new worker, click "Edit code". If you're already on the worker's page, select "Quick edit". This will open a code editor where you should replace the existing code with the following proxy code:
```javascript theme={null}
const FP_CDN_HOST = "https://cdn.firstpromoter.com/fpr-proxy.js";
const FP_HOST = "https://t.firstpromoter.com";
async function handleRequest(request, ctx) {
const url = new URL(request.url)
const pathname = url.pathname
const search = url.search
const pathWithParams = pathname + search
return forwardRequest(request, pathWithParams)
}
async function forwardRequest(request, pathWithSearch) {
const originRequest = new Request(request)
originRequest.headers.delete("cookie")
return await fetch(`${FP_HOST}${pathWithSearch}`, originRequest)
}
export default {
async fetch(request, env, ctx) {
return handleRequest(request, ctx);
}
};
```
3. When done, click "Save and deploy".
4. Download the tracking scripts from here (Click here) and add it to your main website's public directory.
This will allow it to be fetched from your website. You can change the name of the file to anything but remember to rename it in the main tracking code below.
5. For your main tracking scripts, add the following code. Please replace `` with the url of your worker and `` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
6. Test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected
#### Method 3: Apache setup
1. Find your apache config. Depending on your setup you may need to put the below in your default-ssl.conf file.
`yourdomain.com/tr` will be pointed to `https://t.firstpromoter.com/tr` and `yourdomain.com/tr/get_details` will point to `https://t.firstpromoter.com/get_details`.
Feel free to change `/tr` to anything you want on your domain if you do, you will be required to set the following in your script `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url`
```apache theme={null}
#your other configs
ProxyPass /tr/get_details https://t.firstpromoter.com/get_details
ProxyPassReverse /tr/get_details https://t.firstpromoter.com/get_details
ProxyPass /tr https://t.firstpromoter.com/tr
ProxyPassReverse /tr https://t.firstpromoter.com/tr
```
Feel free to change `/tr` and `/tr/get_details` to anything you want on your domain if you do, you will be required to set the following in your script `window.proxy_fpr_tr_url` and `window.proxy_fpr_get_details_url`
2. Restart your server. `sudo service apache2 restart`
3. Download the FirstPromoter scripts from here (Click here) and add it to your main websites public directory.
This will allow it to be fetched from your website.
4. Add the scripts below directly to your website. Replace `` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
5. Deploy and test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected.
#### Method 4: NGINX setup
1. Find your NGINX config file. This is typically at:
`/etc/nginx/sites-available/yourdomain.com` Or if using a default site: `/etc/nginx/sites-available/default`
Then within the server block, add the proxy rules like this:
```nginx theme={null}
location /tr/get_details {
proxy_pass https://t.firstpromoter.com/get_details;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
location /tr {
proxy_pass https://t.firstpromoter.com/tr;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
```
The contents of your file should look like the following:
```
server {
listen 80;
server_name yourdomain.com;
location /tr/get_details {
proxy_pass https://t.firstpromoter.com/get_details;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
location /tr {
proxy_pass https://t.firstpromoter.com/tr;
proxy_set_header Host t.firstpromoter.com;
proxy_ssl_server_name on;
}
# other configs here
}
```
2. Restart your server. `sudo service nginx restart`
3. Download the FirstPromoter scripts from here (Click here) and add it to your main website's public directory.
This will allow it to be fetched from your website.
4. Add the scripts below directly to your website. Replace `your-account-id-here` with your **actual account id** in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
5. Deploy and test using the brave browser or install uBlockOrigin and confirm if your tracking is working as expected
# Tracking with fpr.js
Source: https://docs.firstpromoter.com/guides/tracking-with-fprjs
Track clicks and referrals using the fpr.js scripts
## Installation
First, add the main tracking scripts to your website.
Replace `` with your **actual account id** found in the settings > integrations page on your FirstPromoter dashboard.
```html theme={null}
```
## Tracking Flow
### 1. Click Tracking
The main tracking script automatically tracks visitors that come through your affiliate links:
* When a visitor arrives on your website using a referral link the main tracking script will automatically track the click.
* The click sets 2 cookies in the browser - `_fprom_ref` and `_fprom_tid`
* These cookies are used for tracking in future without the need for a referral link.
### 2. Referral Tracking
When a visitor signs up or fills an opt-in form, convert them to a referral by using the signup function:
```html theme={null}
```
You can send only the email or only the uid or both. You need to ensure that the actual visitor data is passed to the function.
### 3. Sales Tracking
If you are using [Stripe](https://login.firstpromoter.com?redirect=%2Fintegration%2Fstripe), [Chargebee](https://login.firstpromoter.com?redirect=%2Fintegration%2Fchargebee), [Braintree](https://login.firstpromoter.com?redirect=%2Fintegration%2Fbraintree), [Paddle](https://login.firstpromoter.com?redirect=%2Fintegration%2Fpaddle) or [Recurly](https://login.firstpromoter.com?redirect=%2Fintegration%2Frecurly) we can track sales automatically on our end. You will only need to connect your billing provider to FirstPromoter.
If you use any other billing provider you will need to track sales using the tracking [API](https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/sales). For more information on sales tracking API, see documentation [here](/api-reference-v2/api-admin/tracking-api/sales)
When a sale event is received, FirstPromoter will automatically:
* Identify the corresponding affiliate to assign the sale to.
* Assign the corresponding reward/commission to the promoter.
With this in place you have completed the basic tracking flow. From tracking of clicks through to assigning the corresponding commissions to the affiliates.
# Tracking without fpr.js
Source: https://docs.firstpromoter.com/guides/tracking-without-fprjs
Track affiliate leads and sales/payments using API calls
Planning to use sub IDs, postbacks or ad tracking? You still need the tracking script for clicks. See [Using sub IDs, postbacks or ad tracking with the API](#using-sub-ids%2C-postbacks-or-ad-tracking-with-the-api) below.
# Tracking Flow
## 1. Store and retrieve link token (Referral ID):
When a visitor arrives through a referral link (e.g., [https://yourdomain.com?fpr=joe13](https://yourdomain.com?fpr=joe13), where `fpr` is the affiliate's Referral ID parameter and `joe13` is the value), retrieve the referral link token (Referral ID) from the referral link, store it in the browser's localStorage or as cookie for later use.
The available query parameters are `?fpr`, `?via`, `?fp_ref`, `?deal`, `?ref`, `?_from`, `?_by`, `?_go` .
### I. Store referral link token implementation
```javascript client side (localStorage implementation) theme={null}
```
```javascript client side (cookie implementation) theme={null}
```
### II. Retrieve referral ID/token
```javascript client-side (localStorage implementation) theme={null}
```
```javascript client side (cookie retrieval implementation) theme={null}
```
```javascript Server Side (cookie retrieval implementation) theme={null}
// backend.js
// this code is just a demonstration of how to retrieve the referral ID/token stored in the cookie.
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.post('/signup', (req, res) => {
// retrieve the referral ID/token (_fprom_ref) from server-side.
const ref_id = req.cookies['_fprom_ref'];
// make API call with ref_id to track referral
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
```
## 2. Lead/Referral tracking
When a visitor signs up or fills an opt-in form, convert them to a referral by using the [track/signup](/api-reference-v2/api-admin/tracking-api/leads-and-signups) endpoint.
You can send only the email or only the uid or both. You need to ensure that the actual visitor data is passed in the API call.
```sh theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: ' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer1@gmail.com",
"uid": "cus_000001",
"ref_id": "joe13",
"skip_email_notification": true
}'
```
## Using sub IDs, postbacks or ad tracking with the API
If you want to use **sub IDs**, **postbacks** or **ad tracking**, sending `ref_id` to `track/signup` is not enough. These features rely on data captured when the visitor clicks the referral link: the sub ID (`fp_sid`) from the link, the landing page URL with any ad click IDs, and the visit itself. FirstPromoter only records that data when the click is tracked by the tracking script, and only links it to the referral when you send the visit's `tid`.
A signup tracked with only `ref_id` is credited to the right affiliate, but it has no click attached. Its sub ID will be empty, postback values that come from the visit will be blank, and ad traffic can't be detected.
To keep this data, use the tracking script for clicks and the API for signups:
Add the [main tracking script](/guides/tracking-with-fprjs#installation) to every page a referral link can land on. When a visitor arrives through a referral link, the script tracks the click and sets the `_fprom_ref` and `_fprom_tid` cookies.
If visitors land on one domain and sign up on another, set up [cross-domain tracking](/script-docs/fpr-js-docs) so the cookies are available where the signup happens.
When the visitor signs up, read the `_fprom_tid` cookie on your server (or in the browser and send it to your server with the signup form).
Pass the cookie value in the `tid` parameter of [track/signup](/api-reference-v2/api-admin/tracking-api/leads-and-signups). FirstPromoter uses it to find the tracked click, credit the right affiliate, and attach the sub ID, landing URL and ad data to the referral.
```javascript Server side (Express) theme={null}
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(express.json());
app.post('/signup', async (req, res) => {
// Set by the FirstPromoter tracking script when the visitor clicked a referral link
const tid = req.cookies['_fprom_tid'];
// ...create the user in your app...
if (tid) {
await fetch('https://api.firstpromoter.com/api/v2/track/signup', {
method: 'POST',
headers: {
'Account-ID': '',
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: req.body.email, uid: req.body.uid, tid }),
});
}
res.sendStatus(201);
});
```
```sh cURL theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: ' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer1@gmail.com",
"uid": "cus_000001",
"tid": ""
}'
```
If there is no `_fprom_tid` cookie, the visitor didn't arrive through a tracked referral link (or their browser blocked the cookie), so don't send an empty `tid`. If you still know the referral ID, you can send it as `ref_id` instead, but sub IDs, postback visit data and ad tracking won't be available for that referral.
## 3. Sales Tracking
If you are using [Stripe](https://login.firstpromoter.com?redirect=%2Fintegration%2Fstripe), [Chargebee](https://login.firstpromoter.com?redirect=%2Fintegration%2Fchargebee), [Braintree](https://login.firstpromoter.com?redirect=%2Fintegration%2Fbraintree), [Paddle](https://login.firstpromoter.com?redirect=%2Fintegration%2Fpaddle) or [Recurly](https://login.firstpromoter.com?redirect=%2Fintegration%2Frecurly) we can track sales automatically on our end. You will only need to connect your billing provider to FirstPromoter.
If you use any other billing provider you will need to track sales using the tracking [API](https://docs.firstpromoter.com/api-reference-v2/api-admin/tracking-api/sales). For more information on sales tracking API, see documentation [here](/api-reference-v2/api-admin/tracking-api/sales)
When a sale event is received, FirstPromoter will automatically:
* Identify the corresponding affiliate to assign the sale to.
* Assign the corresponding reward/commission to the promoter.
With this in place, you have completed the basic tracking flow. From storing and retrieval of affiliate referral link token (Referral ID) through to assigning the corresponding commissions to the affiliates.
# How FirstPromoter works
Source: https://docs.firstpromoter.com/how-it-works
Set up and manage your own affiliate program, no matter how simple or complex your affiliate scheme is.
## Setting Up a Campaign
Setting up a campaign with FirstPromoter is seamless and can be done in just a few clicks. During the onboarding process, you will create your first campaign. Each campaign generates a unique signup link that can be shared with your affiliates. When they sign up, FirstPromoter creates a unique referral link using the website URL you provide. Affiliates can then share their referral link with potential customers.
## Click Tracking
Click tracking on FirstPromoter works after adding the main tracking script to your website. It works only once when a user visits a referral link by sending a `click` event to FirstPromoter.
## Referral Tracking
Referral tracking occurs when a lead is captured on your website and sent to FirstPromoter after they sign up or fill out a form. This is achieved via the referral tracking script or API, which requires you to send the referral email address or UID to FirstPromoter.
When a lead visits with a referral link, two cookies, `_fprom_tid` and `_fprom_ref` are set in their browser. These cookies have a default lifespan of 60 days (adjustable in the Admin panel) and are essential for the referral tracking script to function.
## Sales Tracking
Sales tracking is crucial for calculating commissions for affiliates. By default, FirstPromoter automatically tracks sales from providers like `Stripe`, `Chargebee`, `Braintree (subscriptions)`, `Recurly`, `Paddle` by listening to and cross-referencing events sent from the billing provider.
For other billing providers or custom setups, we provide an API to send sales events to FirstPromoter.
# API
Source: https://docs.firstpromoter.com/integrations/billing/api
Tracking sales with API
`Difficulty: Intermediate`
`Developer Required: Yes`
Our API allows you to track sales, refunds, upgrades and cancellations even if you have a billing provider we do not support.
**Precondition**:
You will need to set up an endpoint on your server for which you will receive webhook events from your billing provider.
Once you are receiving webhook events on your server from your billing provider, you can then make a request to FirstPromoter to track sales when events are received.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fcustom) to view the guilde.
# Braintree
Source: https://docs.firstpromoter.com/integrations/billing/braintree
Connecting FirstPromoter with Braintree
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales and cancellations by connecting your Braintree account.
Refund tracking is not currently supported for Braintree. Only successful subscription charges and cancellations are tracked.
**Tracked webhook events:**
| Braintree Event | What FirstPromoter tracks |
| - | - |
| `SubscriptionChargedSuccessfully` | Sale / commission |
| `SubscriptionCanceled` | Cancellation |
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fbraintree) to view the setup guide.
# Chargebee
Source: https://docs.firstpromoter.com/integrations/billing/chargebee
Connecting FirstPromoter with Chargebee
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales, refunds, and cancellations by connecting your Chargebee account.
**Tracked webhook events:**
| Chargebee Event | What FirstPromoter tracks |
| - | - |
| `customer_created` | Signup (only when a tracking ID or referral ID is present) |
| `subscription_created` | Signup (including when a 100% discount is applied and no payment event fires) |
| `payment_succeeded` | Sale / commission |
| `payment_refunded` | Refund |
| `subscription_cancelled` | Cancellation |
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fchargebee) to view the setup guide.
# Paddle
Source: https://docs.firstpromoter.com/integrations/billing/paddle
Connecting FirstPromoter with Paddle
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter supports both **Paddle Classic** (v1 webhooks) and **Paddle Billing** (v2 webhooks), and automatically tracks sales, refunds, and cancellations from your Paddle account.
**Paddle Classic (v1) — tracked webhook events:**
| Paddle Event | What FirstPromoter tracks |
| - | - |
| `payment_succeeded` | Sale / commission |
| `subscription_payment_succeeded` | Sale / commission (recurring) |
| `payment_refunded` | Refund |
| `subscription_payment_refunded` | Refund (recurring) |
| `subscription_cancelled` | Cancellation |
VAT-only refunds (`refund_type` of `vat`) are ignored.
**Paddle Billing (v2) — tracked webhook events:**
| Paddle Event | What FirstPromoter tracks |
| - | - |
| `transaction.completed` | Sale / commission |
| `adjustment.created` | Refund — only when the adjustment's `action` is `chargeback` |
| `adjustment.updated` | Refund — only when the adjustment's `action` is `refund` |
| `subscription.canceled` | Cancellation |
Sales with a zero or negative amount are ignored, as are refunds and chargebacks that resolve to a zero amount.
## Paddle fees and commission amounts
The Paddle integration form has an **Exclude Paddle's fees** toggle that controls the amount commissions are calculated on:
| Toggle | Commission is calculated on |
| - | - |
| Off | Your earnings **plus** Paddle's fee |
| On | Your net earnings, after Paddle's fee is deducted |
This applies to both Paddle Classic and Paddle Billing, and it affects refund amounts as well as sales.
Changing this toggle only affects sales and refunds tracked from that point on. Commissions already recorded are not recalculated.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fpaddle) to view the setup guide.
# Recurly
Source: https://docs.firstpromoter.com/integrations/billing/recurly
Connecting FirstPromoter with Recurly
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales, refunds, and cancellations from your Recurly account.
**Tracked webhook events:**
| Recurly Event | What FirstPromoter tracks |
| - | - |
| `closed_invoice_notification` | Sale / commission |
| `paid_charge_invoice_notification` | Sale / commission |
| `successful_refund_notification` | Refund |
| `void_payment_notification` | Refund (voided payment) |
| `canceled_subscription_notification` | Cancellation |
Only invoices with a positive amount and a status of `collected` or `paid` are tracked as sales.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Frecurly) to view the setup guide.
# Stripe
Source: https://docs.firstpromoter.com/integrations/billing/stripe
Connecting FirstPromoter with Stripe
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter enables you to automatically track sales, refunds, and cancellations by connecting your Stripe account in Test or Live mode.
**Tracked webhook events:**
| Stripe Event | What FirstPromoter tracks |
| - | - |
| `invoice.payment_succeeded` | Sale / commission |
| `charge.succeeded` | Sale / commission (one-time charges) |
| `charge.refunded` | Refund |
| `charge.dispute.created` | Refund (disputed charge) |
| `customer.subscription.deleted` | Cancellation |
| `checkout.session.completed` | Signup |
| `customer.discount.created` | Signup (100% discount applied) |
Charges with an amount of zero, or with no associated customer email, are ignored. Invoices with `amount_paid` of zero are also skipped.
Click [here](https://login.firstpromoter.com?redirect=%2Fintegration%2Fstripe) to view the setup guide.
# API Integration
Source: https://docs.firstpromoter.com/integrations/tracking/custom/api
Track referrals server-side with the FirstPromoter Tracking API
`Difficulty: Intermediate`
`Developer Required: Yes`
With the FirstPromoter Tracking API you can track signups, sales, refunds, and cancellations directly from your backend — no JavaScript required.
**Available endpoints:**
| Endpoint | Purpose |
| - | - |
| `POST /api/v1/track/signup` | Track a lead sign-up |
| `POST /api/v1/track/sale` | Track a sale and generate a commission |
| `POST /api/v1/track/refund` | Track a refund and reverse a commission |
| `POST /api/v1/track/cancellation` | Track a subscription cancellation |
See the [Tracking API reference](/api-reference-v1/tracking-api/leads-and-signups) for full parameter documentation including deduplication via `event_id`, recurring commission scheduling, and custom fields.
## Using sub IDs, postbacks or ad tracking with the API
If you want to use **sub IDs**, **postbacks** or **ad tracking**, sending `ref_id` to `track/signup` is not enough. These features rely on data captured when the visitor clicks the referral link: the sub ID (`fp_sid`) from the link, the landing page URL with any ad click IDs, and the visit itself. FirstPromoter only records that data when the click is tracked by the tracking script, and only links it to the referral when you send the visit's `tid`.
A signup tracked with only `ref_id` is credited to the right affiliate, but it has no click attached. Its sub ID will be empty, postback values that come from the visit will be blank, and ad traffic can't be detected.
To keep this data, use the tracking script for clicks and the API for signups:
Add the [main tracking script](/guides/tracking-with-fprjs#installation) to every page a referral link can land on. When a visitor arrives through a referral link, the script tracks the click and sets the `_fprom_ref` and `_fprom_tid` cookies.
If visitors land on one domain and sign up on another, set up [cross-domain tracking](/script-docs/fpr-js-docs) so the cookies are available where the signup happens.
When the visitor signs up, read the `_fprom_tid` cookie on your server (or in the browser and send it to your server with the signup form).
Pass the cookie value in the `tid` parameter of [track/signup](/api-reference-v2/api-admin/tracking-api/leads-and-signups). FirstPromoter uses it to find the tracked click, credit the right affiliate, and attach the sub ID, landing URL and ad data to the referral.
```javascript Server side (Express) theme={null}
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(express.json());
app.post('/signup', async (req, res) => {
// Set by the FirstPromoter tracking script when the visitor clicked a referral link
const tid = req.cookies['_fprom_tid'];
// ...create the user in your app...
if (tid) {
await fetch('https://api.firstpromoter.com/api/v2/track/signup', {
method: 'POST',
headers: {
'Account-ID': '',
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: req.body.email, uid: req.body.uid, tid }),
});
}
res.sendStatus(201);
});
```
```sh cURL theme={null}
curl --request POST \
--url https://api.firstpromoter.com/api/v2/track/signup \
--header 'Account-ID: ' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"email": "customer1@gmail.com",
"uid": "cus_000001",
"tid": ""
}'
```
If there is no `_fprom_tid` cookie, the visitor didn't arrive through a tracked referral link (or their browser blocked the cookie), so don't send an empty `tid`. If you still know the referral ID, you can send it as `ref_id` instead, but sub IDs, postback visit data and ad tracking won't be available for that referral.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fapi) to view the in-app setup guide.
# Django
Source: https://docs.firstpromoter.com/integrations/tracking/custom/django
Adding FirstPromoter to your Django website
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our Django integration option.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fdjango) to view the guide.
# Google Tag Manager
Source: https://docs.firstpromoter.com/integrations/tracking/custom/gtm
Setting up your Main tracking script in Google Tag Manager (GTM)
`Difficulty: Intermediate`
`Developer Required: Yes`
With FirstPromoter you can setup click and signup tracking using our Google Tag Manager option.
This setup mainly requires you to add tracking scripts into your Google Tag Manager and sending details about the referrals using the script.
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
This procedure assumes you have already set up GTM to work on your website.
1. To get started on FirstPromoter:
* [Login](https://login.firstpromoter.com/) to your admin account.
* Navigate to Settings > Integrations > Integrate your website section of your dashboard.
* Click on the `Integrate` button.
* Click on the `setup` button or click on the `change` link for a new setup instructions.
* Under `Custom integration`, select the `JS` option.
* Copy the `Main tracking script` under the `JavaScript` tab.
2. Log in to Google Tag Manager:
* Navigate to your `Tags` section
* Click on `New` button (at top right corner)
* Click on the `Tag configuration` panel to open the TAG type selection panel.
* Scroll down and select the `Custom HTML` option
* Add/paste the `Main tracking script` copied from FirstPromoter into the `HTML` Section. As shown in the screenshot below:
* Now, you need to select when Google Tag Manager should trigger the script. To do this, scroll down to the `triggering` section, click on it and choose when to trigger the tag. We recommend selecting the `pages trigger` to load the `Main tracking script` on all your landing pages.
* Rename/change the name to `FirstPromoter Main Tracking Script`
* Save and publish your changes.
# JavaScript Tracking
Source: https://docs.firstpromoter.com/integrations/tracking/custom/js
Use our Javascript option to track clicks and sign-ups
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our JavaScript integration.
This setup mainly requires you to add tracking scripts into your website or web application integrating it at a code level.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fjavascript) to view the guide.
# Paddle Checkout
Source: https://docs.firstpromoter.com/integrations/tracking/custom/paddle-checkout
Tracking using Paddle Checkout
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
If you are using the paddle checkout feature on your website you can integrate with FirstPromoter.
This setup mainly requires you to add tracking scripts into your website and setting extra configurations on your paddle billing/classic checkout function `Paddle.Checkout.open()` or `Paddle.Initialize()`.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fpaddle-checkout) to view the guide.
# PHP
Source: https://docs.firstpromoter.com/integrations/tracking/custom/php
Adding FirstPromoter to your custom PHP website
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our PHP integration option.
This setup mainly requires you to add tracking scripts into your website or web application integrating it at a code level and sending details about the referrals using the script.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fphp) to view the guide.
# Ruby on Rails
Source: https://docs.firstpromoter.com/integrations/tracking/custom/rails
Adding FirstPromoter to your Rails website
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
With FirstPromoter you can setup click and signup tracking using our Rails integration option.
This setup mainly requires you to add tracking scripts into your website or web application integrating it at a code level and sending details about the referrals using the script.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Frails) to view the guide.
# Stripe Checkout
Source: https://docs.firstpromoter.com/integrations/tracking/custom/stripe-checkout
Tracking using Stripe Checkout
`Difficulty: Intermediate`
`Developer Required: Yes`
Depending on the complexity of your website it is ideal to have a developer assist you in the setup.
If you are using the [stripe checkout feature](https://stripe.com/en-ro/payments/checkout) on your website you can integrate with FirstPromoter.
You should have a checkout page similar to this. Otherwise we suggest you use our JavaScript option instead.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fstripe-checkout) to view the guide.
# Calendly
Source: https://docs.firstpromoter.com/integrations/tracking/platform/calendly
Working with FirstPromoter and Calendly
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our calendly integration option. This integration is for users who have custom websites and have Calendly added.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fcalendly) to view the guide.
# Drop-in Scripts
Source: https://docs.firstpromoter.com/integrations/tracking/platform/chargebee/drop-in-scripts
Integrating FirstPromoter with Chargebee Drop-in Scripts
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our `Chargebee Drop-in Scripts` integration option.
This setup mainly requires you to add/insert our ready made scripts into your website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fchargebee-drop-in-script) to view the guide.
# Hosted Pages
Source: https://docs.firstpromoter.com/integrations/tracking/platform/chargebee/hosted-pages
Integrating FirstPromoter with Chargebee Hosted pages
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our `Chargebee Hosted Pages` integration option.
This setup mainly requires you to add/insert our ready made scripts into your website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fchargebee-hosted-pages) to view the guide.
# ClickFunnels
Source: https://docs.firstpromoter.com/integrations/tracking/platform/clickfunnels
Adding FirstPromoter to your ClickFunnels website
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our ClickFunnels integration option.
This setup mainly requires you to add/insert our ready made scripts into your ClickFunnels website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fclickfunnels) to view the guide.
# Demio
Source: https://docs.firstpromoter.com/integrations/tracking/platform/demio
Adding FirstPromoter to Demio
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our Demio integration option.
This setup mainly requires you to add/insert our ready made scripts into your Demio registration page or your website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fdemio) to view the guide.
# DropFunnels
Source: https://docs.firstpromoter.com/integrations/tracking/platform/dropfunnels
Adding FirstPromoter to your DropFunnels website
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our DropFunnels integration option.
This setup mainly requires you to add/insert our ready made scripts into your DropFunnels website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fdropfunnels) to view the guide.
# Ghost
Source: https://docs.firstpromoter.com/integrations/tracking/platform/ghost
Adding FirstPromoter to your Ghost Website
`Difficulty: Easy`
`Developer Required: No`
The integration between FirstPromoter and Ghost is fully automated and does not require any additional scripts to be added.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fghost) to view the guide.
# Highlevel
Source: https://docs.firstpromoter.com/integrations/tracking/platform/highlevel
Adding FirstPromoter to Highlevel
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Highlevel integration option.
This setup mainly requires you to add/insert our ready made scripts into your Highlevel website.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fhighlevel)
# HubSpot
Source: https://docs.firstpromoter.com/integrations/tracking/platform/hubspot
Adding FirstPromoter to your HubSpot form
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking for websites that use HubSpot forms.
This setup mainly requires you to add/insert our ready made scripts into your website or HubSpot-hosted page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fhubspot) to view the guide.
# Jotform
Source: https://docs.firstpromoter.com/integrations/tracking/platform/jotform
Tracking with FirstPromoter when using Jotform
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking using our Jotform integration option.
This setup requires adding our ready made scripts to your landing and thank-you pages, along with a redirect in Jotform to pass the submitted email to your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fjotform) to view the guide.
# Kajabi
Source: https://docs.firstpromoter.com/integrations/tracking/platform/kajabi
Adding FirstPromoter to Kajabi
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Kajabi integration option.
This setup mainly requires you to add/insert our ready made scripts into your Kajabi website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fkajabi) to view the guide.
# Kartra
Source: https://docs.firstpromoter.com/integrations/tracking/platform/kartra
Adding FirstPromoter to Kartra
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Kartra integration option.
This setup mainly requires you to add/insert our ready made scripts into your Kartra website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fkartra) to view the guide.
# Kickpages
Source: https://docs.firstpromoter.com/integrations/tracking/platform/kickpages
Adding FirstPromoter to Kickpages
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Kickpages integration option.
This setup mainly requires you to add/insert our ready made scripts into your Kickpages website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fkickpages) to view the guide.
# Recurly Hosted Pages
Source: https://docs.firstpromoter.com/integrations/tracking/platform/recurly-hosted-pages
Integrating FirstPromoter with Recurly Hosted pages
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup referral tracking using our `Recurly Hosted Pages` integration option. This is only needed if you use Recurly's hosted checkout pages — this setup mainly requires you to add/insert our ready made script into your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Frecurly-hosted-pages) to view the guide.
# Samcart
Source: https://docs.firstpromoter.com/integrations/tracking/platform/samcart
Adding FirstPromoter to Samcart
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Samcart integration option.
This setup mainly requires you to add/insert our ready made scripts into your Samcart website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fsamcart) to view the guide.
# Payment Links
Source: https://docs.firstpromoter.com/integrations/tracking/platform/stripe/payment-links
Adding FirstPromoter when using Stripe payment links
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our `Stripe Payment Links` integration option. This setup mainly requires you to add/insert our ready made scripts into your website pages where you have buy/payment checkout links such as `https://buy.stripe.com/xxxxx`
NB: If you are using your custom domain with stripe, you will need to change the link in the code that will be provided in your FirstPromoter dashboard from `https://buy.stripe.com/` to your checkout page's custom domain.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fstripe-payment-links) to view the guide.
# Pricing Table
Source: https://docs.firstpromoter.com/integrations/tracking/platform/stripe/pricing-table
Adding FirstPromoter when using Stripe pricing table
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup/referral tracking using our `Stripe Pricing Table` integration option. This setup mainly requires you to add/insert our ready made scripts into your website pages where you have `` html tag.
To get the best results for tracking when using Stripe pricing tables, add the scripts to all pages where `` html tags are available.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fstripe-pricing-table) to view the guide.
# Thinkific
Source: https://docs.firstpromoter.com/integrations/tracking/platform/thinkific
Adding FirstPromoter to Thinkific
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our Thinkific integration option.
This setup mainly requires you to add/insert our ready made scripts into your Thinkific website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fthinkific) to view the guide.
# ThriveCart
Source: https://docs.firstpromoter.com/integrations/tracking/platform/thrivecart
Adding FirstPromoter to ThriveCart
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and signup tracking using our ThriveCart integration option.
This setup mainly requires you to add/insert our ready made scripts into your ThriveCart website platform.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fthrivecart) to view the guide.
# Typeform
Source: https://docs.firstpromoter.com/integrations/tracking/platform/typeform
Tracking with FirstPromoter when using Typeform
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking using our Typeform integration option.
This setup requires adding our ready made scripts to your landing and thank-you pages, along with a redirect in Typeform to pass the submitted email to your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Ftypeform) to view the guide.
# WebinarJam
Source: https://docs.firstpromoter.com/integrations/tracking/platform/webinarjam
Tracking with FirstPromoter when using WebinarJam registration form
`Difficulty: Easy`
`Developer Required: No`
With FirstPromoter, you can setup click and referral tracking using our WebinarJam integration option.
This setup requires adding our ready made scripts to your landing and thank-you/confirmation pages, along with a custom confirmation page redirect in WebinarJam to pass the registrant's email to your thank-you page.
Click [here](https://login.firstpromoter.com?redirect=%2Finstructions%2Fwebinar-jam) to view the guide.
# WordPress
Source: https://docs.firstpromoter.com/integrations/tracking/platform/wordpress
Add FirstPromoter affiliate tracking to your WordPress website using our dedicated plugin.
`Difficulty: Easy`
`Developer Required: No`
FirstPromoter has a dedicated WordPress plugin that handles click tracking, referral tracking, and sales tracking with built-in support for WooCommerce, MemberPress, Contact Form 7, OptimizePress, custom forms, URL-based email capture, and payment links.
***
## Installing the plugin
1. Log in to your WordPress admin dashboard.
2. Go to **Plugins → Add New**.
3. Search for **"FirstPromoter"** in the search bar.
4. Click **Install Now**, then **Activate**.
Alternatively, download the plugin directly from the WordPress Plugin Directory and upload it manually via **Plugins → Add New → Upload Plugin**.
***
## Base configuration
Once activated, go to **FirstPromoter** in the WordPress admin sidebar.
### Account ID
Required for the tracking script to work on your site.
1. In your FirstPromoter dashboard, go to **Settings → Integrations**.
2. Copy your **Account ID** and paste it into the **Account ID** field in the plugin settings.
### API Key
Required for sale tracking (WooCommerce, MemberPress, Contact Form 7).
1. In your FirstPromoter dashboard, go to **Settings → Integrations → Manage API keys**.
2. Copy your **API key** and paste it into the **API Key** field in the plugin settings.
### Cross-domain tracking *(optional)*
If you have multiple domains that need to share tracking data, enter them as a comma-separated list in the **Cross-domain tracking** field.
```
example.com, shop.example.com
```
Not needed if you are only using subdomains of the same root domain.
### Force tracking for ad-blockers *(optional)*
Enable **Force tracking even in privacy browsers or with ad-blockers** to use a server-side fallback that keeps referral attribution working when the client-side script is blocked.
***
## Integrations
### WooCommerce
The plugin automatically tracks WooCommerce account registrations, checkouts, refunds, and cancellations.
**Signup tracking** — Enable **Capture email on new account creation** and/or **Capture email on checkout** to record the customer's email when they register or complete a purchase. No API key required.
**Sale tracking** — Enable **Send sale to FirstPromoter on checkout** to send order data (amount, order ID, coupon codes) to FirstPromoter when an order is marked as processing or completed. Requires an API key.
The plugin also handles:
* **Refunds** — automatically generates a negative commission when an order is refunded.
* **Cancellations** — updates the customer's status in FirstPromoter when an order is cancelled.
***
### MemberPress
**Signup tracking** — Member registrations are captured automatically when the integration is enabled. No API key required.
**Sale tracking** — Enable **Track sales/transactions via API** to send transaction data to FirstPromoter. Requires an API key.
Enable **Track recurring payments via API** to track subscription renewals. Requires an API key.
If you are already using FirstPromoter's native Stripe integration to track payments, leave MemberPress sale tracking **disabled** to avoid duplicate commissions being recorded.
***
### Contact Form 7
Enable Contact Form 7 tracking to automatically capture form submissions and send them to FirstPromoter. The plugin auto-detects email fields — any field with "email" in its name is captured. Requires an API key.
***
### OptimizePress
Enable OptimizePress tracking to capture form submissions from OptimizePress pages. No API key required.
***
### Custom form tracking
Track email submissions from any form on your site using CSS selectors.
1. Enable **Custom Form Tracking** in the plugin settings.
2. For each form, enter:
* **Email input selector** — CSS selector for the email field (e.g. `input[name="email"]`).
* **Submit selector** — CSS selector for the submit button or form element (e.g. `button[type="submit"]`).
3. To track multiple forms, check **I have multiple forms to track** and add additional selector pairs.
The plugin uses a MutationObserver to detect dynamically loaded forms, including popups and AJAX-injected content. A server-side AJAX fallback is included for cases where ad-blockers interfere (requires **Force tracking** to be enabled).
***
### URL email capture
Useful when an external checkout or funnel redirects back to your WordPress site with the customer's email in the URL (e.g. a thank-you page).
1. Enable **URL Email Capture** in the plugin settings.
2. Enter the **Email URL Parameter Key** — the query parameter name that contains the email.
* Example: for `/thank-you?email=user@example.com`, enter `email`.
3. *(Optional)* Enter the **UID URL Parameter Key** if your platform also passes a user ID.
* Example: for `/thank-you?email=user@example.com&uid=12345`, enter `uid`.
No API key required.
***
### Payment links
Automatically appends the FirstPromoter tracking ID to payment links on your pages as the `client_reference_id` parameter, so conversions through direct payment links are attributed to the right affiliate.
1. Enable **Payment Links** in the plugin settings.
2. Enter the **Payment Link URL Prefix** — links starting with this value will be updated automatically. Defaults to `https://buy.stripe.com/`. Use a comma to separate multiple prefixes.
```
https://buy.stripe.com/, https://checkout.mybrand.com/
```
This integration is for direct payment links embedded on your WordPress pages. If you are not placing `buy.stripe.com` links (or equivalent) directly on your site, this integration is not needed.
# Introduction
Source: https://docs.firstpromoter.com/introduction
Turn Affiliate Marketing into Your Competitive Advantage
## What is FirstPromoter
FirstPromoter is a modern and reliable affiliate tool for subscription-based/SaaS companies that enables you to track, manage and optimize referral-based marketing programs. It is easy to set up, yet powerful to scale with your growing needs.
Instead of coding your own affiliate programs, you can simply integrate with FirstPromoter to handle your affiliate programs for you with a few lines of code.
### Benefits of using FirstPromoter
Set your own domain (with SSL encryption support) for affiliate dashboard and sign up pages.
Give performance bonuses and personalize the commissions and rewards scheme for each affiliate individually.
Oversee the performance of your affiliate program across 18 data points.
Affiliates get commissions only when the purchase is confirmed by your billing provider. We also have algorithms to identify suspicious leads.
No redirects. No ugly short-links. Get the maximum SEO juice with referral links in 8 formats.
Get your teammates inside FirstPromoter. You can set 4 different user roles ( `Manager`, `Admin`, `Admin Plus`, `Super Admin`) and restrict access to certain campaigns.
We support 190 currencies and can do conversions in 170. We use daily updated exchange rates and you can apply your own exchange fee.
Get unlimited flexibility on your affiliates' dashboard. From enabling services like live-chat, surveys or analytics to changing the design completely.
You can embed the affiliate dashboard inside your application and log your users in automatically, without asking them to enter a password or email.
### Key Features
Follow the step-by-step setup to start your first affiliate program, no matter how simple or complex your affiliate scheme is.
Edit the affiliate dashboard to make it yours. Add your colors, logo, and choose the layout that suits you.
Track sales by discount coupon codes alone, email or personalized referral links.
Oversee the performance of your affiliate program across 18 data points.
Pay hundreds of affiliates at once, directly from the FirstPromoter dashboard.
# Quickstart
Source: https://docs.firstpromoter.com/quickstart
Start building your awesome affiliate or referral program in minutes.
### Steps
[Click here](https://firstpromoter.com/company/signup) to create an Admin account. If you already have an account, [Login here](https://login.firstpromoter.com/)
If you are a new user, you will need to complete the onboarding process, which involves creating a campaign, connecting your billing provider, and integrating your website.
Connect your billing provider to FirstPromoter. This will enable FirstPromoter to automatically track sales, refunds, upgrades or upsells and cancellations data/record from any of the [supported billing providers](/integrations/billing).
**NB:** For a billing provider that is not supported by default, there is an option to use our [API](/integrations/billing/api)
Install or add our ready-made scripts/pixels to your website or [platform](/integrations/tracking/platform). We also provide [universal scripts and an API for custom-built websites or apps](/integrations/tracking/custom).
Integrating the tracking script into your website enables you to track clicks and referrals (thus, it allows you to send the lead's or referral's details such as the `email` or `uid` to FirstPromoter).
When combined with the billing provider integration, this setup enables FirstPromoter to track sales by linking referral information with transaction data from your billing provider. [Learn more about our tracking script here](/script-docs/fpr-js-docs)
You can also track sales using `Coupon Codes`. This option is available for users who want `No-Code` or `No-Scripts` integration or want an alternative to traditional referral links. [Learn more](https://help.firstpromoter.com/en/articles/8971002-how-to-track-sales-with-coupon-codes-in-firstpromoter)
Test all parts of your integration to make sure everything is tracking.
* Clicks tracking
* Referral tracking
* Sales tracking
# Advanced use cases & examples
Source: https://docs.firstpromoter.com/script-docs/advanced
## Passing the ref id programmatically
`fpr("init",{cid:"...",ref_id:"..."})`
Getting the ref id from the url and passing it to fpr init
```html Custom query parameter theme={null}
```
```html Custom hash theme={null}
```
## Passing the ref id programmatically from a query string
```html theme={null}
```
## Forcing a new tid to be created or reinitializing the FirstPromoter cookies
You can force a new tid to be created by invalidating the old one. This can be done by passing cookie\_ref\_id: 'xxx' as shown in the example below
```js theme={null}
fpr("referral",{email: getParam("wj_lead_email")}, function(){
window.fpr("click",{cookie_ref_id: 'xxx'});
});
```
It can also be used to force new emails to be collected on page refresh
```html theme={null}
```
## Setting a default Promoter
```html theme={null}
```
# Concepts & Key Terminologies
Source: https://docs.firstpromoter.com/script-docs/concepts
List of concepts and key terminologies used in the documentation
## Promoter
Promoters/Affiliates are individuals or companies who drive traffic to a company’s website, products, or services through referral links and earn a commission when that traffic converts.
## Clicks
Clicks are the number of unique visits to your website via the referral link. **NB:** The user's first click on your website via the referral link is what is counted.
## Referral
A referral is an individual or business that signs up for or purchases a service using a referral link. A referral can either be a lead or a customer.
## Lead
A lead is an individual or business that signs up on your website using a referral link but hasn't purchased from your website.
## Customer
A customer is an individual or business that signed up on your website using a referral link and has made at least one purchase from your website.
## Sale
A sale occurs when a customer makes a purchase using a referral link. We generate rewards or commissions only for sales.
## Referral Tracking
This refers to when the referral details (email address/UID) are sent to FirstPromoter from your website after they sign up or fill out a form. This can be done using the referral tracking script or API.
## Sale Tracking
This refers to when payments are tracked from your billing provider, allowing commissions to be generated for your affiliates.
## ref\_id
This is the referral id/token assigned to an affiliate/promoter once they signup or are added to a campaign. It is generated by FirstPromoter by default and can be set using our API as well. If a referral link is used it is set as a cookie `_fprom_ref` in your browser
## tid
This is a tracking ID that is dynamically generated by FirstPromoter when someone visits a referral link. This ID is set as a cookie called `_fprom_tid` in your browser.
# FirstPromoter JavaScript Library (fpr.js)
Source: https://docs.firstpromoter.com/script-docs/fpr-js-docs
This is a reference document for all the methods available in FirstPromoter's browser-side JavaScript Library, fpr.js
# Including fpr.js
On your FirstPromoter dashboard, under the Settings> Integrations> Integrate your website section, based on the selections you make, you are provided with some scripts which are to be added to your website.
It is ideal that the script is added globally on the HEAD section of every marketing or public page of your website.
```html theme={null}
```
For JavaScript frameworks, you can simply insert the script on the public index.html page so it will be available when the framework loads.
For WordPress websites, you can add the scripts to your header.php file before the closing head tag.
To get the best performance, it is ideal that you have the scripts added to all the pages where you need tracking to take place. Also, the Scripts are loaded asynchronously and will not affect the website loading speed.
# Functions
## fpr("init",options, callback?)
This method initializes FirstPromoter with the provided options. Most of these options are loaded automatically when the script loads, but they can be overwritten by passing different ones to the method. The most used one is "ref\_id" which forces the script to track a specific promoter.
### Parameters
#### Available keys
| Property | Description |
| - | - |
| cid | FirstPromoter Company Id (required) |
| ref\_id | Referral id/token of the promoter |
| tid | Tracking ID, value stored in fprom\_tid cookie |
| url | Current URL |
| domain | Current domain |
| referrer | Browser referrer/ domain of the previous visited website |
Setting properties that are not in the list above will be ignored.
A function that will be called after the init function is triggered.
## fpr("click",payload?, callback?)
This method is responsible for click tracking.
### Parameters
This overwrites the stored data exactly like the fpr("init"…) function does before tracking the click.
#### Available keys
| Property | Description |
| - | - |
| cid | FirstPromoter Company Id |
| ref\_id | Referral id/token of the promoter |
| tid | Tracking ID, value stored in fprom\_tid cookie |
| url | Current URL |
| domain | Current domain |
| referrer | Browser referrer/ domain of the previous visited website |
Setting properties that are not in the list above will be ignored.
The callback function receives the response data object and can then be extracted and used
### Example
```javascript click theme={null}
fpr("click")
```
```javascript click_with_referral_id theme={null}
fpr("click", {ref_id: 'xxx'})
```
***
## fpr("onReady",callback)
This method checks if the tracking script is initialized and fully loaded on the page.
### Parameters
The callback function receives the response data object and can then be extracted and used
### Example
```javascript click theme={null}
fpr("onReady", function(data){
console.log(data)
})
```
***
## fpr("referral",payload, callback?)
This method is used primarily to send the referral details to FirstPromoter. It takes as its payload the email of the referral/lead
### Parameters
The callback function receives the response data object and can then be extracted and used
#### Available keys
| Property | Description |
| - | - |
| email | actual email of the user |
| uid | user id of the user |
Setting properties that are not in the list above will be ignored.
### Example
```javascript referral theme={null}
fpr('referral',{email:actual_user_email@email.com, uid: 123456})
```
```javascript referral_with_callback theme={null}
fpr('referral',{email:actual_user_email@email.com, uid: 123456},
function(){console.log("referral submitted")
})
```
***
## fpr("details",callback)
This method is used in getting the details of the promotion and the promoter. **To avoid making multiple requests, it is important to note that the details are stored in a cookie called "fprom\_details" and is available for a day.**
### Parameters
The callback function receives the response data object and can then be extracted and used
### Response Format
```javascript theme={null}
{
ref_id:
promo_code:
campaign_id:
customer_promo_code:
offer:
promoter: {
id:
first_name:
last_name:
}
}
```
### Example
```javascript click theme={null}
fpr("details", function(data){
console.log(data)
})
```
***
## fpr("crossDomain",domains)
This method is used when attempting to track across multiple domains. It mainly appends the tracking details to all links to the domain provided. Note: this works with only direct links and should be added preferably to the footer section or called when the whole page is loaded
The crossDomain(s) you want to track
### Example
```javascript one domain theme={null}
fpr('crossDomain','newwebsite.com')
```
```javascript multiple domains theme={null}
fpr('crossDomain',['newwebsite.com', 'newwebsite1.com', 'newwebsite2.com'])
```
## fpr("urlTracking")
This method is used for Direct URL tracking, thus, if you have landing pages for your affiliates/promoters, you can use the method on those pages if you don't want the affiliates/promoters "Referral ID" to be part of their referral links.
For this method to work, you will have to first add FirstPromoter's main tracking scripts to the landing page(s) and also enable "Direct URL tracking" on FirstPromoter. To do so, please check out this article: [How to enable direct URL tracking in FirstPromoter](https://help.firstpromoter.com/en/articles/8971394-how-to-enable-direct-url-tracking-in-firstpromoter)
Please note that the method **should not** be used on your homepage, but instead should only be used on all landing pages of your affiliates/promoters.
```js theme={null}
```