Skip to main content
All CollectionsAffiliate Portal
How to embed the promoter dashboard inside your app and automatically log promoters in
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 over a week ago

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:

1. Grab your API key from your "Settings" > "Integrations" page and set it in the header as X-API-KEY.

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

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. The POST request, made in step 2, will return a response with the access token and an expiration time:

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

4. 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 general public. The token expires after 24 hours, so it is best to fetch the token on every page refresh.

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 APIKey = "6f3dc10858030a7ab12509ab4855517f";
console.log(" hello i am here ");
axios
.post(
`https://v2.firstpromoter.com/api/v1/promoters/iframe_login`,
{promoter_id},
{
headers: {
"X-API-KEY": APIKey,
},
}
)
.then(function (response) {
res.send(response.data.access_token);
})
.catch(function (error) {
console.log("oops! something went wrong");
console.log(error);
});
});


PHP

// php backend

<?php

$apiKey = "6f3dc10858030a7ab12509ab4855517f";
// 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') {
$promoterID = $_POST['promoter_id'];
$url = 'https://v2.firstpromoter.com/api/v1/promoters/iframe_login?promoter_id=' . $promoterID;
$headers = [
'X-API-KEY' => $apiKey
];
$response = $client->post($url, ['headers' => $headers]);
echo $response->getBody()->getContents();
exit;
}

?>

FRONTEND

React


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

function MyComponent() {
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>
);
}

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]="`https://mycustom.domain.com/iframe?tk=${accessToken}`"
>
</iframe>
</div>
`,
})
export class MyComponent implements OnInit {
loading = true;
loadingError = false;
accessToken = null;

constructor(private http: HttpClient) {}

ngOnInit(): void {
this.http
.post('http://localhost:3000/fp-iframe-login', { promoter_id: 7497107 })
.subscribe((response) => {
this.accessToken = response;
}, (error) => {
console.log(error);
this.loadingError = true;
}, () => {
this.loading = false;
});
}
}

JavaScript

<!DOCTYPE html>
<html>
<head>
<title>Vanilla JavaScript Version</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;

fetch('http://localhost:3000/fp-iframe-login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ promoter_id: 7497107 })
})
.then(response => response.json())
.then(data => {
accessToken = data;
renderIframe();
})
.catch(error => {
console.log(error);
loadingError = true;
renderError();
})
.finally(() => {
loading = false;
});

function renderIframe() {
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() {
const errorDiv = document.createElement('div');
errorDiv.textContent = 'Oops, there seems to have been a problem';
container.appendChild(errorDiv);
}

function renderLoading() {
const loadingDiv = document.createElement('div');
loadingDiv.textContent = 'Loading the iframe';
container.appendChild(loadingDiv);
}

if (loading) {
renderLoading();
}
</script>
</body>
</html>

Did this answer your question?