Use GitHub to serve Cloud Pages

31 March 2024 Salesforce 8 mins read

Have you ever created a Cloud Page and wished you could roll back to a previous version? Using Github will allow you to serve changes immediately without republishing the page.

Contents

Overview

Marketing Cloud, sadly, doesn't include any sort of version control - what does that mean for the user in Marketing Cloud? Have you ever made a code change in an email or Cloud Page only to find that it was incorrect only to go back and rewrite the code you had mistakenly overwritten?

There shouldn't be a need to go into what GitHub is as you most likely came across this article wondering how to utilise this tool. A quick summary of what it provides

Version Control
If you've ever made a mistake or something just doesn't work anymore at least you can just roll back to a previously known version.

Instant Publishing
Any changes that are made and pushed to your Git repository will instantly be updated to the latest version as the Cloud Page will reference the single instance. No need to sign in to Marketing Cloud and wait forever for the cache to clear.

Collaboration
With the nature of Git, you and your team members can work on the same content and merge any relevant changes. You can also see who's to blame for certain pieces of code.

Implementation

The "how-to" part of the implementation consists of three steps to build a version control component

  1. Creating an Access Token
  2. Writing the relevant AMPScript to build a Content Block
  3. Define the Content Block in your Emails and Cloud Pages

Before we start it would be good to cover the pros and cons of building this solution as a couple of the items may be a deal-breaker for your organisation.

Pros

  • History of all code changes and who made them are recorded for you to blame or commend the author
  • Git can be integrated into many different applications or CMS systems to manage content
  • Teams can collaborate on single items at the same time without causing conflicts

Cons

  • All content editing capabilities that Marketing Cloud has will be unavailable
  • Your organisation will need to implement an editor to interact with Content Blocks

Creating an Access Token

GitHub holds two repository types; Public and Private - since all content is catered to a specific company the assumption here is that we will need to work to retrieve content from private repositories from GitHub. Interacting with private repositories requires an access token to authenticate requests retrieve content.

To create an access token first navigate to the Settings in your GitHub account, once you're in go ahead and create an Access Token by clicking on Developer Settings and then Personal Access Tokens - found on the sidebar. The idea here is that we create a token that will only allow us to retrieve content from the repository and ensure that this token can't make important code changes.

Click Generate new token which will allow you to name your token and define the scope - all we need is the access to our repositories and then generate our token.

Before we move on Marketing Cloud the access token needs to be set up to match Basic Authentication - this involves concatenating the Git username with the above-generated access token and then finally base64 encoded.

To do this you can access an online Base64 tool and enter the credentials as in the format

GITHUB_USERNAME:ACCESS_TOKEN

Take note of the colon in between the two values - this is intended.

Generate and keep the base64 encoded value.

Build the Content Block

What we're going to do is build a Content Block in Content Builder that can be referenced in Emails and Cloud Pages - using the block will provide a reusable code snippet that will allow easy maintainability.

The first step is to create the Content Block itself - login to Marketing Cloud and create an HTML Only Content Block in the location you want, for this guide the content will be saved in Content Builder > Git with the name GitHub. Simply copy and paste the code below and we'll run through the required changes to cater for your environment.

<script runat="server" type="text/javascript">
/*
 * Author: Sandeep Bansal <https://sa.ndeep.me>
 * Description: Allow rendering GitHub stored code
 * License: Provided as-is with no support, the code cannot be sold for commercial purposes.
 */

Platform.Load("Core", "1.1.5");

var GITHUB_ORG = "ORG_HERE"; // Enter your org here, the part after github.com
var GITHUB_TOKEN = "TOKEN_HERE"; // Enter the base64 encoded Basic auth token

/* DO NOT TOUCH ANYTHING BELOW THIS LINE */

try {

    // Retrieve the AMPScript Variables that have been included in the Email or Cloud Page
    var GITHUB_REPO = Variable.GetValue("@GITHUB_REPO");
    var GITHUB_BRANCH = Variable.GetValue("@GITHUB_BRANCH");
    var GITHUB_PATH = Variable.GetValue("@GITHUB_PATH");

    // Check to see if the variables have been defined or show an error and cancel the send.
    if (!GITHUB_REPO || !GITHUB_BRANCH || !GITHUB_PATH) {
        Platform.Function.RaiseError("GitHub Parameters not defined");
        return;
    }

    // Generate the URL to retrieve
    var url = 'https://raw.githubusercontent.com/' + GITHUB_ORG + '/' + GITHUB_REPO + '/' + GITHUB_BRANCH + '/' + GITHUB_PATH;

    // Perform the HTTP request to get the content
    var req = new Script.Util.HttpRequest(url);
    req.method = "GET";
    req.setHeader("Authorization", "Basic " + GITHUB_TOKEN);
    req.emptyContentHandling = 0;
    req.retries = 1;
    req.continueOnError = true;

    var resp = req.send();

    // Check if the request was successful
    if (resp.statusCode != 200) {
        Platform.Function.RaiseError("There was an error retrieving the content");
        return;
    }

    // Print out the content from GitHub
    Platform.Response.Write(resp.content);

} catch (e) {
    Platform.Response.Write(Stringify(e));
}
</script>

We're going to be using Server Side Javascript in our code - the main reason for this is that the HTTP Requests in AMPScript cannot include Authorization headers or any other header for the matter - we have to use the power of Server SIde Javascript to achieve this.

The script itself requires only two parameters, the rest are defined when adding the code in your email -

GITHUB_ORG requires your org name, this is the part that comes directly after github.com in the address bar

GITHUB_TOKEN should be populated with the base64 encoded token we generated in the previous step.

The code simply makes an API call to the raw.githubusercontent.com domain and authenticates it with the access token.

Defining our Email/Cloud Page

Here's the fun part - adding some code to our Email or Cloud page in Marketing Cloud to generate the content, simply create a new Email or Cloud page and enter the following AMPScript, yes, we're moving to AMPScript for this part.

%%[
	SET @GITHUB_REPO = "REPO_HERE" // Enter the Repo in GitHub
	SET @GITHUB_BRANCH = "BRANCH_HERE" // The branch we should access in the repo
	SET @GITHUB_PATH = "PATH_HERE" // The path of the file
]%%
%%=TreatAsContent(ContentBlockByName("Content Builder\PATH_TO_OUR_CONTENTBLOCK"))=%%

The code requires you to enter three variables to retrieve the correct content for this specific component -

GITHUB_REPO

GITHUB_BRANCH

GITHUB_PATH

To help understand where to get the values you can refer to the address bar in GitHub to help aid you - https://github.com/GITHUB_ORG/GITHUB_REPO/blob/GITHUB_BRANCH/GITHUB_PATH

There are two AMPScript functions used here, ContentBlockByName to retrieve the Content Block we had created earlier, and the TreatAsContent function which allows us to render any HTML and Dynamic AMPScript in our email.

Finally, we can save the Email/Cloud Page and Preview it against an audience, you'll notice that the content gets rendered and any changes you make on GitHub will be reflected in Marketing Cloud.

Remarks

The following are assumptions/remarks based on the provided script

  • GitHub is not a content engine and should be used to compliment an existing Content Management Solution.
  • The use of Script.Util.HTTPGet will cache requests to GitHub which will help improve performance on email sends.
  • The TreatAsContent AMPScript function will allow any AMPScript or personalisation to be rendered as if it was coming from Marketing Cloud itself.
  • This code has not been tested on large data sets, it's safe to assume that there shouldn't be any issue using this code but it's always best to run your own tests.
  • Authentication is a tricky point in Marketing Cloud, where do you store keys - is it safe to store keys in Content Blocks? There are better ways to do this but for the purpose of the article this was an easier method.
  • You're free to use the code included on this page in your own projects but you must include a link back to this page and reference the author if you are including it on your website or social media

References

Share On:
Sandeep Bansal
Marketing Cloud Technical Architect
Follow me on LinkedIn