We Generated $19,243 ARR With a Self-Built Affiliate Program That Consists of Only 30 Lines of Code. Here’s How It Works

Our MarTec start-up Friendly currently generates an annually recurring revenue (ARR) of $27,106. Of this, a whopping 71% ($19,243) came from our affiliates and agency partners:

Six active customers came through affilates and agency partners, including our largest customer. Another one is still in the trial phase.

I decided to develop the affiliate program myself and not to rely on an existing solution like Rewardful. I had three reasons for this:

  1. I wanted to have maximum control over the affiliate program so that I could influence every aspect myself.
  2. The integrity of our affiliates and partners is of the utmost importance to me. There are many ways in which bad affiliates can even harm you. That is why I did not want a fully automated solution. Instead, I do things that don’t scale: I make a personal video call with each potential affiliate before we work together.
  3. Another aspect is of course the cost – having your own solution will save you money for a tool. But that was not the main reason for my decision.

In this article I am going to show you the implementation of our affiliate program in detail in three simple steps.

Important note: if you don’t want to deal with web development or are looking for a fully automated tool, then this article is not for you. In this case I would choose an external tool.

Step 1: Define a URL parameter for your affiliates and save the value in a cookie

First of all, you should define a parameter that your affiliates can use for posts on social media, blog posts, etc. With this parameter you can track which affiliate a lead came from.

We use the parameter “ref” for our affiliate program. Example:


In this case I know that a lead has come from our affiliate Jessica. Alternatively you can use any other name as parameter, e.g. “via=jessica”.

For technical reasons, you will only see this parameter once – the first time someone visits the site via this affiliate link. If the person clicks on another page of your website, the parameter disappears.

Therefore you have to save the parameter immediately into a cookie, which you can read out later – e.g. during the checkout process. You can do this easily via Javascript by including this code snippet on each of your pages:

<script type='text/javascript'>

/* Simple affiliate tracking script
 * @author      Stefan Vetter
 * @link        https://friendly.is
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html

/* Affiliate cookie settings */

	// Set the URL parameter name to "ref". You can choose any other name here
var paramName = "ref";

	// Set the duration to one year. You can just change the duration by changing the numbers below (it's the duration in seconds that the cookie should last)
var cookieDuration = 3600 * 1000 * 24 * 365;

/* You should not need to edit below this point */

	// Get an URL parameter
function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));

	// Get a specific cookie
getCookie = function (name) {
	var value = "; " + document.cookie;
	var parts = value.split("; " + name + "=");
	if (parts.length == 2) return parts.pop().split(";").shift();

	// Get the domain name from an URL
function getDomainFromUrl(url) {
    var a = document.createElement('a');
    a.setAttribute('href', url);
    return a.hostname;

	// If the URL contains parameters (the stuff after a "?"), proceed
if (window.location.search) {   

			// If the visitor does not come from a search engine, proceed (I don't want our affiliates to buy ads on Google etc.)
    if (/google|bing/i.test(getDomainFromUrl(document.referrer)) == false ) {

				// If there is not already a cookie for an affiliate set, proceed
	    if (!getCookie(paramName)) {
				// Set the cookie
			var expires = new Date(Date.now () + cookieDuration );
			document.cookie = paramName + '=' +getParameterByName(paramName) + ';path=/; expires=' + expires.toUTCString() + ';';



Of course you can also put the code into a separate .js file and then embed it into the website:

<script type='text/javascript' src='path/to/your/file.js'></script>

Here you can download the script as JavaScript file: affiliate.js

Step 2: Read affiliate cookie at checkout

In step 1 we made sure that we put the affiliate source into a cookie.

In this step we will read this cookie when creating a new customer account in order to assign the customer to the appropriate affiliate.

If you are using PHP, this is easily done with the system variable $_COOKIE:

$affiliate = htmlspecialchars($_COOKIE["ref"]);

If you use a different programming language, just search for “read cookie” + the appropriate programming language.

If you use a no-code tool like Typeform for the checkout, you can alternatively simply read the cookie with Javascript and attach it to the checkout link.

This could be done with this code, for example:

<script type='text/javascript'>

/* Simple affiliate no-code checkout script
 * @author      Stefan Vetter
 * @link        https://friendly.is
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html

// Read cookie. Just change the name of the cookie to the one from step 1.
var affiliateName = getCookie("ref");

	// If an affiliate cookie is set, proceed. 
if (affiliateName) {

		// set listener to wait until DOM is fully loaded
    document.addEventListener("DOMContentLoaded", function(e) {

				// Get all the links on the site
			var links = document.getElementsByTagName("a");
			for (var i = 0; i < links.length; i++) {	
					// If link goes to a certain domain, append a parameter to transmit the affiliate name (just change domain name accordingly)
				if (links[i].getAttribute("href").match(/^https:\/\/yourname\.typeform\.com\/to\/WWaDcN/i)) {
						// Change the parameter name as needed
					links[i].setAttribute("href", links[i].getAttribute("href") + "#affiliate=" + affiliateName );

	// Add getCookie function if not already set
if (typeof getCookie !== "function") { 

		// Get a specific cookie
	getCookie = function (name) {
		var value = "; " + document.cookie;
		var parts = value.split("; " + name + "=");
		if (parts.length == 2) return parts.pop().split(";").shift();


You can download it here: affiliate-checkout.js

Step 3: Create commission dashboard for affiliates

After you have read and submitted the name of the affiliate in step 2, you should of course save it in your customer database.

The last step would be to give your affiliates access to a dashboard where they can view their referrals and commissions.

We currently still manage our customers quite simply in a Google spreadsheet. In the future we will certainly have a more sophisticated solution for this – so far we had other priorities.

My goal was to read the relevant data from this table for each affiliate. Of course, each affiliate should only have access to the data of his/her customers.

I solved this by creating a separate Google spreadsheet for each affiliate. I then share this new spreadsheet only with the corresponding affiliate.

This is what the dashboard of one of our affiliates looks like:

I automatically import this data from our main customer spreadsheet – to which the affiliate has no access. To do this, I use the IMPORTRANGE function of Google Spreadsheets as part of the Google Query Language:

=QUERY(IMPORTRANGE("https://docs.google.com/spreadsheets/d/abc123","Tab Name!A:N"), "select Col1, Col2, Col3, Col4, Col11,Col6, Col7, Col8, Col7*Col8, Col9, Col12 where Col10 = 'Affiliate Name' LABEL Col7*Col8 'Commission per month'", 1)

Because I’m retrieving data from another document, I can’t use the names of the columns, but must address the columns with a number – “Col1” is the first column, “Col2” the second, and so on.

Our affiliates then invoice us each month for their commissions based on this dashboard.


So far this simple solution has worked very well for us. Affilates are the most important source of acquisition for Friendly – not in terms of number of customers, but in terms of revenue.

Should we ever need to scale our affiliate model more, we would especially automate step 3 (affiliate dashboards and billing) more – using in-house software or external tools.

Questions? Ask me anything 🙂

Friendly in your inbox? Sign up for our newsletter.