Working with cookies

A cookie is a small piece of data that a website asks your browser to store on your computer or mobile device. The cookie allows the website to “remember” your actions or preferences over time.

Xperience provides an extensible framework, built around cookie levels, for manipulating cookies – from assigning specific levels of allowed cookies to users and contacts, to registering custom cookies and their corresponding cookie levels.

A site’s default cookie level determines which cookies the system stores in users’ browsers by default. To set the default cookie level:

  1. Open Settings application and select the System category.
  2. Under the Cookies heading, select a Default cookie level.
  3. Click Save.

The system now uses the selected cookie level when evaluating which cookies should be stored in users’ browsers. 

All cookies level required for On-line marketing features to work correctly in Xperience

Xperience On-line marketing features only work fully for visitors who have their cookie level set to All cookies.

For example, the system does not track contacts for visitors whose allowed cookie level is only System or Essential. Contacts may still be created in certain cases for visitors without the required cookie level, e.g., if they submit data through a form or subscribe to a newsletter, but such contacts only store the provided data and do not track the visitor.

Xperience classifies cookies into several levels according to their purpose. The levels allow you to set cookie levels for users. The following are the default levels available in the cookie API (CMS.Helpers.CookieLevel class):

Cookie level

Description

None (-1000)

Absolutely no cookies are allowed, including the cookie that stores the cookie level selected for users. This makes sense only if you want to disable absolutely every cookie by default.

System (-100)

This level allows the session cookie, and the CookieLevel cookie used to store the cookie level selected by the user. In terms of the end user and the Cookie law, this means “Cookies are not allowed”.

Essential (0)

Cookies required for all website functionality needed by site visitors. This includes authentication, language selection, etc. From the visitor’s perspective, this means “Allow only cookies that I may need, but do not track me”.

Editor (100)

Cookies required for correct administration interface functionality. For example used to track the selected view mode, remember tabs and sliders, etc.

Visitor (200)

All cookies that are not assigned to an explicit level are considered to be cookies identifying the visitor, i.e. user tracking cookies, which are not really needed, but are useful for the site owner if using Xperience Enterprise marketing features.

This level is used for all custom cookies by default. You can register custom cookies to adjust their assigned cookie level.

All (1000)

Allows all cookies, no matter what their level is. From the site visitor’s perspective this means “Allow all cookies now and in the future”.

The numbers associated with each cookie level are integer constants, which allows you to further customize the granularity of available cookie levels. The levels ‘None’ and ‘All’ are set to an absolute value of 1000 to provide enough space for future Xperience updates or developer-specified custom levels.

Automatic tracking of contacts and their activities only works for new visitors if the Default cookie level setting is set to ‘Visitor’ or ‘All’. For more information, see Working with consents.

Automatic cookie consent for administrators and editors

If a user signs in to the Xperience administration interface, cookies are automatically enabled to provide full editing functionality. The system assumes that working in the administration interface identifies the user as staff, so there is no need for cookie consent.

Registering custom cookies

If your website uses any custom or third-party cookies, we recommend that you register them with an appropriate cookie level. Unregistered cookies are processed with the Visitor level by default.

When a visitor adjusts their allowed cookie level (for example by accepting or revoking a consent), the system automatically clears all cookies that have a higher level from the visitor’s browser. You may also encounter problems with custom or third-party cookies not being stored if your site’s System -> Default cookie level setting has a lower value than Visitor, for example when managing tracking consent.

To register custom cookies, you need to add custom code to your project. Call the CookieHelper.RegisterCookie method (available in the CMS.Helpers namespace of the Xperience API), with the following parameters:

  • string name – the name of the cookie that you are registering.
  • int level – an integer value representing the cookie level required to use the cookie. You can access the default level values in the CookieLevel enumeration.

To ensure that your cookies are recognized correctly, call the RegisterCookie method at the beginning of the application’s life cycle – either during the initialization of a custom module class, or within suitable startup code if you are using the Xperience API in an external application.

Handling cookies in ASP.NET Core

When setting cookies in ASP.NET Core projects, there is an option to use the CookieOptions.IsEssential property.




var cookieOptions = new CookieOptions
{
    IsEssential = true
};

// Adds the cookie to the response cookie collection
HttpContext.Response.Cookies.Append("cookieName", "cookieValue", cookieOptions);


Cookies that are not registered by the Xperience CookieHelper are seen as Visitor level cookies by the Xperience system, but the CookieOptions.IsEssential option overrides the system cookie settings as it is handled directly by the framework. As a result, such cookies are always set for visitors, even if they are not registered using the CookieHelper.

Example

The following example demonstrates how to register a custom cookie named CustomCookie with the Essential cookie level:

  1. Open the Xperience live site project in Visual Studio.

  2. Create a custom module class.

    • We recommend adding the class into a custom Class Library project within the solution.
  3. Override the module’s OnInit method and call the CookieHelper.RegisterCookie method.

    
    
    
     using CMS;
    
     using CMS.DataEngine;
     using CMS.Helpers;
    
     // Registers the custom module into the system
     [assembly: RegisterModule(typeof(CustomInitializationModule))]
    
     public class CustomInitializationModule : Module
     {
         // Module class constructor, the system registers the module under the name "CustomInit"
         public CustomInitializationModule()
             : base("CustomInit")
         {
         }
    
         // Contains initialization code that is executed when the application starts
         protected override void OnInit()
         {
             base.OnInit();
    
             // Registers the "CustomCookie" with the 'Essential' cookie level
             // Ensures that the cookie is preserved for visitors who change their allowed cookie level below 'Visitor'
             CookieHelper.RegisterCookie("CustomCookie", CookieLevel.Essential);
         }
     }
    
    
     

The CustomCookie is now registered and can be used by visitors with the Essential and above cookie level (based on your site’s default cookie level, the users’ preferred cookie level, or other custom actions such as consent agreements).

Setting cookies

You can use the Xperience API to create and set custom cookies into a user’s browser. Call the CookieHelper.SetValue method within the scope of an HTTP request:

CookieHelper.SetValue in hotfix 13.0.165 and newer

With version 13.0.165, the following overload of the SetValue method


CookieHelper.SetValue(string name, string value, DateTime expires, string path = null, bool? httpOnly = null, string domain = null, SameSiteMode sameSiteMode = SameSiteMode.Lax, bool secure = false)

was made obsolete and replaced with SetValue(CookieHelperValueSettingParameters parameters). The CookieHelperValueSettingParameters object contains the parameters from the obsolete method and can be used identically, with one exception. CookieHelperValueSettingParameters.Secure is now nullable and null by default, which means Xperience uses the value provided by the framework (false in most cases).


Additionally, the method and all its overloads now reflect the requireSSL web.config attribute on the httpCookies element.


<httpCookies requireSSL="true" />

In older versions, the requireSSL configuration was suppressed by the optional secure attribute of the now-obsolete SetValue method, which defaulted to false unless explicitly set.

Explicitly configuring CookieHelperValueSettingParameters.Secure when setting cookies overrides the web.config value.


using CMS.Helpers;

// Saves a custom cookie named "CustomCookie" to the current visitor's browser,
// with "CustomValue" as its value and an expiration time of 1 year
CookieHelper.SetValue("CustomCookie", "CustomValue", DateTime.Now.AddYears(1));

Cookies set using CookieHelper use the Lax SameSite mode by default. To specify a different SameSite mode, add an additional parameter with a value from the CMS.Base.SameSiteMode enumeration when setting the cookie:


// With hotfix 13.0.164 and older
CookieHelper.SetValue("CustomCookie", "CustomValue", DateTime.Now.AddYears(1), sameSiteMode: SameSiteMode.Strict);

// Adds the Secure attribute to the cookie with 'SameSite=None'. 
// The user agent will include the cookie in an HTTP request only if the request is transmitted over a secure channel (typically HTTPS).
CookieHelper.SetValue("CustomCookie", "CustomValue", DateTime.Now.AddYears(1), sameSiteMode: SameSiteMode.None, secure: true);

// With hotfix 13.0.165 and newer
CookieHelper.SetValue(new CookieHelperValueSettingParameters {
                Name = "CustomCookie",
                Value = "CustomValue",
                Expires = DateTime.Now.AddYears(1),
                SameSiteMode = SameSiteMode.Strict
            });

// Adds the Secure attribute to the cookie with 'SameSite=None'. 
// The user agent will include the cookie in an HTTP request only if the request is transmitted over a secure channel (typically HTTPS).
CookieHelper.SetValue(new CookieHelperValueSettingParameters {
                Name = "CustomCookie",
                Value = "CustomValue",
                Expires = DateTime.Now.AddYears(1),
                SameSiteMode = SameSiteMode.None,
                Secure = true
            });

In compliance with the cookie law, you can allow users to select their preferred cookie level. Use the SetCurrentCookieLevel method provided by the ICurrentCookieLevelProvider service.

The following code snippets demonstrate the usage of the ICurrentCookieLevelProvider API on a basic example. The code allows users to set their preferred cookie level via a simple form.

CookieLevelController.cs



using System.Web.Mvc;
using System.Collections.Generic;

using CMS.Helpers;

public class CookieLevelController : Controller
{
    private readonly ICurrentCookieLevelProvider cookieLevelService;

    // Initializes instances of required services using dependency injection
    public CookieLevelController(ICurrentCookieLevelProvider cookieLevelService)
    {
        this.cookieLevelService = cookieLevelService;
    }

    public ActionResult Index()
    {
        // Creates a list with the three default levels of cookie compliance relevant for site visitors.
        // The CookieLevel class is used to directly extract integer values corresponding to each cookie level
        // so that no additional mapping is necessary.
        var cookieLevels = new List<object>() {
                new { label = "Essential", value = CookieLevel.Essential },
                new { label = "Visitor", value = CookieLevel.Visitor },
                new { label = "All", value = CookieLevel.All }
            };

        return View(new SelectList(cookieLevels, "value", "label"));
    }

    // Sets the cookie level for the current user
    // The value passed into the action from the corresponding view directly corresponds to one of the system's 
    // cookie levels thanks to the CookieLevel class.
    [HttpPost]
    public ActionResult SetCookieLevel(int SelectedValue)
    {
        // Sets the cookie level for the current user to the level corresponding to the provided value
        cookieLevelService.SetCurrentCookieLevel(SelectedValue);

        return RedirectToAction(nameof(Index));
    }
}


The corresponding view contains a drop-down selectors that allows users to select the desired level of cookies.

Index.cshtml



@model SelectList

@using (Html.BeginForm("SetCookieLevel", "CookieLevel", FormMethod.Post))
{
    @Html.DropDownListFor(x => x.SelectedValue, Model)
    <input type="submit" value="Select" />
}