Skip to main content

How to embed the promoter dashboard inside your app and automatically log promoters in

Embedding the affiliate dashboard into your custom app

Maxwell Adapoe avatar
Written by Maxwell Adapoe
Updated today

In FirstPromoter, you can embed the entire promoter dashboard inside your website and automatically log your promoters in without requiring them to enter an email or password.

​*Please note:
The set-up requires a developer to assist.
This requires you to set up a custom domain on FirstPromoter and also be on the Business plan or above. The instructions can be found here.

To log the promoter in, you need to make an API request to get an access token and use that in logging your promoter in via the iframe. Below are the steps to follow:

Steps to implement

1. Get your API credentials

Grab your Account ID and API Key from your "Settings" > "Integrations" page > "Manage API Keys". You'll need both for authentication.


Please do not use the legacy v1 keys. Click on Manage API Keys and create a new key

2. Make the API request

To avoid exposing your API credentials, make a POST request on the backend of your application to https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=xxxxx where xxxxx is the promoter_id.

  • URL: https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=xxxxx

  • Method: POST

  • Headers:

    • Authorization: Bearer {your_api_key}

    • Account-Id: {your_account_id}

  • Body: Empty (promoter_id is passed in the URL)
    1. Grab your API key from your "Settings" > "Integrations" page and set it in the header as X-API-KEY.

How do I get the promoter id?

You can get the promoter id:

a) When you create the Promoter via the API you'll get in the JSON response the id value in the response. Save the "id" to the corresponding user object on your system.

b) When you create the promoter via the API you can pass the user id from your system as the cust_id parameter. This will be saved as a field and can be used to query FirstPromoter to get the promoter details as shown here. In the response you can grab the ID of the promoter and use in making your request.

c) From the promoter_accepted webhook. If you don't handle the Promoter creation using the API, you can still get the id from the webhook notification we send you when a promoter signs up from our sign up form. You will need to save the "id" somewhere in your system.


3. Handle the API response

The POST request will return a response with the access token and an expiration time:

{
"access_token": "xxxxxxxxxxxxxxx",
"expires_in": 86400
}

4. Create the iframe

Create an iframe on your page and grab the "access_token" from the response, return it to your Frontend and set iframe src as https://<yourcustom.domain.com>/iframe?tk={{access_token}}.

Your full iframe code should look like this:

<iframe allow="clipboard-write" height="850px" width="100%" frameborder="0" src="https://<yourcustom.domain.com>/iframe?tk={{access_token}}"></iframe>

IMPORTANT: Make sure the iframe is added inside a protected area of your website that is not accessible to search engines or the public. The token expires after 24 hours, so it is best to fetch the token on every page refresh.

Code Examples

Below are some examples of how your code will look like:

BACKEND

Node

//node backend
var express = require("express");
var axios = require("axios");
var app = express();
var bodyParser = require("body-parser");
var cors = require('cors');

app.use(bodyParser.json());
app.use(cors());

app.post("/fp-iframe-login", function (req, res) {
var promoter_id = req.body.promoter_id;
var accountId = "your_account_id"; // Replace with your account ID
var apiKey = "your_api_key"; // Replace with your API key

console.log("Requesting iframe login for promoter:", promoter_id);

axios
.post(
`https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=${promoter_id}`,
{},
{
headers: {
"Authorization": `Bearer ${apiKey}`,
"Account-Id": accountId
}
}
)
.then(function (response) {
res.send(response.data.access_token);
})
.catch(function (error) {
console.log("Error occurred:", error.response?.data || error.message);
res.status(500).send("Authentication failed");
});
});


PHP

// php backend

<?php

$apiKey = "your_api_key"; // Replace with your API key
$accountId = "your_account_id"; // Replace with your account ID

// Create a new HTTP client
$client = new GuzzleHttp\Client();

// Handle POST request on /fp-iframe-login route
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/fp-iframe-login') {
$input = json_decode(file_get_contents('php://input'), true);
$promoterID = $input['promoter_id'];

$url = 'https://v2.firstpromoter.com/api/v2/promoters/iframe_login?promoter_id=' . $promoterID;
$headers = [
'Authorization' => 'Bearer ' . $apiKey,
'Account-Id' => $accountId
];

try {
$response = $client->post($url, ['headers' => $headers]);

$data = json_decode($response->getBody()->getContents(), true);
echo $data['access_token'];
} catch (Exception $e) {
http_response_code(500);
echo "Authentication failed";
}

exit;
}

?>

FRONTEND

React


//react frontend
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function MyIframeComponent() {
const [loading, setLoading] = useState(true);
const [loadingError, setLoadingError] = useState(false);
const [accessToken, setAccessToken] = useState(null);

useEffect(() => {
axios.post('http://localhost:3000/fp-iframe-login', { promoter_id: 7497107 })
.then((response) => {
setAccessToken(response.data);
})
.catch((error) => {
console.log(error);
setLoadingError(true);
})
.finally(() => {
setLoading(false);
});
}, []);

return (
<div>
{loading || loadingError ? (
<div>
{loading ? <div>Loading the iframe</div> : null}
{loadingError ? <div>Oops, there seems to have been a problem</div> : null}
</div>
) : (
<iframe
height="850px"
width="100%"
frameBorder="0"
allow="clipboard-write"
src={`https://mycustom.domain.com/iframe?tk=${accessToken}`}
/>
)}
</div>
);
}

export default MyIframeComponent;

Vue

\\ vue frontend 
<template>
<div>
<div v-if="loadingError || loading">
<div v-if="loading">Loading the iframe</div>
<div v-if="loadingError">Oops there seems to have been a problem</div>
</div>

<iframe
v-else
height="850px"
width="100%"
frameborder="0"
allow="clipboard-write"
:src="`https://mycustom.domain.com/iframe?tk=${accessToken}`"
/>
</div>
</template>

<script setup>
import { onBeforeMount, ref } from 'vue'
import axios from 'axios'

const loading = ref(true)
const loadingError = ref(false)
const accessToken = ref(null)

onBeforeMount(() => {
axios
.post('http://localhost:3000/fp-iframe-login', { promoter_id: 7497107 })
.then((response) => {
accessToken.value = response.data
})
.catch((error) => {
console.log(error)
loadingError.value = true
})
.finally(() => {
loading.value = false
})
})
</script>

Angular

//angular
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-my-component',
template: `
<div>
<div *ngIf="loadingError || loading">
<div *ngIf="loading">Loading the iframe</div>
<div *ngIf="loadingError">Oops, there seems to have been a problem</div>
</div>

<iframe
*ngIf="!loading && !loadingError"
height="850px"
width="100%"
frameborder="0"
allow="clipboard-write"
[src]="iframeSrc"
>
</iframe>
</div>
`,
})
export class MyIframeComponent implements OnInit {
loading = true;
loadingError = false;
accessToken: string | null = null;
iframeSrc = '';

constructor(private http: HttpClient) {}

ngOnInit(): void {
this.http
.post<string>('http://localhost:3000/fp-iframe-login', { promoter_id: 7497107 })
.subscribe({
next: (response) => {
this.accessToken = response;
this.iframeSrc = `https://mycustom.domain.com/iframe?tk=${this.accessToken}`;
},
error: (error) => {
console.log(error);
this.loadingError = true;
},
complete: () => {
this.loading = false;
}
});
}
}

JavaScript

<!DOCTYPE html>
<html>
<head>
<title>FirstPromoter Dashboard Embed</title>
</head>
<body>
<div id="container">
<!-- iframe will be rendered here -->
</div>

<script>
const container = document.getElementById('container');
let loading = true;
let loadingError = false;
let accessToken = null;

// Show loading state
renderLoading();

fetch('http://backend/fp-iframe-login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ promoter_id: 7497107 })
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.text();
})
.then(data => {
accessToken = data;
renderIframe();
})
.catch(error => {
console.log(error);
loadingError = true;
renderError();
})
.finally(() => {
loading = false;
});

function renderIframe() {
container.innerHTML = '';
const iframe = document.createElement('iframe');
iframe.height = '850px';
iframe.width = '100%';
iframe.frameBorder = '0';
iframe.allow = 'clipboard-write';
iframe.src = `https://mycustom.domain.com/iframe?tk=${accessToken}`;
container.appendChild(iframe);
}

function renderError() {
container.innerHTML = '';
const errorDiv = document.createElement('div');
errorDiv.textContent = 'Oops, there seems to have been a problem';
container.appendChild(errorDiv);
}

function renderLoading() {
container.innerHTML = '';
const loadingDiv = document.createElement('div');
loadingDiv.textContent = 'Loading the iframe';
container.appendChild(loadingDiv);
}
</script>
</body>
</html>

Did this answer your question?