Module: Data protection
8 of 13 Pages
Hide builder content from visitors who have not consented to tracking
The activity tracking documentation explains that Xperience logs the Form submit activity automatically, even for users who have not consented to tracking. As the page notes, this means you need to ensure that usage of personal data collected through such activities falls under legitimate interest purposes.
To avoid potential legal complications, you may want to display certain forms only to users who have consented to tracking.
Let’s go over the process of creating a Page Builder section which hides its contents from users who have not given consent for tracking. The code you develop will add an alternate version of the existing Form column section included in the training guides repository.
Edit the view model
This form section needs to execute complex logic and change its behavior accordingly, so you should base it on a view component.
A view component will allow you to pass your own model to the section, rather than relying on the ComponentViewModel<TPropertyModel> object Xperience provides for basic sections.
You need to create this view model before you can use it in the view component.
- Navigate to TrainingGuides.Web/Features/Shared/Sections/FormColumn/FormColumnSectionViewModel.cs.
- Add a boolean field to represent whether the form section should render its content.
- Add three
string
fields to hold a message that will display when visitors have not consented to tracking, along with the text and URL of a link to the cookie policy page.
The SectionAnchor
property corresponds to a property of the same name from the existing FormColumnSectionProperties class. It lets editors specify the value of an id
attribute added to the HTML <section>
tag that wraps the contents of the FormColumnSection.
namespace TrainingGuides.Web.Features.Shared.Sections.FormColumn;
public class FormColumnSectionViewModel
{
public bool ShowContents { get; set; }
public string SectionAnchor { get; set; } = string.Empty;
public string NoConsentMessage { get; set; } = string.Empty;
public string NoConsentLinkText { get; set; } = string.Empty;
public string NoConsentLinkUrl { get; set; } = string.Empty;
}
Alter the view
Next, you need to account for the new ShowContents
and NoConsentHtml
properties of the FormColumnSectionViewModel
in the view.
- Navigate to TrainingGuides.Web/Features/Shared/Sections/FormColumn/FormColumnSection.cshtml.
- Add a conditional that only shows the view’s contents if the
ShowContents
property of the model istrue
, and otherwise renders the no-consent message and link.
@using TrainingGuides.Web.Features.Shared.Sections.FormColumn
@model FormColumnSectionViewModel
@if(Model.ShowContents)
{
var sectionAnchor = !string.IsNullOrWhiteSpace(Model.SectionAnchor) ? $"id={Model.SectionAnchor}" : "";
<section class="c-section form" @sectionAnchor>
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8">
<widget-zone />
</div>
</div>
</div>
</section>
}
else
{
<div>
@Model.NoConsentMessage
</div>
<div>
<a href="@Model.NoConsentLinkUrl">@Model.NoConsentLinkText</a>
</div>
}
Handle the view components
Create a new view component
Earlier in this series, you saw how you can use the value of the CMSCookieLevel cookie to determine whether the current visitor is trackable. Then, you created a method called CurrentContactCanBeTracked
to determine whether or not Xperience should track the current user.
If you arrived directly at this example or did not code along earlier in the series, you can simply add this method to your cookie consent service:
...
// Use dependency injection to populate this service.
private readonly ICurrentCookieLevelProvider cookieLevelProvider;
...
/// <summary>
/// Checks if the current contact's CMSCookieLevel is All (1000) or higher
/// </summary>
/// <returns>True if CMSCookieLevel is greater than or equal to 1000, false otherwise</returns>
public bool CurrentContactCanBeTracked() =>
cookieLevelProvider.GetCurrentCookieLevel() >= 1000;
...
You can use this method in a new view component to create a view model and pass it along to the view.
Start by creating a new view component called FormColumnSectionConsentViewComponent.cs to the TrainingGuides.Web/Features/Shared/Sections/FormColumn folder.
- Use dependency injection to get instances of the following:
ICookieConsentService
IStringLocalizer<SharedResources>
IHttpRequestService
IHttpContextAccessor
- Set the
Invoke
method to take aComponentViewModel<FormColumnSectionProperties>
object as a parameter.Xperience will supply this object automatically. You can use it to access properties configured by editors from theInvoke
method. - Use
sectionProperties.Properties.SectionAnchor
to populate the corresponding view model property. - Set the
ShowContents
property totrue
based on theCurrentContactCanBeTracked
method of the cookie consent service, or if the site is in Preview or Page Builder mode. - Set the message to display when the section is hidden, and configure the properties for the link prompting visitors to visit the cookie policy page and consent to tracking.
- Define an identifier and use it to register the view component as a Page Builder section.
using CMS.Base.Internal;
using Kentico.Content.Web.Mvc;
using Kentico.PageBuilder.Web.Mvc;
using Kentico.Web.Mvc;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using TrainingGuides.Web.Features.DataProtection.Services;
using TrainingGuides.Web.Features.Shared.Sections.FormColumn;
using TrainingGuides.Web.Features.Shared.Services;
[assembly: RegisterSection(
identifier: FormColumnSectionConsentViewComponent.IDENTIFIER,
viewComponentType: typeof(FormColumnSectionConsentViewComponent),
name: "Form column: Consent-based",
propertiesType: typeof(FormColumnSectionProperties),
Description = "Form column section that hides its contents if the visitor has not consented to tracking.",
IconClass = "icon-square")]
namespace TrainingGuides.Web.Features.Shared.Sections.FormColumn;
public class FormColumnSectionConsentViewComponent : ViewComponent
{
public const string IDENTIFIER = "TrainingGuides.FormColumnSectionConsent";
private readonly ICookieConsentService cookieConsentService;
private readonly IStringLocalizer<SharedResources> stringLocalizer;
private readonly IHttpRequestService httpRequestService;
private readonly IHttpContextAccessor httpContextAccessor;
public FormColumnSectionConsentViewComponent(ICookieConsentService cookieConsentService,
IStringLocalizer<SharedResources> stringLocalizer,
IHttpRequestService httpRequestService,
IHttpContextAccessor httpContextAccessor)
{
this.cookieConsentService = cookieConsentService;
this.stringLocalizer = stringLocalizer;
this.httpRequestService = httpRequestService;
this.httpContextAccessor = httpContextAccessor;
}
public IViewComponentResult Invoke(ComponentViewModel<FormColumnSectionProperties> sectionProperties)
{
var httpContext = httpContextAccessor.HttpContext;
bool showContents = cookieConsentService.CurrentContactCanBeTracked() // Display if the visitor has consented to tracking.
|| httpContext.Kentico().PageBuilder().GetMode() != PageBuilderMode.Off // Display if the page is in Page Builder mode.
|| httpContext.Kentico().Preview().Enabled; // Display if the page is in Preview mode.
var cookiePolicyUrlBuilder = new UriBuilder(httpRequestService.GetBaseUrlWithLanguage());
cookiePolicyUrlBuilder.Path = httpRequestService.CombineUrlPaths(cookiePolicyUrlBuilder.Path, "cookie-policy");
var model = new FormColumnSectionViewModel()
{
SectionAnchor = sectionProperties.Properties.SectionAnchor,
ShowContents = showContents,
NoConsentMessage = stringLocalizer["The content of this section includes tracking functionality. To view it, please consent to Marketing cookies."],
NoConsentLinkText = stringLocalizer["Configure cookies"],
NoConsentLinkUrl = cookiePolicyUrlBuilder.ToString()
};
return View("~/Features/Shared/Sections/FormColumn/FormColumnSection.cshtml", model);
}
}
Tweak the existing section
Now that you’ve added new properties to hide the section’s contents, you need to make sure this only happens for the consent-based version.
Adjust the existing FormColumnSectionViewComponent.cs file to account for the new ShowContents
property of the view model.
...
public IViewComponentResult Invoke(ComponentViewModel<FormColumnSectionProperties> sectionProperties)
{
var model = new FormColumnSectionViewModel()
{
SectionAnchor = sectionProperties.Properties.SectionAnchor,
ShowContents = true
};
return View("~/Features/Shared/Sections/FormColumn/FormColumnSection.cshtml", model);
}
...
Add an identifier
Now, in case the identifier of the new consent-based component needs to be accessed externally, add it to the component identifiers file.
Add a new constant to the Sections
class in TrainingGuides.Web/ComponentIdentifiers.cs that references the constant from the view component.
...
public static class ComponentIdentifiers
{
public static class Sections
{
...
public const string FORM_COLUMN_CONSENT = FormColumnSectionViewComponent.IDENTIFIER;
...
}
...
}
See the result
You have implemented a layout and logic that displays or hides content on the website depending on a visitor tracking consent. In order to see it in action, you need to use it on a page.
Run your project locally, login to the administration interface, and navigate to the Training guides pages channel.
Click Edit → Create new version to edit the Contact-us page.
Set Page Builder to use the Form column: Consent-based section, then Save and Publish the web page.
Now pretend that you are a visitor and navigate to your website in a browser’s incognito window. Visit the Cookie policy page, set the cookie level to essential and then visit your Contact us page. The section should not display.
Go back to the Cookie policy page, change your consent to Marketing and revisit Contact us page. If you’ve implemented the functionality properly, you’ll see the form displayed on the page.
Your site now includes a section with a powerful custom logic. Your website editors can use the new section to hide forms on the website from specific visitors. But they are not limited to just forms. They can hide any custom widgets which might lead to, for example, a GDPR compliance breach if displayed for all the visitors.