Skip to main content

External Game

How to integrate an external game

Preamble

At the end of 2020, Qualifio opened a new step in its campaigns in order to host external JavaScript and HTML5 games. The objective is to allow our customers to host a wide variety of interactive games, developed by themselves or their agencies while keeping the data capture flow within Qualifio (for integration and security reasons).

In a nutshell:

  • The "Game" step may follow or precede the form (if any).
  • All other steps, including the look and feel of the campaign, are managed using the standard steps and configured via Qualifio.

This new step in our campaigns has been designed to limit the technical dependencies between the game and the Qualifio Player, which supports all steps.

On desktop, the game will be visible in the general layout of the campaign (as a minisite or as an iframe).

On mobile, it will occupy the entire screen (providing the smart URL is used to share the campaign).

external-game-fig-1

However, for security reasons, we have implemented a token mechanism to limit cheating. It is based on the use of two tokens:

  • A token signed with our private key issued by the "Player" to the game:
    • contains some data including the game ID,
    • and will be read by the game with our public key.
  • A token sent by the game containing the first token completed with the performance of the participant (score, game time):
    • signed with the private key of the game developer and read by our Player with their public key,
    • and sent by the game to the "Player" by postMessage().

external-game-fig-2

external-game-fig-3

In this document,

  • the token issued by the Player to the game is referred to as "JWT1".
  • the token issued by the game to the Player is referred to as "JWT2".

Game integration

Game initialisation

The game is initialised to the construction of the iframe with the help of a token (JWT1) which contains useful information for sending the results.

JSON structure (JWT1)

The Player generates a JSON with some information about expiration, where to POST results, etc.

  • This JSON will be signed with our private key.
  • The JWT will be sent when we construct the iframe used to display the game (cf. token argument).
{
"iat":1601889938869, // Unix time - 20 minutes
"exp":1601894738869, // Unix time + 60 minutes
"iss":"com.qualifio.game.integration", // fixed value
"refresh": {
"before":1601894738749, // exp - 2 minutes
"url":"http://localhost:8081/20/v1.cfm?page=1&uk=QCKUD4ZI6YU&cfid=33d86f4c-7146-4035-837a-81f613169688&cftoken=0" // Url to be used for the expiration renewal (don't use it, this component is not available yet)
},
"config_location":"assets/noel.json", // url indicating the location of a configuration file if your game offers several variants. Useless for tailor-made developments that do not change.
"config_override":{
"lang":"en", // campaign language
"landscape":0, // 0 if the game can be displayed in portrait mode only, 1 if it supports both modes (landscape and portrait).
"postURL":"http://localhost:8081/20/v1.cfm?page=1&uk=QCKUD4ZI6YU&cfid=33d86f4c-7146-4035-837a-81f613169688&cftoken=0", // url where to post result
"resetURL":"https://localhost/20/v1.cfm?id=6E573BF2-2274-4860-BE86-ECDB91F4F58B&cache=true&pdomain=" // surl to use to restart the campaign (same as before today)
}
}

Signature

Qualifio sign the JSON using the RS512 algorithm and following the PKCS8 standard.

Here is the public key to use to read the JWT1:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvZSuTqskEn+p7bauY561
NvOVlPq623fB21J67FrUirWlYbBf/OhNWdS1ckV0AP8fgGvkavtya1kIef+6V1d2
hFS1E+T6vy19deEOBrL4h6qW1fP003F74ISnjfqzNd4cpX3ES8zI7nv0b0sw9EPF
fNICqBhgwBQ/ziz6eguYI5CHf/JJfInobWg9OvTQm7147TurAC8JOQDrZij7gEJJ
jj8e4j2HFKS700X+8Kaeubo1pjRUoyomjASg6HcjXgexKYRX3+diD4dj5ms+8aOd
st2J9vE/haRwe33Ax+BxRgqx+n2gwVeFRe666T8nsSnnuEp8TrRUeXbIfiMku1nD
xi+h1jr99kxsZ4R1+qABUMX0O9idDGAXn/vTBKDBIHHrXeRhnFg10CcagdjnImCx
QI0C/8J/fGoCJbXLg3y0wF74iBuNEW/4jmU9yUnQwG6W3iTMS+RwGr44w2RCeD5p
dgjc+XEy4kHJRRJCnsKwnon7bz0JSCbuEEi3AuFj3G0rnEFSRHmPhbhxoYUYT6cA
40FKMVtkAGtBKMr6h5HpTLmdtzsuf1V/sqcCP+7/xzJ0TSbNG/Oa04G331kZPZAS
i97ITuVjC3/ccLwU5uWpWELxehKxDSYPKR7gwSe0LsGJZaiETq4nLQ4dIHLC7BAk
5FNxm9C7KjIs97LUg5M2ztECAwEAAQ==
-----END PUBLIC KEY-----

Communication

The token will be sent to the game as an URL argument.

<iframe allowtransparency="true" id="minigame" class="minigames" src="https://your-game-location?token=#token#"></iframe>

Concrete example (using an other set of keys):

<iframe allowtransparency="true" id="minigame" class="minigames" src="https://your-game-location/?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJpYXQiOjE2MDE4ODk5Mzg4NjksInJlZnJlc2giOnsiYmVmb3JlIjoxNjAxODk0NzM4NzQ5LCJ1cmwiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvMjAvdjEuY2ZtP3BhZ2U9MSZ1az1RQ0tVRDRaSTZZVSZjZmlkPTMzZDg2ZjRjLTcxNDYtNDAzNS04MzdhLTgxZjYxMzE2OTY4OCZjZnRva2VuPTAifSwiaXNzIjoiY29tLnF1YWxpZmlvLmdhbWUuaW50ZWdyYXRpb24iLCJleHAiOjE2MDE4OTQ3Mzg4NjksImNvbmZpZ19sb2NhdGlvbiI6ImFzc2V0cy9ub2VsLmpzb24iLCJjb25maWdfb3ZlcnJpZGUiOnsibGFuZHNjYXBlIjowLCJwb3N0VVJMIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgxLzIwL3YxLmNmbT9wYWdlPTEmdWs9UUNLVUQ0Wkk2WVUmY2ZpZD0zM2Q4NmY0Yy03MTQ2LTQwMzUtODM3YS04MWY2MTMxNjk2ODgmY2Z0b2tlbj0wIiwibGFuZyI6ImVuIiwicmVzZXRVUkwiOiJodHRwczovL2xvY2FsaG9zdC8yMC92MS5jZm0_aWQ9NkU1NzNCRjItMjI3NC00ODYwLUJFODYtRUNEQjkxRjRGNThCJmNhY2hlPXRydWUmcGRvbWFpbj0ifX0.W8aIN-yjDIDjiTDdpflw33X0hDB9k7jNO7C1BAd7f7jTYilt_s_QnyAuPresEPprZZV8Q6EY9wzpRNK9eJBC9Cv2BFG38UrVdibUWXydBBlU0gfUBcrRiBBDktdgyFDSxJJqQaO1HpNKno04GqqyXduGNtPaBVu-RnRqqA4ofN0NZ6JsDlL3GNzakd7yW1eBjKikyieQuosuL7H2arC5kN6rQhLm3Xc5ifPSMMk05YRf9yWl4KCpRTvnDL_9mPEh7pEa6GlC6FQ_zUHYRAAYiCfgeNJnxVr-sCHBBRnsuLYkC3ENIv19zmoUO0CSniiep7UcPv1lpzNCxVA_OEcl4g7ZibrzixQhiY_yeHQYlvj0ajvu11gZ9nvqiyaoc3rtahxZqvOawWKVSvyOWMur1-z4mPuamdqEVCT4UqW_RPMT-4SqlSd0DuubklxpigyZqyOElciuMa4SSpL7olrkUXm_UR4dnn9gUWOrhBcfbmPHos351A88Ks9SeDyH2VDAo4bQ4t_3DBSNDupQms0xlKR-mTIFqk1BeSXwsMDxB5R8fzuCmOPWQPYePahRflkofD0NcHqsSJVKwhv-9pvYgo-ol0wkVqGuDJ3LuToVWTjjdkxmCqlKYqw-h000D9heTH5W4hSD_4EmHJTefv8rhy8mSOXzjCAZkxE_PbUBdc0&loaderBG=de5e5d&progressBarColor=9fe2da"></iframe>

Note: Those arguments are used by Qualifio to define the colours of its pre-loader, you can skip this: &loaderBG=**de5e5d**&progressBarColor=**9fe2da**

Game side verification

The JWT will be read by the game and decoded with our public key. The game will only load if the signature is valid.

Sending results to the Player

The result is saved by the "Player". To do this, we must receive the score and the time spent on the game in a new JSON (referred to as "JWT2").

JSON structure (JWT2)

Here is an example of the JSON we are expecting to receive. It contains the original JWT (JWT1), the score, etc.

{
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJpYXQiOjE2MDE4ODk5Mzg4NjksInJlZnJlc2giOnsiYmVmb3JlIjoxNjAxODk0NzM4NzQ5LCJ1cmwiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvMjAvdjEuY2ZtP3BhZ2U9MSZ1az1RQ0tVRDRaSTZZVSZjZmlkPTMzZDg2ZjRjLTcxNDYtNDAzNS04MzdhLTgxZjYxMzE2OTY4OCZjZnRva2VuPTAifSwiaXNzIjoiY29tLnF1YWxpZmlvLmdhbWUuaW50ZWdyYXRpb24iLCJleHAiOjE2MDE4OTQ3Mzg4NjksImNvbmZpZ19sb2NhdGlvbiI6ImFzc2V0cy9ub2VsLmpzb24iLCJjb25maWdfb3ZlcnJpZGUiOnsibGFuZHNjYXBlIjowLCJwb3N0VVJMIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgxLzIwL3YxLmNmbT9wYWdlPTEmdWs9UUNLVUQ0Wkk2WVUmY2ZpZD0zM2Q4NmY0Yy03MTQ2LTQwMzUtODM3YS04MWY2MTMxNjk2ODgmY2Z0b2tlbj0wIiwibGFuZyI6ImVuIiwicmVzZXRVUkwiOiJodHRwczovL2xvY2FsaG9zdC8yMC92MS5jZm0_aWQ9NkU1NzNCRjItMjI3NC00ODYwLUJFODYtRUNEQjkxRjRGNThCJmNhY2hlPXRydWUmcGRvbWFpbj0ifX0.W8aIN-yjDIDjiTDdpflw33X0hDB9k7jNO7C1BAd7f7jTYilt_s_QnyAuPresEPprZZV8Q6EY9wzpRNK9eJBC9Cv2BFG38UrVdibUWXydBBlU0gfUBcrRiBBDktdgyFDSxJJqQaO1HpNKno04GqqyXduGNtPaBVu-RnRqqA4ofN0NZ6JsDlL3GNzakd7yW1eBjKikyieQuosuL7H2arC5kN6rQhLm3Xc5ifPSMMk05YRf9yWl4KCpRTvnDL_9mPEh7pEa6GlC6FQ_zUHYRAAYiCfgeNJnxVr-sCHBBRnsuLYkC3ENIv19zmoUO0CSniiep7UcPv1lpzNCxVA_OEcl4g7ZibrzixQhiY_yeHQYlvj0ajvu11gZ9nvqiyaoc3rtahxZqvOawWKVSvyOWMur1-z4mPuamdqEVCT4UqW_RPMT-4SqlSd0DuubklxpigyZqyOElciuMa4SSpL7olrkUXm_UR4dnn9gUWOrhBcfbmPHos351A88Ks9SeDyH2VDAo4bQ4t_3DBSNDupQms0xlKR-mTIFqk1BeSXwsMDxB5R8fzuCmOPWQPYePahRflkofD0NcHqsSJVKwhv-9pvYgo-ol0wkVqGuDJ3LuToVWTjjdkxmCqlKYqw-h000D9heTH5W4hSD_4EmHJTefv8rhy8mSOXzjCAZkxE_PbUBdc0",
"result": [
[
"score",
17 // points
],
[
"time",
36000 // milliseconds (36 seconds here)
]
],
"iat": 1601891574, // Unix time - 20 minutes
"exp": 1601891694, // Unix time + 60 minutes
"iss": "com.yourCompanyName.games.gameName" // for example
}

Currently, only the "score" and "time" keys are supported by Qualifio's "Player" and campaign statistics.

Signature

  • You will sign the JSON using the RS512 algorithm.
  • Keys MUST follow the PKCS8 standard.
  • You have to communicate the public key to Qualifio.
{"jwt":"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJqd3QiOiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpTVXpVeE1pSjkuZXlKcFlYUWlPakUyTURFNE9EazVNemc0Tmprc0luSmxabkpsYzJnaU9uc2lZbVZtYjNKbElqb3hOakF4T0RrME56TTROelE1TENKMWNtd2lPaUpvZEhSd09pOHZiRzlqWVd4b2IzTjBPamd3T0RFdk1qQXZkakV1WTJadFAzQmhaMlU5TVNaMWF6MVJRMHRWUkRSYVNUWlpWU1pqWm1sa1BUTXpaRGcyWmpSakxUY3hORFl0TkRBek5TMDRNemRoTFRneFpqWXhNekUyT1RZNE9DWmpablJ2YTJWdVBUQWlmU3dpYVhOeklqb2lZMjl0TG5GMVlXeHBabWx2TG1kaGJXVXVhVzUwWldkeVlYUnBiMjRpTENKbGVIQWlPakUyTURFNE9UUTNNemc0Tmprc0ltTnZibVpwWjE5c2IyTmhkR2x2YmlJNkltRnpjMlYwY3k5dWIyVnNMbXB6YjI0aUxDSmpiMjVtYVdkZmIzWmxjbkpwWkdVaU9uc2liR0Z1WkhOallYQmxJam93TENKd2IzTjBWVkpNSWpvaWFIUjBjRG92TDJ4dlkyRnNhRzl6ZERvNE1EZ3hMekl3TDNZeExtTm1iVDl3WVdkbFBURW1kV3M5VVVOTFZVUTBXa2syV1ZVbVkyWnBaRDB6TTJRNE5tWTBZeTAzTVRRMkxUUXdNelV0T0RNM1lTMDRNV1kyTVRNeE5qazJPRGdtWTJaMGIydGxiajB3SWl3aWJHRnVaeUk2SW1WdUlpd2ljbVZ6WlhSVlVrd2lPaUpvZEhSd2N6b3ZMMnh2WTJGc2FHOXpkQzh5TUM5Mk1TNWpabTBfYVdROU5rVTFOek5DUmpJdE1qSTNOQzAwT0RZd0xVSkZPRFl0UlVORVFqa3hSalJHTlRoQ0ptTmhZMmhsUFhSeWRXVW1jR1J2YldGcGJqMGlmWDAuVzhhSU4teWpESURqaVREZHBmbHczM1gwaERCOWs3ak5PN0MxQkFkN2Y3alRZaWx0X3NfUW55QXVQcmVzRVBwclpaVjhRNkVZOXd6cFJOSzllSkJDOUN2MkJGRzM4VXJWZGliVVdYeWRCQmxVMGdmVUJjclJpQkJEa3RkZ3lGRFN4SkpxUWFPMUhwTktubzA0R3FxeVhkdUdOdFBhQlZ1LVJuUnFxQTRvZk4wTlo2SnNEbEwzR056YWtkN3lXMWVCaktpa3lpZVF1b3N1TDdIMmFyQzVrTjZyUWhMbTNYYzVpZlBTTU1rMDVZUmY5eVdsNEtDcFJUdm5ETF85bVBFaDdwRWE2R2xDNkZRX3pVSFlSQUFZaUNmZ2VOSm54VnItc0NIQkJSbnN1TFlrQzNFTkl2MTl6bW9VTzBDU25paWVwN1VjUHYxbHB6TkN4VkFfT0VjbDRnN1ppYnJ6aXhRaGlZX3llSFFZbHZqMGFqdnUxMWdaOW52cWl5YW9jM3J0YWh4WnF2T2F3V0tWU3Z5T1dNdXIxLXo0bVB1YW1kcUVWQ1Q0VXFXX1JQTVQtNFNxbFNkMER1dWJrbHhwaWd5WnF5T0VsY2l1TWE0U1NwTDdvbHJrVVhtX1VSNGRubjlnVVdPcmhCY2ZibVBIb3MzNTFBODhLczlTZUR5SDJWREFvNGJRNHRfM0RCU05EdXBRbXMweGxLUi1tVElGcWsxQmVTWHdzTUR4QjVSOGZ6dUNtT1BXUVBZZVBhaFJmbGtvZkQwTmNIcXNTSlZLd2h2LTlwdllnby1vbDB3a1ZxR3VESjNMdVRvVldUampka3htQ3FsS1lxdy1oMDAwRDloZVRINVc0aFNEXzRFbUhKVGVmdjhyaHk4bVNPWHpqQ0Faa3hFX1BiVUJkYzAiLCJyZXN1bHQiOltbInNjb3JlIiwxN10sWyJ0aW1lIixudWxsXV0sImlhdCI6MTYwMTg5MTU3NCwiZXhwIjoxNjAxODkxNjk0LCJpc3MiOiJodHRwczovL3N0YWdpbmcuZ2FtZXMucXVhbGlmaW9hcHAuY29tIn0.m6UrTAQUQ5MYySS6GqpUYfRDNjCOrU_FF1ijXB7xfIkFoWtlhbTZBzMmWTDpJuF-uyKEaWlw4GaYddSEI9AVTCbDda1L062_sBu-UG8iKVqTAnHq7mTtWSdNAhL0yO5KU-cQjEpAZzlbOpXaXzPGg89MJToOuDFDhqH26r6Dc5tnx9PbwLHwg2E5ebGjOwbTiJ7RoQYZaZXNnPr9Tihs8lyUaxII2pVnRCHxIPebO-KmyuDnkMa83FFyTEUUbo_AITsiquuWB9vi_Ou09oqXXQyc-7H-k3m5SZEe31hTZ5QN-cqaZCTr4we8JCmf_gcLlOejqjr3YDav2nRl8ugbe-PAnPB3fFrWujq82QJG1J4rFIzqdW5KreQNt3z8RuJ6aTPiM99VEo8Dc5b_y2h-OK1g320KzkxblJWfAPZTtx2FyE44UoLMD37D6i8Gg_4WIi9PT3HsNV1eEbyZ1ufnx6oU5b5Y0cFmiuZsBOrFlMeXseBNhajvSAJs1UCwLE0TKfXOejHvsmCyB_Ms31IKgdl48UTtUo4ceXnyzom0Q0hE1wavikBVPIWIDbpqMn1dgXlOkvjdlniXFz__u-z5OAqfEjKm-qXYw6hoRI77WYZ-HTAGvqFOWWgIHWaIJUj2vagkhQhwA9-WTu6wg3C0q1Ya7K4Ek5r-v7fNogbeBBQ"}

Communication

Your JWT can now be sent to the player by POST, using postMessage method.

Game side

This is the function we have implemented on our games:

postDataAfter(url, token, timeToWait) {

window.setTimeout(function () {
parent.postMessage({ type: "gameOver", payload: token, url }, "*");
}, timeToWait);

}

Let's not forget that we are in an iframe → parent.postMessage()

Player side

The function which receives the message called "gameOver".

if (event.data && event.data.type && event.data.type === "gameOver") {
// verify token, save data, go to the next step...
}

Player side verification

The JWT will be read by the Player and decoded with your public key. The campaign will stop in case of problem.

Code example

Here is a "one file" concrete example of reading and sending signed JWT using the jsrsasign library.

The 'jsrsasign' (RSA-Sign JavaScript Library) is an opensource free cryptography library supporting RSA/RSAPSS/ECDSA/DSA signing/validation, ASN.1, PKCS#1/5/8 private/public key, X.509 certificate, CRL, OCSP, CMS SignedData, TimeStamp, CAdES JSON Web Signature/Token in pure JavaScript.

```html
<html>
<head>
<title>HTML game</title>
<script language="JavaScript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.0.2/jsrsasign-all-min.js"></script>
<style type="text/css">
body { font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; font-size: 1em;}
</style>
</head>
<body>
<h3>Minigame</h3>

<p>This page contains a short description of the mechanics to be used to read the JWT1 and return the scrore and time in a signed JWT2.</p>

<p>It is obviously understood that the keys cannot be readable in the source code of your application. Their presence only serves to explain the method.</p>

<script language="JavaScript" type="text/javascript">
```

```jsx
// default
var postURL = '';
var url = '';
// get token in query string
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const jwt1 = urlParams.get('token');

// here the Qualifio Public Key
var publicKey1 = `-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2fAi2xFo4MVb5bLxOzQR
O8R31tU2tGQ4WfCT+5KtVQOrPoXBpLI1oRyiCQ2NWQhuwl8ADT0UoNM+FHLHvjXp
fM17jcuzBR5kpn5LdIG/iJaLLAC32XpsQTxAkwSC/UHuhiRl5nRvhj3uEuM2AMc+
Y0kHh1yQN9/v5Y/Xwa0LrcMPJ/sTFzEuC1E4xNggIcmgthEsRodskP1ILpoM2jN2
...
-----END PUBLIC KEY-----`;

// here the Partner's private key
var privateKey2 = `-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC9lK5OqyQSf6nt
tq5jnrU285WU+rrbd8HbUnrsWtSKtaVhsF/86E1Z1LVyRXQA/x+Aa+Rq+3JrWQh5
/7pXV3aEVLUT5Pq/LX114Q4GsviHqpbV8/TTcXvghKeN+rM13hylfcRLzMjue/Rv
SzD0Q8V80gKoGGDAFD/OLPp6C5gjkId/8kl8iehtaD069NCbvXjtO6sALwk5AOtm
KPuAQkmOPx7iPYcUpLvTRf7wpp65ujWmNFSjKiaMBKDodyNeB7EphFff52IPh2Pm
...
-----END PRIVATE KEY-----`;

var pubKey1 = KEYUTIL.getKey(publicKey1);

var jswParsed = KJUR.jws.JWS.parse(jwt1);

// check the JWT1 with the public key
isValid = KJUR.jws.JWS.verify(jwt1, pubKey1, ['RS512']);

// if it's OK, let's go to sending the score and time
if (isValid) {

// recover where to send the data in the JWT1
var postURL = jswParsed.payloadObj.config_override.postURL;

// JWT2 preparation
var jwt2 = {
"jwt": jwt1,
"result": [
["score", 17],
["time", 26000 ]
],
"iat": Math.floor(Date.now() / 1000) - (20*60),
"exp": Math.floor(Date.now() / 1000) + (60*60),
"iss": "com.yourCompanyName.games.gameName"
};

// signature of the JWT with the partner's private key
var sJwt2 = KJUR.jws.JWS.sign(null, {alg: "RS512"}, JSON.stringify(jwt2), privateKey2);

// retrieve the result in the token
var jwtToken = {
"jwt": sJwt2
}

// sending of the token by postMessage in the parent page (the Player)
var token = JSON.stringify(jwtToken);

function postResult(url, token) {
parent.postMessage({ type: "gameOver", payload: token, url }, "*");
}

}

```

```html
</script>

<!-- call to action -->
<a href="#anchor" onclick="javascript:postResult(postURL, token);">Post result</a>

</body>
</html>
```

You can download our HTML kit at this address:

Preview using this

Preview Widget

Recommended technologies

The agency or developer will ensure the quality, lightness and portability of its code.

Think portability

We recommend to develop your games in JavaScript and/or HTML5.

Think lightness

  • Optimise the elements that make up the game (illustrations and sounds).
  • If the gameplay allows it, use vector elements.
  • If necessary, set up a pre-loading stage.

Think usability

The game should be designed to work on mobile and desktop devices. It is therefore necessary that the movements specific to the use of a touch screen are transposed to the mouse and/or keyboard.

Think responsiveness

The game will have to be able to operate in an iframe which will sometimes occupy a reserved space and sometimes the entire screen. The game must therefore be responsive.

Think your display mode

If the game can only be displayed in portrait or landscape mode, please let us know which mode to block. We'll take care of presenting a screen inviting the participant to orient their device correctly.

Implementation

We need to know which URL to call to build the iframe. With the understanding that the game is hosted on your servers.

Recommendations

  • The game cannot receive and/or store personally identifiable information (PII).
  • The game cannot set any cookies.
  • Do not expose private and or public keys in your source code.

Dynamic variables (placeholders)

If you wish to display the score and time in the exit screen of your campaign, you can use the following placeholders:

  • {score} = score returned by the JWT2
  • {time} = time returned by the JWT2 (recommended unit = millisecond)
  • {timeInSeconds} = {time} / 1000

Steps to get started

Initial setup

  1. You download, unzip and host our HTML kit which contains:
    1. A public key for JWT1 reading (RS512 / PKCS8).
    2. An example of the JWT2 (containing the score and time) to be signed and returned to us.
  2. You give us the address of the HTML kit.
  3. We create a campaign that uses this HTML kit.

Game development

  1. You develop the game.
  2. You replace the HTML kit by the game you have developed.
  3. If you have changed the keys for signing and reading the JWT2:
    1. Test your JWT and your public key on this page: Token Checker.
    2. If the test is OK, you give us the public key to read the JWT2 (RS512 / PKCS8).

Additional resources