12 Days of Scriptmas - 2022 Winners!
Published on 12/09/2021
The HowTo Crew must have been extra good this year because Santa left few extra presents under the tree so, we've decided to give them to a few of the folks who submitted scripts for Scriptmas! To add a little sparkle we decided to make a cloud page to randomize the winners. :sparkle emoji: Details on that a little later on.
Without further ado, the winners of Scriptmas 2022 are...
Tim Felch
Tim has won a physical copy of [Automating Salesforce Marketing Cloud] (https://www.amazon.com/Automating-Salesforce-Marketing-Cloud-productivity/dp/1803237198), as well as a Trailblazer Hoodie, an Astro plushy, and a Salesforce Certification voucher!
Cenk Irman
Akash Israni
Jake Wiesenthal
Elliott Davidson
All addtional winners will recieve a digital copy of [Automating Salesforce Marketing Cloud] (https://www.amazon.com/Automating-Salesforce-Marketing-Cloud-productivity/dp/1803237198), a Trailblazer Hoodie, and a Salesforce Certification voucher!
Thank you again to all who submitted scripts for Scriptmas '22 and we'll see you next year!
Now that we know who the winners are and what they won, let's take a look at how we selected these winners.
To make things fair, we randomly selected between the 12 chosen script creators who would be taking the grand prize as well as the other prizes. This was done via a CloudPage on SFMC using SSJS. We thought this would be fitting with the theme of helpful scripts and advocacy of Marketing Cloud.
Now, how do we make SSJS do a random selection? Lets dive in and take a look!
When broken down, the randomizer is a do/while() statement combined with a simple function. See below script for example:
do {
//entriesRS is an array of objects (taken from a DE holding all the entries)
var winnerIndex = getRandomWinner(entriesRS.length);
//winnerRS is an object
var winnerRS = entriesRS[winnerIndex];
var winnerID = winnerRS.ID;
var winnerName = winnerRS.Name;
var upsert = Platform.Function.UpsertData("Winners_2022",["ID"],[winnerID],["Name","Prize"],[winnerName,prize]);
//Prize is set above do/while loop for grand prize
//remove winner from eligible array
entriesRS.sort(function(x,y){ return x == winnerRS ? -1 : y == winnerRS ? 1 : 0; });
entriesRS.shift();
var prize = "Winner"
cnt++;
} while (cnt < 5)
function getRandomWinner(max) {
return Math.floor(Math.random() * max);
}
The main crux of the randomization is the combination of Math.random() and multiplying it by the max number. random() will generate a completley number between 0 and 1, this then multiplied times the maximum number you want displayed will give you a random number between 0 and the maximum number. Now, this number will not be a whole number, so to make sure we only return a whole number, we add on Math.floor() to reduce the number down to the whole number displayed, removing all decimals. From there we then get a random number between 0 and the maximum number, which we can then use as an index for our array of objects, to select the winning row.
To better explain that, here are the breakdown steps to how it was selected:
Of course we could have just made this a script activity and run it and called it a day, but that seemed a bit...anti-climactic, so we decided to instead create a form on a CloudPage, that upon submit ran this script then displayed the winners on the page. Below are the requirements of this CloudPage and the script contained within:
Now that we know what assets are needed, let's dive into what these assets are and what they need to contain.
This one is fairly simple, it will hold all the current entries along with the necessary information. For example in this case, we had the following columns:
Now to be fair, ID was not necessary, but I tend to like making my primary keys numbers or otherwise simple and unique values. The next data extension has a bit more to it though...
Although this has a bit more to it then the previous, it really is just one field....Prize.
This field is a text field, with max character length of 50 and is nullable. This will show whether the person won the Grand Prize or not.
The CloudPage is the most intricate part. But honestly, outside the script and a couple elegant functions and conditionals, it really is still fairly simple.
It is a few Rows.Retrieve() to get the entries and validate if the winners have already been chosen or not. From there it is a group of conditionals checking:
We then have a form that just has a simple submit button that will POST to itself passing along the simple input of 'submit = 1' to let the page know that the form button was pushed and to run the randomizer script. Outside that, it is a simple display of AMPscript variables showing the winners pulled from the winner data extension.
That is really it! It has some complicated parts and some twisty/turney type coding to it, but in general it is not too complex.
<script runat="server">
Platform.Load("Core","1.1.1");
try {
var debug = 0;
var debugForm = 0;
var submit = Request.GetFormField("submit");
var winDE = DataExtension.Init("Winners_2022");
var winRS = winDE.Rows.Retrieve();
if ((winRS.length < 1) && (submit)) {
var entriesDE = DataExtension.Init("Selected_Entries");
var entriesRS = entriesDE.Rows.Retrieve();
var prize = "Grand Prize"
var cnt = 0;
do {
var winnerIndex = getRandomWinner(entriesRS.length);
var winnerRS = entriesRS[winnerIndex];
var winnerID = winnerRS.ID;
var winnerName = winnerRS.Name;
if (prize == 'Grand Prize') {
TreatAsContent('%' + '%[ SET @GrandPrize = "' + winnerName + '" ]%' + '%')
} else {
TreatAsContent('%' + '%[ SET @Prize' + cnt + ' = "' + winnerName + '" ]%' + '%')
}
var upsert = Platform.Function.UpsertData("Winners_2022",["ID"],[winnerID],["Name","Prize"],[winnerName,prize]);
//remove winner from eligible array
entriesRS.sort(function(x,y){ return x == winnerRS ? -1 : y == winnerRS ? 1 : 0; });
entriesRS.shift();
var prize = "Winner"
cnt++;
} while (cnt < 5)
} else if (submit) {
winRS.sort(function(x,y){ return x.Prize == "Grand Prize" ? -1 : y.Prize == "Grand Prize" ? 1 : 0; });
Variable.SetValue("@GrandPrize",winRS[0].Name);
Variable.SetValue("@Prize1",winRS[1].Name);
Variable.SetValue("@Prize2",winRS[2].Name);
Variable.SetValue("Prize3",winRS[3].Name);
Variable.SetValue("Prize4",winRS[4].Name);
debugWrite('winRS',Stringify(winRS))
} else if (winRS.length < 1) {
Variable.SetValue("@form", "1")
} else {
Variable.SetValue("@GrandPrize",winRS[0].Name);
Variable.SetValue("@Prize1",winRS[1].Name);
Variable.SetValue("@Prize2",winRS[2].Name);
Variable.SetValue("Prize3",winRS[3].Name);
Variable.SetValue("Prize4",winRS[4].Name);
if (submit != 1) { (debugForm) ? Variable.SetValue("@form", "1") : ''; }
}
function debugWrite(name,val,overwrite) {
if (debug && !overwrite) {
Write('<b>' + name + ': </b>' + val + '<hr>')
}
}
function getRandomWinner(max) {
return Math.floor(Math.random() * max);
}
</script>
<!DOCTYPE>
<html>
<head>
<style>
body {
background-color: aqua;
margin: 0;
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Sego UI, Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,ui-monospace, SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monopsace;
}
.container {
max-width:1000px;
margin: 0 auto;
background-color: #fff;
}
.logo {
width:100%;
padding: 30px;
background-color: #000000;
text-align: center;
}
.h2Logo {
max-width: 200px;
}
.display {
background-color: #fff;
width: 100%;
padding: 30px;
}
h1 {
text-transform:capitalize;
}
.subheading {
font-size: 1.4em;
margin: -22px 0 20px;
font-style: italic;
color: #444
}
.copy {
margin: 0 0 30px;
}
.divTable{
display: table;
width: auto;
min-width: 600px;
}
.divTableRow {
display: table-row;
}
.divTableHeading {
background-color: #EEE;
display: table-header-group;
}
.divTableCell, .divTableHead {
border: 1px solid #999999;
display: table-cell;
padding: 7px 14px;
}
.divTableHeading {
background-color: #EEE;
display: table-header-group;
font-weight: bold;
}
.divTableFoot {
background-color: #EEE;
display: table-footer-group;
font-weight: bold;
}
.divTableBody {
display: table-row-group;
}
.GrandPrize {
background-color: rgb(247, 90, 90);
}
.Prize {
background-color: rgb(105, 190, 105);
}
form {
margin: 0 auto;
text-align: center;
}
input[type=submit] {
font-family: inherit;
font-size: 1.2em;
color: #fff;
width: 250px;
padding:20px 50px;
background:rgb(17, 187, 94);
border:0 none;
cursor:pointer;
-webkit-border-radius: 10px;
border-radius: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="logo"><img class="h2Logo" src="https://res.cloudinary.com/howtosfmc/image/upload/v1614651577/HowtoSFMCPlaceholder_White_vlsjf0.png" /></div>
<div class="display">
%%[if @form == 1 then]%%
<div class="heading"><h1>Scriptmas 2022</h1></div>
<div class="subheading">It is time for us to randomly select the winners for Scriptmas 2022!</div>
<div class="copy">Using randomization scripting in SSJS on a SFMC CloudPage, we will select 1 Grand Prize winner and 4 other prize winners for this year's Scriptmas event. By Clicking the button below, we will have each of these selected and then displayed</div>
<form method="POST">
<input type="hidden" name="submit" value="1" />
<input type="submit" value="Select the winners!">
</form>
%%[else]%%
<div class="heading"><h1>Scriptmas 2022</h1></div>
<div class="subheading">The winners have been selected for our grand and other prizes!</div>
<div class="copy">A big thank you to all that have entered, and a hearty congratulations to those selected. Without further ado, displayed below are the randomly selected prize winners for the 2022 Scriptmas event by HowToSFMC!</div>
<div class="divTable">
<div class="divTableBody">
<div class="divTableRow GrandPrize">
<div class="divTableCell"><b>Grand Prize</b></div>
<div class="divTableCell"><b>%%=v(@GrandPrize)=%%</b></div>
</div>
<div class="divTableRow Prize">
<div class="divTableCell">Prize 1</div>
<div class="divTableCell">%%=v(@Prize1)=%%</div>
</div>
<div class="divTableRow Prize">
<div class="divTableCell">Prize 2</div>
<div class="divTableCell">%%=v(@Prize2)=%%</div>
</div>
<div class="divTableRow Prize">
<div class="divTableCell">Prize 3</div>
<div class="divTableCell">%%=v(@Prize3)=%%</div>
</div>
<div class="divTableRow Prize">
<div class="divTableCell">Prize 4</div>
<div class="divTableCell">%%=v(@Prize4)=%%</div>
</div>
</div>
</div>
%%[endif]%%
</div>
</div>
</body>
</html>
<script runat="server">
} catch(e) {
Write(Stringify(e))
}
</script>
Well, that is pretty much it! I hope you enjoyed it and can use this in some way to help assist in your future needs. So long and thanks for all the fish!