You are currently viewing Fetch code từ GitHub về MC Cloudpage

Fetch code từ GitHub về MC Cloudpage

Hello mọi người, lại là mình Gâu Đần đây!

Như trong một bài viết từ lâu, mình đã chỉ các bạn dùng Dropbox để sync code từ máy lên cloud này và kéo code về khởi chạy trên Cloudpage. Và mình cũng khẳng định luôn, đây là cách nhanh, tiện lợi, free và an toàn.

Nhưng nếu bạn không được dùng Dropbox bởi vì quy định trong cty/ giữa khách hàng và công ty thì việc development của bạn như bị kéo về thời kì đồ đá vậy 🥲

Trường hợp bạn vẫn có thể sử dụng GitHub thì bạn có thể nghía vào bài viết của Gâu Đần để biết mình đã giải quyết ra sao nhé.

Essential Needs and Operating Principles

Phương pháp này đến từ một nhu cầu hết sức thiết yếu: Làm sao tôi có thể chạy code của mình trên Marketing Cloud nhanh, dễ, ít tốn thời gian và có thể dễ dàng chạy lại sau khi thay đổi code?

Vấn đề lớn nhất của SFMC: Có môi trường để chạy code nhưng không hề là nơi lý tưởng để dev/test

Lý do:

  • Copy paste trong Cloudpage phải republish lại page → quá mất thời gian
  • Chạy bằng preview mode trong Email content builder thì load lâu và có nhiều phụ thuộc (E.g. Data Extension, Email template,…)
  • Cả Cloudpage và Email nếu edit code rồi save là coi như khỏi revert được phiên bản cũ, không highlight được code, không có autocomplete function,…
  • VScode thì dev được nhưng không test được.

Ý tưởng và nguyên lý hoạt động của kĩ thuật này:

  • Dùng host trung gian thứ 3 để có thể đẩy code lên host này.
  • Host này phải có thể xem được raw file.
  • Cloudpage sử dụng HTTP get raw file về, tạo môi trường khởi chạy.
  • Truy cập vào Cloudpage để chạy code.

Nếu bạn thắc mắc tại sao không đẩy code thẳng lên Cloudpage thì câu trả lời đơn giản là hiện không có cách nào cả. Cả REST và SOAP API đều không chức năng tác động được vào được Cloudpage. Tức code ở Cloudpage là fix cứng, chỉ có thể đổi nếu thay thủ công và republish lại. Vì thế thông qua một host trung gian thứ 3 ta có thể linh động thay đổi code từ phía local.

Dropbox được Gâu Đần recommend vì nó tự động sync lên host một khi save từ phía local nên giảm đi rất nhiều công đoạn.

Fetch code from Public GitHub repo to SFMC cloudpage

Raw file từ Public GitHub repo có dạng như thế này:

https://raw.githubusercontent.com/{userName}/{repoName}/{branch}/{fileName}

Tuy nhiên không thể cứ get raw file URL này, vì nó có cache nên chỉ cập nhật file mới nhất sau 15 phút.

Thay vào đó raw file mới nhất sẽ có dạng:

https://raw.githubusercontent.com/{userName}/{repoName}/{SHA}}/{fileName}

Tức là ở đây ta cần tìm SHA commit ID cho lần commit (gần nhất) đó.

Thật may là GitHub cung cấp cho ta API format sau để ta có thể lấy SHA mới nhất

Host: https://api.github.com
GET /repos/{userName}/{repoName}/branches/{branchName}
Content-Type: application/json
User-Agent: {userName}

Vậy có 03 việc ta cần làm:

  • Tìm SHA commit ID
  • Tạo raw URL
  • HTTP Get raw URL và Treat As Content để có thể chạy code

Find SHA commit ID

<script runat="server">
Platform.Load("core","1");
// Fetch code from public repo github

var userName = "YOUR GITHUB USERNAME";
var repoName = "YOUR REPO NAME";
var branchName  = "YOUR BRANCH NAME";
var repo_API_url = "https://api.github.com/repos/" + userName +"/"+ repoName +"/branches/" + branchName;
var fileName = "YOUR FILE NAME"

function getSHA(userName, repo_API_url){
    // Get SHA from the latest commit
    var req = new Script.Util.HttpRequest(repo_API_url);
    req.emptyContentHandling = 0;
    req.retries = 2;
    req.continueOnError = true;
    req.contentType = "application/json"; 
    req.method = "GET";
    req.setHeader("User-Agent", userName);
    var resp = req.send();

    var resultJSON = Platform.Function.ParseJSON(String(resp.content));
    var sha = String(resultJSON.commit.sha);
    //Write(sha);
    return sha;
}

</script>

Get RAW URL

function getRawURL(userName, repoName, fileName, repo_API_url){
    // Get raw url
    var sha = getSHA(userName, repo_API_url);
    var rawURL = "https://raw.githubusercontent.com/" + userName +"/"+ repoName + "/"+ sha + "/"+ fileName;
    return rawURL;
}

Full code:

<script runat="server">
Platform.Load("core","1");
// Fetch code from public repo github

var userName = "YOUR GITHUB USERNAME";
var repoName = "YOUR REPO NAME";
var branchName  = "YOUR BRANCH NAME";
var repo_API_url = "https://api.github.com/repos/" + userName +"/"+ repoName +"/branches/" + branchName;
var fileName = "YOUR FILE NAME"

var rawURL = getRawURL(userName, repoName, fileName, repo_API_url);
//Write(rawURL);

//Set URL value
Variable.SetValue("@url", rawURL);

function getRawURL(userName, repoName, fileName, repo_API_url){
    // Get raw url
    var sha = getSHA(userName, repo_API_url);
    var rawURL = "https://raw.githubusercontent.com/" + userName +"/"+ repoName + "/"+ sha + "/"+ fileName;
    return rawURL;
}

function getSHA(userName, repo_API_url){
    // Get SHA from the latest commit
    var req = new Script.Util.HttpRequest(repo_API_url);
    req.emptyContentHandling = 0;
    req.retries = 2;
    req.continueOnError = true;
    req.contentType = "application/json"; 
    req.method = "GET";
    req.setHeader("User-Agent", userName);
    var resp = req.send();

    var resultJSON = Platform.Function.ParseJSON(String(resp.content));
    var sha = String(resultJSON.commit.sha);
    //Write(sha);
    return sha;
}

</script>

%%=TreatAsContent(HTTPGet(@url))=%%

Fetch code from Private GitHub repo to SFMC cloudpage

Để an toàn hơn nữa ta có thể dùng Private GitHub. Cách này có thể tránh được bot crawl từ các public repo.

Với Private GitHub repo thì cũng tương tự với Public GitHub repo, chỉ khác là ở đây có thêm bước authenticate token.

Đầu tiên bạn tạo GitHub Fine-grained token như hướng dẫn sau.

Nhớ là để an toàn thì token được tạo chỉ được truy cập repo chứa SFMC code và cấp quyền: Read access to code, commit statuses, and metadata thôi nhé.

Full code:

<script runat="server">
Platform.Load("core","1");
// Fetch code from private repo github
var github_pat = "YOUR GITHUB TOKEN" //temporary key
var auth =  "Bearer " + github_pat;

var userName = "YOUR GITHUB USERNAME";
var repoName = "YOUR REPO NAME";
var branchName  = "YOUR BRANCH NAME";
var repo_API_url = "https://api.github.com/repos/" + userName +"/"+ repoName +"/branches/" + branchName;
var fileName = "YOUR FILE NAME"

var rawURL = getRawURL(userName, repoName, fileName, repo_API_url);
//Write(rawURL);

//Set URL value
Variable.SetValue("@auth", auth);
Variable.SetValue("@rawURL", rawURL);

function getRawURL(userName, repoName, fileName, repo_API_url){
    // Get raw url
    var sha = getSHA(userName, repo_API_url);
    var rawURL = "https://raw.githubusercontent.com/" + userName +"/"+ repoName + "/"+ sha + "/"+ fileName;
    return rawURL;
}

function getSHA(userName, repo_API_url){
    // Get SHA from the latest commit
    var req = new Script.Util.HttpRequest(repo_API_url);
    req.emptyContentHandling = 0;
    req.retries = 2;
    req.continueOnError = true;
    req.contentType = "application/json"; 
    req.method = "GET";
    req.setHeader("User-Agent", userName);
    req.setHeader("Authorization", auth);
    var resp = req.send();

    var resultJSON = Platform.Function.ParseJSON(String(resp.content));
    var sha = String(resultJSON.commit.sha);
    //Write(sha);
    return sha;
}

</script>

%%=TreatAsContent(HTTPGet(@rawURL, false, 0, @response, "Authorization", @auth))=%%

Conclusion

Vậy là các bạn biết cách để kéo code từ GitHub về SFMC Cloudpage rồi đó. Các bạn thoải mái chia sẽ workaround này nhé. Integrate GitHub vào Marketing Cloud chắc chắn sẽ thuận lợi hơn cho việc development. Hy vọng mọi người đã có một trải nghiệm thú vị và hữu ích, follow mình để học được thêm nhiều mẹo và kiến thức về Salesforce Marketing Cloud nhé.

Leave a Reply