Documentation

Table of Contents

Consent Solution – JS Documentation

The Consent Solution JavaScript library allows you to record consent actions performed by your users, which will be referred to as “subjects” throughout the rest of this guide.

The Consent Solution JavaScript library has the following features:

  • Directly write to the Consent Solution API (i.e. record the consent)
  • Write both synchronously and asynchronously, optionally leveraging localStorage
  • Multiple consent tracking options. Not only can you monitor a specific form and track consent on submit, you can also track consent by other programmatic means (e.g. after a validation process or after some other event).
  • Supports most browsers (IE8+)
  • Provides callbacks
  • Logging features
Notice

On 03/04/2019 a new version of the Consent Solution JS has been released; if you have installed the Consent Solution prior that date and you want to move to the new version please refer this section (at the end of this post).

1. Setup script

To install the Consent Solution JS widget, insert your Consent Solution code inside every page of your site, before closing the HEAD tag (see example code below).

<script type="text/javascript">
    var _iub = _iub || {};
    _iub.cons_instructions = _iub.cons_instructions || [];
    _iub.cons_instructions.push(["init", {api_key: "YOUR_PUBLIC_API_KEY"}]);
</script>
<script type="text/javascript" src="https://cdn.iubenda.com/cons/iubenda_cons.js" async></script>

*The API key is a unique code that the SDK uses in order to communicate with our API’s endpoint. Your API key (displayed as “YOUR_PUBLIC_API_KEY” in the example above) is generated by us during the Consent Solution activation and is specific to that particular site.

Caution

The code above is just an example. Please be sure to use your own Consent Solution code as the code is specific to your particular site. You can find your code snippet by going to Dashboard > [your website area] > Consent Solution > EMBED. Once there, simply copy the information you need.

2. init configuration

The init function (included into the setup script above) defines how the library is instantiated and is required on every page that implements the Consent Solution widget.

It is possible to add a callback function as a second parameter of the init function. The callback function will then be called once the library has been loaded.

Configuring the init function this way (by adding a callback function — see “YOUR_CALLBACK” in the example below) can be used to set some additional action after the library has been loaded.

_iub.cons_instructions.push(["init", {
    api_key: "YOUR_PUBLIC_API_KEY"},
    function YOUR_CALLBACK() {
        //the library has been loaded
        ...
        //put you code here
	...
    }
]);

The following are the parameters that you can use inside the init configuration object ( i.e. the first parameter on init function which contains the API key) to customize, for example, the logger or the behaviour of the library.

See table and code example below:

Name Required Type Notes
api_key yes String Your public key
logger no String Possible values: “none”, “console”. Defaults to: “console”
log_level no String Possible values: “none”, “debug”, “info”, “warn”, “error”, “fatal”. Defaults to: “error”
sendFromLocalStorageAtLoad no boolean Determines whether the script reads localStorage at load and submits whatever is included. Defaults to: true
// An example configuration with optional parameters added (note: api_key parameter is always required)

_iub.cons_instructions.push(["init", {
    api_key: "YOUR_PUBLIC_API_KEY",
    logger: "console",
    log_level: "warn",
    sendFromLocalStorageAtLoad: false
}, ...]);

3. Connect the Consent Solution to a submission form

In order to automatically record the consents provided via a submission form you can either use the load function or the submit function.

3.1 load

The load function allows you to bind fields of the consent object to input fields of your <form> and to automatically record the consent at submit time.

Note: the load function must only be invoked after the declaration of the form object (as can be seen in the example below).

We suggest inserting the <script> tag after the <form> tag as follows:

<form>
    <!-- Your form input fields -->
    <input type="submit" name="submit_button" />
</form>

<script type="text/javascript">
    _iub.cons_instructions.push(["load",
        {
            submitElement: document.getElementById("submit_button"), // if this line is missing, the consent is not automatically recorded at submit time; a call to _iub.cons.sendData (see section below) is needed instead
            form: {
                ...your form object
            },
            consent: {
                legal_notices: [{
                    identifier: "terms",
                    version: "1"
                }]
            }
        }
    ])
</script>

Parameters:

Name Required Type Notes
submitElement no DOM element Select an element that will trigger the submit of the consent, when clicked. If this element is not specified, or not triggered, you need to call _iub.cons.sendData() to record the consent (see also below).
form No/Yes if consent is not defined FormConfig Check the form object section
consent No/Yes if form is not defined ConsentConfig Check the consent object section
writeOnLocalStorage no boolean Defines whether the data should be sent directly or written in localStorage. Defaults to: true
autodetect_ip_address no boolean A parameter that enable or disable the ip autodetect. Default to: true

The code in the example above will automatically record the consent object with the values of the bound input fields:

  • when the submitElement receives a click event (if submitElement was specified); or
  • when the _iub.cons.sendData() function gets manually called (see below)

3.1.1 sendData

The sendData function must be used in conjunction with the load function and triggers the recording of the consent object with the values of the input fields that have been bound by a prior call to the load function.

It must be used in case the submitElement is not provided (eg. when you need to validate the input form before submitting) and you need to programmatically trigger the fetching of the data from the form and the consequent recording of the consent.

// your form handler function
function validateForm() {
    if (isValidForm()) {
        // the form has been validated
  	_iub.cons.sendData();
  	// ...
     }
}

3.1.2 sendFromLocalStorage

By default, the consent object created by the load function is not directly sent to our servers for storage; it is indeed saved into the localStorage in order to protect from any loss of data in case a new page is loaded before the JavaScript has finished executing. The consent saved into localStorage will be automatically recorded (that is, sent to our servers for storage) at the very next page load.

If you want to disable the automatic sending of the consent saved in localStorage at page load, you need to provide the parameter sendFromLocalStorageAtLoad = false inside the init object configuration; in such cases, in order to sent the consent stored in localStorage to our servers you’ll need to explicitly call the _iub.cons.sendFromLocalStorage function (see below).

_iub.cons.sendFromLocalStorage()

3.2 submit

The submit function allows you to send the consent data to iubenda APIs, that is to record the consent, programmatically (for example inside an event handler or a callback function):

// An example of .submit scenario: inside the init callback function
$("#submit-btn").click(function(e) {
    e.preventDefault();
    // Synchronous call, it's sent immediately when this function is executed
    _iub.cons_instructions.push(["submit", {... your configuration object(see the examples below)},
      {
        success: function(response) {
          console.log(response);
        }, 
        error: function(response) {
          console.log(response);
        }
      }
    ])
 });

It can be configured in two ways:

  • Specifying the form selector parameter in the same way as the load function
  • By specifying all the values of the consent object

It’s worth noting that, unlike the load function, by default the submit function does not leverage the localStorage and instead directly sends the consent object to our server for storage.

Parameters:

Name Required Type Notes
form No/Yes if consent is not defined FormConfig (See the form object section below)
consent No/Yes if form is not defined ConsentConfig (See the consent object section below)
writeOnLocalStorage No boolean Defines whether the data should be sent directly or written to localStorage. Default to: false
autodetect_ip_address No boolean Allows you to enable or disable the ip autodetect. Default to: true
Note

In cases where you provide both the form and the consent parameter, they will be merged to create the consent object. In cases where there is a conflict between data retrieved from the form and the data specified directly in the consent object, the consent object will take precedence.

Callbacks

The .success callback is called in cases of success, the .error callback is called in cases of error.

3.2.1 When the form object is provided

In the example below (where the form object is provided), the submit function will take care of populating the consent object from the form inputs.

_iub.cons_instructions.push(["submit",
{
    form: {"... your form object"},
    consent: {
      legal_notices: [{
        identifier: "terms",
        version: "1"
      }]
    }
},
{
    success: function(response) {
      console.log(response);
    },
    error: function(response) {
      console.log(response);
    }
}
])

3.2.2 When the form object is not provided

Alternatively, you can also pass the consent object as shown the example below:

_iub.cons_instructions.push(["submit",
  {
    consent: {
      subject: {
        id: "your-subject-id",
        email: "your-subject-email0@example.com"
      },
      preferences: {
        terms: true
      },
      legal_notices: [
        {
          identifier: "privacy_policy"
        }
      ],
      proofs: [
        {
          content: "{ \"first_name\": \"John\", \"last_name\": \"Doe\", \"email\": \"john@example.com\" }"
          form: "<form action=\"/action\" method=\"POST\"><p><label>First Name</label><input type=\"text\" name=\"first_name\" /></p><p><label>Last name</label><input type=\"text\" name=\"last_name\" /></p><p><label>E-mail</label><input type=\"email\" name=\"email\" /></p><input type=\"submit\" /></form>"
        }
      ]
    }
  },
  {
    success: function(response) {
      console.log(response);
    },
    error: function(response) {
      console.log(response);
    }
  }
])

This is an example of a response (in this case a success response) from the server:

200 OK
{
    id: "de801ca9-abec-45e2-8f7c-729822cfffad",
    timestamp: "2018-05-04T14:52:26Z",
    subject_id: "J02eZvKYlo2ClwuJ1"
}

If you want to programmatically build your consent object and send it to the Consent Solution API you’ll need to use the submit function as previously described in 3.2.2 When The Form Object Is Not Provided.

5. FormConfig

This is the structure of the form object passed to load and submit functions:

Name Type Notes
selector DOM element Selector of the form
map Object Object allowing to map consent attributes to specific form fields by their “name” attributes as an alternative to data-cons-x attributes (see example below)
subject Object
id String name attribute of a DOM element present in the form
email String name attribute of a DOM element present in the form
first_name String name attribute of a DOM element present in the form
last_name String name attribute of a DOM element present in the form
full_name String name attribute of a DOM element present in the form
preferences Object
preference_name String name attribute of a DOM element present in the form
exclude Array A list of fields name that we would like to exclude from proofs

5.1 Binding the form fields to your consent object

The form fields can be bound to your consent object in two ways:

1) By specifying the relevant name attribute in the MAP object (please note that id cannot be used here, only the name attribute):

form: {
  selector: document.getElementById("form"), // The selector of the form from which you'd like to detect the data
  map: { // optional: map consent attributes directly to the corresponding
         // input's "name" attribute, instead of using data-cons-x attributes
    subject: {
      id: "id-element-name"
      email: "email-element-name",
      first_name: "first-name-element-name",
      last_name: "last-name-element-name",
      full_name: "full-name-element-name"
    },
    preferences: {
      terms: "terms-checkbox-element-name"
    }
  }
}

2) By using data-cons-x attributes in your input field:

<form>
  <!-- subject -->
  <input type="..." name="subject_name" data-cons-subject-name />
  
    <input type="hidden" name="id" value="12141412" data-cons-subject="id" />
    <p>
        First name:<br/>
        <input type="text" value="value" name="first_name" data-cons-subject="first_name" />
    </p>
    <p>
        Last name:<br/>
        <input type="text" name="last_name" data-cons-subject="last_name" />
    </p>
    <p>
        Full Name:<br/>
        <input type="text" name="full_name" data-cons-subject="full_name" />
    </p>
    <p>
        Email<br/>
        <input type="text" name="email" data-cons-subject="email" />
    </p>
    <p>
        Password<br/>
        <input type="password" name="password" data-cons-exclude />
    </p>
    
    <!-- preferences -->
    <p>
        <label><input type="hidden" name="terms-and-conditions" data-cons-preference="terms-and-conditions" value="value"/> 
        Accept terms and conditions</label>
    </p>
    <p>
        <label><input type="hidden" name="newsletter" value="newsletter" data-cons-preference="newsletter" /> newsletter</label>
    </p>
    <input type="submit" id="submit-btn"/>
</form>

You can also exclude certain fields ( i.e. password or fields not related to the consent) in two ways:

1) By using data-cons-exclude in your input field:

<input type="password" name="password" data-cons-exclude />

2) By using the exclude object inside the map:

map: {
    .
    .
    // exclude fields by inserting inputs names in this array
    exclude: ['password']
}

6. ConsentConfig

The consent object is composed of the following fields:

Name Required Type Notes
timestamp No String ISO 8601 timestamp which marks the time at which the consent occurred. Defaults to current time if not specified
subject Yes Object
id No String Identifier to identify the subject that sent the consent. If an ID is passed that one is used and you can update a subject info by posting new consents using the same subject ID. However if you do not provide a specific subject ID the API will create a secure random UUID for you.
email No String
first_name No String
last_name No String
full_name No String
verified No Boolean Reserved field used to signal whether a subject is verified, for instance via the double opt-in method
legal_notices Yes Array Array of objects containing legal_notices data
identifier No String
version No String Auto-filled if not provided
proofs Yes Array Array of objects containing proof data
content No String
form No String
preferences Yes Object Set of key-value pairs with user preferences for the consent action

Note: In the JS library, all of the properties must be specified from within the consent object. Example:

consent: {
  subject: {
    id: "your-subject-id",
    email: "your-subject-email0@example.com"
  },
  preferences: {
    terms: true
  },
  legal_notices: [
    {
      identifier: "privacy_policy"
    }
   ]},
   proofs: [
    {
      content: "{ \"first_name\": \"John\", \"last_name\": \"Doe\", \"email\": \"john@example.com\" }"
      form: "<form action=\"/action\" method=\"POST\"><p><label>First Name</label><input type=\"text\" name=\"first_name\" /></p><p><label>Last name</label><input type=\"text\" name=\"last_name\" /></p><p><label>E-mail</label><input type=\"email\" name=\"email\" /></p><input type=\"submit\" /></form>"
    }
   ]
}

If you use iubenda for your legal documents, we’ll automatically update the contents of the legal_notices for you whenever your legal documents are changed. You can read about how to enable this feature here.

However it is still required for you to declare which legal_notices are being agreed upon on each consent creation, therefore if you’re using legal notices, you should fill the legal_notices array with the identifier and version of your legal notices created beforehand.

Example:

consent: {
  legal_notices: [
    {
      identifier: "privacy_policy",
      version: "1" // auto-filled if not provided
    },
    {
      identifier: "another_legal_notice"
    },
    ...
  ]
}

8. Implementation examples

Included below are some practical examples of how you can actually implement the Consent Solution.

8.1 MAP feature

Load function

See the Pen [Iubenda Cons] (async) Load function by iubenda (@iubenda) on CodePen.

Load function with Map (no data-attribute)

See the Pen [Iubenda Cons] (async) Load function and Map option by iubenda (@iubenda) on CodePen.

8.2 Submit implementation (async)

See the Pen [Iubenda Cons] (async) Submit implementation by iubenda (@iubenda) on CodePen.

8.3 Multiple Form implementation

See the Pen [Iubenda Cons] (async)Multiple Form implementation by iubenda (@iubenda) on CodePen.

8.4 External validation tools (Load function with validate.js)

See the Pen [Iubenda Cons] (async) load function with validate.js by iubenda (@iubenda) on CodePen.

How to update ConS installations prior to 03/04/2019

If you have installed the iubenda Consent Solution prior to 03/04/2019, in order to use the current version update the usage of the init and load functions to accommodate the new asynchronous loading feature.

The init or load functions can be called in two different scenarios:

  • Before the library has finished loading (asynchronous loading)
  • After the library has finished loading (synchronous loading)

Load

Before:

_iub.cons.load({ ... your options })

After:

_iub.cons_instructions.push(["load", { ... your options }])

Note: this code must be put after your element, ref. to load section above.

Init

Before:

_iub.cons.init({api_key: "YOUR_PUBLIC_API_KEY"}, YOUR_CALLBACK_FUNCTION);

After:

_iub.cons_instructions.push(["init", {api_key: "YOUR_PUBLIC_API_KEY"}, YOUR_CALLBACK_FUNCTION]);

Note: the init function is embedded into your setup script and it should not need any update from you.

See also

Still have questions?

Visit our support forum Email us