Iframe Setup Guide

This page shows details about how to set up and use the Arkose Fraud Deterrence Platform (Arkose Platform) in the context of an iframe.

📘

Please note that Arkose Platform can host the domain/iframe for use by a customer. Please contact your CSM (Customer Success Manager) or SE for additional information.

📘

iframe-auth to be deprecated.

Previous uses of iframe-auth in URLs have been changed to use iframe.

How to Use the iframe

The code below shows a full example of how to load the hosted Arkose Platform iframe. Please select either the Arkose Protect or Arkose Detect code view, appropriate to which you are using.

<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Identity Page</title>
    <style>
        iframe {
            width: 0px;
            height: 0px;
            border: 0 !important;
            overflow-y: hidden;
        }
    </style>
    <script>
        window.addEventListener("message", function (event) {
            var json_parsed_event = JSON.parse(event.data)

            switch (json_parsed_event.eventId) {
                case "challenge-loaded":
                    document.getElementById("arkoseFrame").style.height = json_parsed_event.payload.frameHeight;
                    document.getElementById("arkoseFrame").style.width = json_parsed_event.payload.frameWidth;
                    break;
                case "challenge-suppressed":
                    break;
                case "challenge-complete":
                    alert(json_parsed_event.payload.sessionToken)
                    break;
                case "challenge-shown":
                    console.log("Challenge Shown");
                    console.log(json_parsed_event.payload);
                    break;
                case "challenge-iframeSize":
                    document.getElementById("arkoseFrame").style.height = json_parsed_event.payload.frameHeight;
                    document.getElementById("arkoseFrame").style.width = json_parsed_event.payload.frameWidth;
                    break;
            }
        });
    </script>
</head>

<body>
    <iframe id="arkoseFrame" src="https://iframe.arkoselabs.com/11111111-1111-1111-1111-111111111111/index.html">
    </iframe>
</body>

</html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Identity Page</title>
    <style>
        iframe {
            width: 0px;
            height: 0px;
            border: 0 !important;
            overflow-y: hidden;
        }
    </style>
    <script>
        window.addEventListener("message", function (event) {
            var json_parsed_event = JSON.parse(event.data)

            switch (json_parsed_event.eventId) {
                case "detect-loaded":
                    document.getElementById("arkoseFrame").style.height = json_parsed_event.payload.frameHeight;
                    document.getElementById("arkoseFrame").style.width = json_parsed_event.payload.frameWidth;
                    break;
                case "detect-suppressed":
                    break;
                case "detect-complete":
                    alert(json_parsed_event.payload.sessionToken)
                    break;
            }
        });
    </script>
</head>

<body>
    <iframe id="arkoseFrame" src="https://iframe.arkoselabs.com/11111111-1111-1111-1111-111111111111/index.html">
    </iframe>
</body>

</html>

Iframe Events

The iframe events are listed below. Please note the appropriate name and description depends on whether you are using Arkose Protect or Arkose Detect.

Event

Type

Description (Arkose Protect)

Description (Arkose Detect)

challenge-loaded

event

Challenge has finished loading.

Not applicable.

detect-loaded

event

Not applicable.

Detection has finished loading.

challenge-suppressed

event

Challenge will not be presented to the user (Good User Case).

Not applicable.

detect-suppressed

event

Not applicable.

Detection is running and analyzing the user intent.

challenge-complete

event

Challenge solved / user is validated as good.

Not applicable.

detect-complete

event

Not applicable.

Detection is complete.

challenge-shown

event

Challenge is presented to the user.

Not applicable.

challenge-iframesize

event

Height and Width of the content within the iframe (For Dynamic Styling).

Not applicable.

challenge-error

event

Challenge has encountered an error.

Not applicable.

detect-error

event

Not applicable.

Detection has encountered an error.

URL Reference

This is a breakdown of the URL which needs to be loaded in the iframe:

  • Domain: https://iframe.arkoselabs.com
  • Path Options:
    • public key: In the examples above this is 11111111-1111-1111-1111-111111111111. Replace this with the public key Arkose Labs gives you.
  • URL Params:
    • mkt: This is the parameter for passing in a language code. For a list of our supported language codes see Supported Languages.

📘

Please note that Arkose Labs can host the iframe for merchants.

Hosting your Own iframe

Although Arkose Labs generally hosts customer Iframes, customers may choose to host their own iframe.

Creating the Iframe Page and Domain

When using this solution:

  • A separate domain must be set up.
  • A page with the Arkose Platform code must be hosted from it.

Creating the Domain

Create and host the domain using your standard process. An example domain name is https://iframe.arkoselabs.com.

Creating the Hosted Page

The following is example code that could be used to load the Arkose Platform iframe. Please see our Client-Side Instructions for more information on the Arkose Platform implementation. Please select the code view for either Arkose Detect or Arkose Protect, depending on which one you are using.

📘

Please note that some accessibility tools (e.g. Windows narrator) will use the words in the title section as spoken text for this iframe. Update the title to comply with your branding strategy.

<html>

<head>
    <meta charset="utf-8">
    <title>Authentication</title>
    <script>

        function getAllUrlParams(url) {
            // get query string from url (optional) or window
            var queryString = url ? url.split('?')[1] : window.location.search.slice(1);

            // we'll store the parameters here
            var obj = {};

            // if query string exists
            if (queryString) {

                // stuff after # is not part of query string, so get rid of it
                queryString = queryString.split('#')[0];

                // split our query string into its component parts
                var arr = queryString.split('&');

                for (var i = 0; i < arr.length; i++) {
                    // separate the keys and the values
                    var a = arr[i].split('=');

                    // set parameter name and value (use 'true' if empty)
                    var paramName = a[0];
                    var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];

                    // (optional) keep case consistent
                    paramName = paramName.toLowerCase();
                    if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();

                    // if the paramName ends with square brackets, e.g. colors[] or colors[2]
                    if (paramName.match(/\[(\d+)?\]$/)) {

                        // create key if it doesn't exist
                        var key = paramName.replace(/\[(\d+)?\]/, '');
                        if (!obj[key]) obj[key] = [];

                        // if it's an indexed array e.g. colors[2]
                        if (paramName.match(/\[\d+\]$/)) {
                            // get the index value and add the entry at the appropriate position
                            var index = /\[(\d+)\]/.exec(paramName)[1];
                            obj[key][index] = paramValue;
                        } else {
                            // otherwise add the value to the end of the array
                            obj[key].push(paramValue);
                        }
                    } else {
                        // we're dealing with a string
                        if (!obj[paramName]) {
                            // if it doesn't exist, create property
                            obj[paramName] = paramValue;
                        } else if (obj[paramName] && typeof obj[paramName] === 'string') {
                            // if property does exist and it's a string, convert it to an array
                            obj[paramName] = [obj[paramName]];
                            obj[paramName].push(paramValue);
                        } else {
                            // otherwise add the property
                            obj[paramName].push(paramValue);
                        }
                    }
                }
            }
            return obj;
        }

        // Setup Arkose Script
        var pathArray = window.location.pathname.split('/')

        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.defer = true;
        script.src = '//client-api.arkoselabs.com/v2/' + pathArray[1] + '/api.js'
        script.setAttribute('data-callback', 'setupEnforcement');

        document.getElementsByTagName('head')[0].appendChild(script);

        // Let this function run on a set interval. It will review the Arkose Content that loads and send the page sizing for the iframe to the parent
        var interval = setInterval(function () {
            frameHeight = document.getElementById("fc-iframe-wrap").offsetHeight;
            frameWidth = document.getElementById("fc-iframe-wrap").offsetWidth;
            parent.postMessage(JSON.stringify({
                eventId: "challenge-iframeSize",
                payload: {
                    frameHeight: frameHeight,
                    frameWidth: frameWidth
                }
            }), "*")
        }, 3000);

        function setupEnforcement(myEnforcement) {
            var params = getAllUrlParams(window.location.href);

            myEnforcement.setConfig({
                selector: '#arkose',
                styleTheme: params.theme,
                language: params.mkt,
                mode: 'inline',
                onCompleted: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "challenge-complete",
                        payload: {
                            sessionToken: response.token
                        }
                    }), "*")
                },
                onReady: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "challenge-loaded",
                    }), "*")
                },
                onSuppress: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "challenge-suppressed",
                    }), "*")
                },
                onShown: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "challenge-shown",
                    }), "*");
                },
                onError: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "challenge-error",
                        payload: {
                            error: response.error
                        }
                    }), "*");
                }
            });
        }

    </script>
</head>

<body style="margin: 0px">
    <div id="arkose">
    </div>
</body>

</html>
<html>

<head>
    <meta charset="utf-8">
    <title>Authentication</title>
    <script>

        function getAllUrlParams(url) {
            // get query string from url (optional) or window
            var queryString = url ? url.split('?')[1] : window.location.search.slice(1);

            // we'll store the parameters here
            var obj = {};

            // if query string exists
            if (queryString) {

                // stuff after # is not part of query string, so get rid of it
                queryString = queryString.split('#')[0];

                // split our query string into its component parts
                var arr = queryString.split('&');

                for (var i = 0; i < arr.length; i++) {
                    // separate the keys and the values
                    var a = arr[i].split('=');

                    // set parameter name and value (use 'true' if empty)
                    var paramName = a[0];
                    var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];

                    // (optional) keep case consistent
                    paramName = paramName.toLowerCase();
                    if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();

                    // if the paramName ends with square brackets, e.g. colors[] or colors[2]
                    if (paramName.match(/\[(\d+)?\]$/)) {

                        // create key if it doesn't exist
                        var key = paramName.replace(/\[(\d+)?\]/, '');
                        if (!obj[key]) obj[key] = [];

                        // if it's an indexed array e.g. colors[2]
                        if (paramName.match(/\[\d+\]$/)) {
                            // get the index value and add the entry at the appropriate position
                            var index = /\[(\d+)\]/.exec(paramName)[1];
                            obj[key][index] = paramValue;
                        } else {
                            // otherwise add the value to the end of the array
                            obj[key].push(paramValue);
                        }
                    } else {
                        // we're dealing with a string
                        if (!obj[paramName]) {
                            // if it doesn't exist, create property
                            obj[paramName] = paramValue;
                        } else if (obj[paramName] && typeof obj[paramName] === 'string') {
                            // if property does exist and it's a string, convert it to an array
                            obj[paramName] = [obj[paramName]];
                            obj[paramName].push(paramValue);
                        } else {
                            // otherwise add the property
                            obj[paramName].push(paramValue);
                        }
                    }
                }
            }
            return obj;
        }

        // Setup Arkose Script
        var pathArray = window.location.pathname.split('/')

        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.defer = true;
        script.src = '//client-api.arkoselabs.com/v2/' + pathArray[1] + '/api.js'
        script.setAttribute('data-callback', 'setupDetect');

        document.getElementsByTagName('head')[0].appendChild(script);

        function setupDetect(myDetect) {
            var params = getAllUrlParams(window.location.href);

            myDetect.setConfig({
                selector: '#arkose',
                styleTheme: params.theme,
                language: params.mkt,
                mode: 'inline',
                onCompleted: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "detect-complete",
                        payload: {
                            sessionToken: response.token
                        }
                    }), "*")
                },
                onReady: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "detect-loaded",
                    }), "*")
                },
                onSuppress: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "detect-suppressed",
                    }), "*")
                },
                onError: function (response) {
                    parent.postMessage(JSON.stringify({
                        eventId: "detect-error",
                        payload: {
                            error: response.error
                        }
                    }), "*");
                }
            });
        }

    </script>
</head>

<body style="margin: 0px">
    <div id="arkose">
    </div>
</body>

</html>

Please note the following regarding the above sample code:

getAllUrlParams - A reference function for parsing url parameters if you need to pass any important information through the iframe. An example of important information is language code. See the URL reference section later in this page for more information about URL parameters.

parent.postMessage - Pass event data back to the parent domain. For example, passing back the session token to submit to the server-side.

challenge-iframeSize - Not applicable for Arkose Detect. This runs on an interval for dynamic resizing of the iframe on the parent element. This data can also be parsed and passed through as part of the Arkose Platform loaded event.

The above code snippet is for implementing Client-API v2, which is the most up to date implementation of Arkose Protect and Detect. For iFrame implementation information regarding Client-API v1, please see xxxxxxx[link].