Admin Panel

Add SCILL to a website

SCILL gives you the tools to activate, retain and grow your user base on your websiteby bringing you features well known in the gaming industry: Gamification. We take care of the services and technology involved, so you can focus on your content and services.

Today, as an operator of a website you want to generate first party data, that is you want your users to sign up and keep logged in. Furthermore, you want your users to deliver data that you can use for targeting in advertising and to learn more about your users needs and interests.

The tools we provide leverage “hard-wired” user behaviour to trigger certain actions that are of value for you and your users.

This guide will show you how to add our web components quickly to your website. These webcomponents implement best practices in your website. However, you are free to build custom implementation by using our JavaScript/PHP SDKs or by consuming our REST-API directly.

After you have ordered a SCILL subscription, we already have created a couple of challenges, webhooks and battle passes to give you a head start. You shoud have an email in your inbox with these infos:

  • Your App ID
  • Your API Key
  • The Battle Pass Id

You can login into the Admin Panel to see the content created. We’ll walk through that in this guide.

Let`s get started

SCILL Website Gamification integration consists of three steps.:

1 Get an access token

As SCILL does not know anything about your users, your application needs to request an access token from the SCILL backend that links you user to the events and to user specific data.

3 Implement web components

Implement a user interface to show daily and weekly tasks to your users and show them the personal rankings and next steps to improve that ranking.

1 Send Events

Events are the engine of SCILL and drive the whole ecosystem. To “drive” tasks and user rankings you need to send specific events at specific locations in your website.

Basic Application Structure

As said before, we already have created a SCILL application for you that should help you getting started quickly. The SCILL application consists of these parts:

Daily Tasks

A couple of daily and weekly tasks, built with SCILL Challenges, i.e.

  • Visit the website (every day)
  • Read an article (every day)
  • Share an article (every week)
Tip

SCILL challenges can be created in a variety of different ways. In this case, we chose auto-activated challenges that reset every day or week. In this case, the challenge activates at midnight, and the user has time to complete it - for example by visiting the website - until the next days midnight. The same is possible on a weekly and monthly basis. You can also set up challenges that never expire/reset.

User rankings

One thing, that might be important for you is pushing logins and sign ups. The best approach is to give your users some value in doing that. To give that value, we created a “Battle Pass”. Battle passes in SCILL are structured tasks and challenges grouped in levels. Users start at Level 1, and by completing tasks, they will - step by step - climb up in the rankings.

The example battle pass is structured like this:

  • Level 1
    • Sign up
  • Level 2
    • Upload profile image
  • Level 3
    • Collect 100 points
  • Level 4
    • Collect 100 points
Tip

The 3rd and 4th level consists of a challenge that is achieved once 100 points have been collected. Each of the daily and weekly challenges has an XP value value of 1 which means, that achieving these challenges one point is added to the users ranking system.

Generate Access Token

Generating an access token should be done in the backend, as this is the only place you can securely protect from your users. More info on this topic you can find here: Authentication.

If you already have a backend (i.e. HTTP server or Cloud Functions like Lambda or Google Cloud Functions) it’s easy to create such a backend webservice. If you don’t have any backend for your game, we suggest using Google Firebase which is very cheap and Cloud Functions can be easily created using JavaScript (NodeJS) or PHP.

Tip

If you render HTML on the server with PHP or NodeJS then you don’t need to do it this way. You can just create an access token and directly render the value in the web components attribute access-token. See Implement webcomponents for details on how to do it differently.

NodeJS

If your backend runs on NodeJS you can integrate sending events like this:

Step 1: Install JavaScript SDK

npm install @scillgame/scill-js --save

You will now have installed our NPM module and can use it in your NodeJS based code. Please upgrade the package regulary to get updates and bug fixes.

Step 2: Initialize module

Add this to the head of your NodeJS code or cloud function.

Importing SCILL class
const scill = require('@scillgame/scill-js');

Congratulations! You have configured a SCILL class that can be used to send events and generate access tokens. Refer to the API-Reference to learn what you can do with it.

Step 3: Node-JS Server example

You don’t want to expose User IDs and/or the API-key in unsecure environments as this would allow anyone with some basic knowledge of the browsers web console to extract those and being able to send requests without your permission. To secure this, you create an access token for each user for each client session.

In your NodeJS backend you need to provide a webservice that your client can call to get an access token. You will most likely already have some sort of webservice so this is just a very basic example code based on a simple express server.

NodeJS server example
// This example implements a NodeJS backend receiving sessions from your client and asking SCILL
// to generate an access token for the userId "encoded" in/via the session.

const express = require('express');
const bodyParser = require('body-parser');
const scill = require('scill');

// Generate an instance of the SCILL SDK with example API-Key
const auth = scill.getAuthApi('__YOUR_API_KEY__');

const app = express();
const port = 80;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.get('/scill/generate-access-token', (req, res) => {
    // In this example we use a session sent to this endpoint from the client to extract a user id from the session
    // How you implement that is up to you and depends on your user system
    const session = req.query.session;
    
    // In this example we just hard core the user id. You should have someline like getUserIdFromSession to extract
    // the user id from the session
    const userId = '1234';

    // Call SCILL backend to generate an access token encoding user and API-Key
    return auth.generateAccessToken({
        user_id: userId
    }).then(accessToken => {
        // return access token
        return res.send({
            success: true,
            token: accessToken.token
        });
    }).catch(error => {
        return res.send({
            success: false,
            error: error
        });
    });
});

app.listen(port, () => {
    console.log('Example app listening at http://localhost:${port}');
});

The SCILL JavaScript SDK function generateAccessToken is used to generate an access token based on the user id you are providing. What happens here is that SCILL receives your API-Key together with the user id and then creates as well as signs a JWT token.

More info on this topic can be found in the Authentication document.

Please note: A cheater/hacker only needs to get his hands on userid and your api key to send events “on a users behalf”.

Whatever your implementation looks like, make sure that you follow these basic rules:

  • Don’t expose any part of the access token generation to the user, especially the api key and the userid
  • Don’t think that any sort of client side “obfuscation” does help in any way - hackers overcome these things in minutes
  • Your design must be secure by design. If you follow this guide it definitely will be.
  • All communication must be done via HTTPS

PHP

If your backend runs on PHP you can integrate sending events like this:

Step 1: Install PHP SDK

composer require scill/scill-php

If you don’t use composer in your project you can also download the PHP SDK from Github and import the classes manually into your project.

Step 2: Initialize library

Use autoload.php to initialize PHP library and setup an instance of the SCILLClient class by providing your API key.

Getting SCILL Client instance
<?php
    require_once(__DIR__ . '/vendor/autoload.php');

    // Setup SCILL Events client instance    
    $scillClient = new \SCILL\SCILLClient('__YOUR_API_KEY__');
    $scillEvents = $scillClient->getEventsClient();    
?>

Congratulations! You have set up an instance of the SCILL SDK class, that can be used to send events and generate access tokens. Refer to the API-Reference to learn what you can do with it.

Step 3: PHP Slim Server Example

You don’t want to expose User IDs and/or the API-key in unsecure environments as this would allow anyone with some basic knowledge of the browsers web console to extract those and being able to send requests without your permission. To secure this, you create an access token for each user for each client session.

This example is based on the Slim Framework to quickly create REST-APIs with PHP to get you an idea how to implement it.

Slim route to generate access token
<?php
    $app->get('/scill/generate-access-token', function (Request $request, Response $response) {
    
        // In this example we expect that the client sends us a session id that we decode to receive a user id
        // This could also be a JWT token or a Steam Session. Whatever it is, it's your job to receive an encoded
        // user auth from the client, to decode it into a user id
        $params = $request->getQueryParams();
        $userId = null;
        if (!$params || !$params["session"]) {
            $response->getBody()->write('No session provided');
            return $response;
        } else {
            // Decode the session - in this example we just hardcode it
            $userId = "1234";
        }
    
        // Create the request to generate an access token
        /** @var \SCILL\SCILLClient $scill */
        $scill = $this->get('scill');
    
        $payload = new \SCILL\Model\ForeignUserIdentifier();
        $payload->setUserId($userId);
    
        // Run the request and if everything worked fine we can return the access token to the client
        try {
            $result = $scill->getAuthClient()->generateAccessToken($payload);
            $accessToken = $result->getToken();
            $result = array(
                "success" => true,
                "token" => $accessToken
            );
            $response->getBody()->write(json_encode($result));
        } catch(\SCILL\ApiException $exception) {
            $result = array(
                "success" => false,
                "error" => $exception->getMessage()
            );
            $response->getBody()->write(json_encode($result));
        }
        return $response;
    });
?>

The function generateAccessToken is used to generate an access token based on the user id you are providing. What happens here is that SCILL receives your API-Key together with the user id and then creates as well as signs a JWT token.

More info on this topic can be found in the Authentication document.

Please note: A cheater/hacker only needs to get his hands on userid and your api key to send events “on your behalf”. Everything else is public information and can be found in this documentation (i.e. SCILL endpoints to send events to).

Whatever your implementation looks like, make sure that you follow these basic rules:

  • Don’t expose any part of the access token generation to the user, especially the api key and the userid
  • Don’t think that any sort of client side “obfuscation” does help in any way - hackers overcome these things in minutes
  • Your design must be secure by design. If you follow this guide it definitely will be.
  • All communication must be done via HTTPS

Implement Webcomponents

Webcomponents is a fairly new, but widely supported solution (in all major browsers) that allows developers to package external functionality into another website by a custom html component. It’s like an iframe but embedded directly into the website. As Webcomponents are embedded in the DOM of the website web components can be responsive and respond to the outer side.

SCILL offers a variety of web components for different use cases. Web components are also open source, so you can customize them quickly to your own needs. Please check out our Github respository on web components.

Let’s start adding the following web component to your website (you can adjust colors and styles later):

Adding a web component
<link href="https://cdn.scillgame.com/styles.css" rel="stylesheet">
<script src="https://cdn.scillgame.com/scill-widgets.js" type="text/javascript"></script>
<script type="text/javascript">
    // Get a session id from a cookie or any other method that makes sense in your application
    const sessionId = getSessionId();
    
    // Call the cloud function created before in your backend
    fetch('https://example.com/scill/generate-access-token?session=' + sessionId).then(response => response.json()).then(response => {
        // If everything works, we should get the access token in the response
        if (response && response.success && response.token) {
            // We got a token - find all SCILL web components and set the access token attribute
            const components = document.getElementsByClassName("scill-web-component");
            for (let i=0;i<components.length;i++) {
                components[i].setAttribute("access-token", response.token);
            }            
        } else {
            console.warn("Failed to generate access token: ", response);
        }
    });
</script>
<scill-popover-preview class="scill-web-component"
                       username="Guest"
                       app-id="__YOUR_APP_ID__"
                       battle-pass-id="__YOUR_BATTLE_PASS_ID__">
</scill-popover-preview>

As you can see, this is pretty simple. Short explanation what happens:

  1. Call the backend function that we created earlier with a session id (i.e. from a cookie or localStorage)
  2. If successful, find all DOM elements with a class named scill-web-component and set the access-token attribute.
  3. Embed the SCILL web component with the class scill-web-component and with the app id and battle pass id created for the demo application (see your emails for that info).

If you render HTML on the server side for example with PHP, you can add the web component directly in your website:

Set access token directly in HTML
<html>    
    <head>
        <link href="/css/scill-styles.css" rel="stylesheet">
        <script type="text/javascript" src="/js/scill-widgets.js"></script>
    </head>
    <body>
        <?php 
            $payload = new \SCILL\Model\ForeignUserIdentifier();
            $payload->setUserId($userId);
            $result = $scill->getAuthClient()->generateAccessToken($payload);
            $accessToken = $result->getToken();
        ?>
        <scill-popover-preview class="scill-web-component"
                       username="Guest"
                       app-id="__YOUR_APP_ID__"
                       battle-pass-id="__YOUR_BATTLE_PASS_ID__"
                       access-token="<?php $accessToken ?>">
        </scill-popover-preview>
    </body>
</html>

That’s it. Your web page should now show a fully dynamic and working gamification element. Last step is to add events to your website.

Sending events

Some basic info about challenges and how events relate together:

  • Each challenge “listens” on specific event type.
  • SCILL supports many event types (see Event Types.
  • Events can also have meta-data, that adds additional info to them and challenges can be specified to just listen on events with specific meta-data.
  • More info on the relationship between Events and Challenges can be found here.

This is the challenge setup in the example app:

Challenge Event-Type Meta-Data
Visit the website craft-item item_type = page_impression
Read an article craft-item item_type = article_page_impression
Share an article craft-item item_type = share_article
Sign up upgrade-item item_name = account
Update profile image upgrade-item item_name = profile_image
Collect 100 points collect-item item_type = points

To trigger the “Visit the website” challenge, we need to send a craft-item event with meta data being set to page_impression for the item_type.

Sending the craft-item event
// In Backend code you can use the API key
const SCILL = require('@scillgame/scill-js');
const eventsApi = SCILL.getEventsApi('__YOUR_API_KEY__');

eventsApi.sendEvent({
    event_name: 'craft-item',
    event_type: 'single',
    session_id: '__SESSION_ID__',
    user_id: '__USER_ID__',
    meta_data: {
        amount: 1,
        item_type: isArticlePage ? "article_page_impression" : "page_impression"
    }
}).then(() => {})
.catch(error => {
    console.warn("Event could not be sent", error);
});
<?php
require_once(__DIR__ . '/vendor/autoload.php');

// Setup SCILL Events client instance
$scillClient = new \SCILL\SCILLClient('__YOUR_API_KEY__');

$eventsApi = $scillClient->getEventsClient();

try {
    $result = $scillClient->sendEvent('craft-item', '__USER_ID__', '__SESSION_ID__', array(
        "amount" => 1,
        "item_type" => $isArticlePage ? "article_page_impression" : "page_impression"
    ));
} catch(\SCILL\ApiException $exception) {
    echo("Error: ".$exception->getMessage());
}

We send an item type of page_impression if a standard website like the start page is requested by the user. And we’ll use an article_page_impression if it’s an article page.

You need to replace these values with actual values:

__YOUR_API_KEY__
The API key of your application - please refer to the email you received. Or check out the Admin Panel for your App Id and API key.
__USER_ID__
This is the user id as a string. It must be the same you use for generating the access token!
__SESSION_ID__
The session id is used to group events together. If a new session id is sent the challenge counter will reset. The idea behind that is this: You could create a challenge like “Read 5 articles in one hour”. You would then use the hour as a session id. This way, the counter of the challenge would reset every full hour. If you don’t need such functionality, you can just set the same value as the user id. Please note: Daily, weekly or monthly challenges will reset even if the session is kept persistent! With the session id you can reset challenges within their live-time.
Tip

SCILL provides a Playground application that allows you to play around with your challenges, battle passes and events. It’s a good way to learn how SCILL works: SCILL Playground.

The next event we need to add is the event that drives the “Share article” challenge. Add this code in your page once the articles has been shared:

Sending the share article event
// In Backend code you can use the API key
const SCILL = require('@scillgame/scill-js');
const eventsApi = SCILL.getEventsApi('__YOUR_API_KEY__');

eventsApi.sendEvent({
    event_name: 'craft-item',
    event_type: 'single',
    session_id: '__SESSION_ID__',
    user_id: '__USER_ID__',
    meta_data: {
        amount: 1,
        item_type: "share_article"
    }
}).then(() => {})
.catch(error => {
    console.warn("Event could not be sent", error);
});
<?php
require_once(__DIR__ . '/vendor/autoload.php');

// Setup SCILL Events client instance
$scillClient = new \SCILL\SCILLClient('__YOUR_API_KEY__');

$eventsApi = $scillClient->getEventsClient();

try {
    $result = $scillClient->sendEvent('craft-item', '__USER_ID__', '__SESSION_ID__', array(
        "amount" => 1,
        "item_type" => "share_article"
    ));
} catch(\SCILL\ApiException $exception) {
    echo("Error: ".$exception->getMessage());
}

Let’s drive the battle pass challenges with this event. Add it to your code once your user has created an account.

Sending events for account upgrades
// In Backend code you can use the API key
const SCILL = require('@scillgame/scill-js');
const eventsApi = SCILL.getEventsApi('__YOUR_API_KEY__');

eventsApi.sendEvent({
    event_name: 'upgrade-item',
    event_type: 'single',
    session_id: '__SESSION_ID__',
    user_id: '__USER_ID__',
    meta_data: {
        amount: 1,
        item_name: "account"
    }
}).then(() => {})
.catch(error => {
    console.warn("Event could not be sent", error);
});
<?php
require_once(__DIR__ . '/vendor/autoload.php');

// Setup SCILL Events client instance
$scillClient = new \SCILL\SCILLClient('__YOUR_API_KEY__');

$eventsApi = $scillClient->getEventsClient();

try {
    $result = $scillClient->sendEvent('upgrade-item', '__USER_ID__', '__SESSION_ID__', array(
        "amount" => 1,
        "item_type" => "account"
    ));
} catch(\SCILL\ApiException $exception) {
    echo("Error: ".$exception->getMessage());
}
Tip

Events are always the same, they are not different if you have Battle Pass Challenges or Personal Challenges. Events drive most modules within SCILL. By having all these events, you have the full flexibility to build new challenges or leaderboards without adding one line of code!

I leave adding the last events up to you. Try to find events that make sense for your use case. We have a huge list of available event types.

More Webcomponents

We offer a couple of web components that you can use throughout your website or application. All web components are provided open source at Github. It’s an Angular project that allows you to quickly adjust the code to fit your needs. All web components also offer a lot of attributes to customize them without any code changes.

More info on Webcomponents: SCILL Webcomponents