Skip to content

Commit 914b542

Browse files
cornehoskamgitbook-bot
authored andcommitted
GITBOOK-84: Update cookiebot consent
1 parent 2a392e7 commit 914b542

File tree

2 files changed

+70
-30
lines changed

2 files changed

+70
-30
lines changed

13/umbraco-engage/developers/ab-testing/csharp-api.md

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,69 @@ description: >-
44
Umbraco Engage C# API.
55
---
66

7-
# Retrieving A/B test variants in C#
7+
# Retrieving A/B test variants in C\#
88

99
## Retrieving Active A/B test variants
1010

1111
You can retrieve the active A/B test variants for a visitor in different ways depending on your specific scenario:
1212

13-
* `IAbTestingService.GetCurrentVisitorActiveAbTestVariants()`
14-
* Namespace: `Umbraco.Engage.Web.AbTesting`
15-
* Returns the active variants for the current visitor on the current page.
16-
* Can only be used with an active request context
1713
* `IAbTestingVisitorService.GetVisitorAbTestVariants(visitorExternalId, pageId, culture, contentTypeId)`
18-
* Namespace: `Umbraco.Engage.Business.AbTesting`
14+
* Namespace: `Umbraco.Engage.Infrastructure.AbTesting.Services.Interfaces`
1915
* Retrieves active A/B test variants on a specific page, without requiring a request context.
2016
* The visitor external id can be retrieved using `IAnalyticsVisitorExternalIdHandler.GetExternalId()`
2117
* `IAbTestVisitorToVariantManager.GetActiveVisitorVariants(visitorExternalId)`
22-
* Namespace: `Umbraco.Engage.Business.AbTesting`
18+
* Namespace: `Umbraco.Engage.Infrastructure.AbTesting`
2319
* Retrieves _all_ active A/B test variants for the given visitor throughout the website.
2420
* The visitor external id can be retrieved using `IAnalyticsVisitorExternalIdHandler.GetExternalId()`
2521

26-
### Example
22+
### Example - Getting the A/B test variants for the current visitor
2723

28-
To use these services, inject the specified service into your code. The example below uses `IAbTestingService.GetCurrentVisitorActiveAbTestVariants()` by injecting the service into a controller:
24+
This example demonstrates how to create a service that retrieves the active A/B test variants for a specific visitor, content, and culture variation. The service wraps the `IAbTestingVisitorService.GetVisitorAbTestVariants()` method, using the current HttpContext and UmbracoContext to obtain the visitor ID and requested content.
2925

3026
```cs
31-
using Umbraco.Engage.Business.AbTesting;
32-
using Umbraco.Engage.Web.AbTesting;
27+
using Umbraco.Cms.Core.Models.PublishedContent;
28+
using Umbraco.Cms.Core.Web;
29+
using Umbraco.Engage.Infrastructure.AbTesting.Models;
30+
using Umbraco.Engage.Infrastructure.AbTesting.Services.Interfaces;
31+
using Umbraco.Engage.Infrastructure.Analytics.Collection.Visitor;
3332

34-
public class YourController : SurfaceController
33+
namespace Umbraco.Example;
34+
35+
public class ExampleService
3536
{
36-
public YourController(IAbTestingService abTestingService)
37+
private readonly IHttpContextAccessor _httpContextAccessor;
38+
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
39+
private readonly IAnalyticsVisitorExternalIdHandler _externalIdHandler;
40+
private readonly IAbTestingVisitorService _abTestingVisitorService;
41+
42+
public ExampleService(
43+
IHttpContextAccessor httpContextAccessor,
44+
IUmbracoContextAccessor umbracoContextAccessor,
45+
IAnalyticsVisitorExternalIdHandler externalIdHandler,
46+
IAbTestingVisitorService abTestingVisitorService)
47+
{
48+
_httpContextAccessor = httpContextAccessor;
49+
_umbracoContextAccessor = umbracoContextAccessor;
50+
_externalIdHandler = externalIdHandler ;
51+
_abTestingVisitorService = abTestingVisitorService;
52+
}
53+
54+
/// <summary>
55+
/// Gets the active A/B test variants for the current visitor.
56+
/// </summary>
57+
/// <returns>Active <see cref="AbTestVariant"/>s for the visitor, or an empty list if unavailable.</returns>
58+
public IEnumerable<AbTestVariant> GetCurrentVisitorActiveAbTestVariants()
3759
{
38-
var activeVariantsCurrentVisitor = abTestingService.GetCurrentVisitorActiveAbTestVariants();
60+
if (_httpContextAccessor?.HttpContext is not HttpContext httpCtx ||
61+
_externalIdHandler.GetExternalId(httpCtx) is not Guid externalId)
62+
return [];
63+
64+
if (!_umbracoContextAccessor.TryGetUmbracoContext(out var umbCtx) ||
65+
umbCtx.PublishedRequest?.Culture is not string culture ||
66+
umbCtx.PublishedRequest?.PublishedContent is not IPublishedContent content)
67+
return [];
68+
69+
return _abTestingVisitorService.GetVisitorAbTestVariants(externalId, content.Id, culture, content.ContentType.Id);
3970
}
4071
}
4172
```

13/umbraco-engage/security-and-privacy/gdpr/how-to-become-gdpr-compliant-using-cookiebot.md

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The rest of the code is deserializing the JSON string stored inside the cookie f
2828
```cs
2929
using System.Text.Json;
3030
using System.Text.Json.Serialization;
31+
using System.Text.RegularExpressions;
3132
using System.Web;
3233
using Umbraco.Engage.Infrastructure.Permissions.ModulePermissions;
3334

@@ -56,7 +57,7 @@ namespace Umbraco.Engage.StarterKit.CookieBot
5657
return IsAllowed(context, "preferences");
5758
}
5859

59-
private bool IsAllowed(HttpContext context, string cookiePermission)
60+
public bool IsAllowed(HttpContext context, string cookiePermission)
6061
{
6162
// C# Code from CookieBot to check for their cookie
6263
// https://www.cookiebot.com/en/developer/#h-server-side-usage
@@ -81,34 +82,41 @@ namespace Umbraco.Engage.StarterKit.CookieBot
8182
return false;
8283
}
8384

84-
private bool CheckCookieBotValue(string rawCookieBotConsentValues, string cookiePermissionToCheck)
85+
public bool CheckCookieBotValue(string rawCookieBotConsentValues, string cookiePermissionToCheck)
8586
{
8687
// Read current user consent in encoded JSON
8788
// Sample JSON cookie payload
8889
/*
89-
{
90-
"stamp": "Ov4gD1JVnDnBaJv8K2wYQlyWlnNlT/AKO768tibZYdQGNj/EolraLw==",
91-
"necessary": true,
92-
"preferences": true,
93-
"statistics": true,
94-
"marketing": true,
95-
"method": "explicit",
96-
"ver": 1,
97-
"utc": 1698057791350,
98-
"region": "gb"
99-
}
90+
* {
91+
* stamp:'Ov4gD1JVnDnBaJv8K2wYQlyWlnNlT/AKO768tibZYdQGNj/EolraLw==',
92+
* necessary:true,
93+
* preferences:false,
94+
* statistics:true,
95+
* marketing:false,
96+
* method:'explicit',
97+
* ver:1,
98+
* utc:1698057791350,
99+
* region:'gb'
100+
* }
100101
*/
101102

102103
// Decode the consent string
103-
var decodedConsent = HttpUtility.UrlDecode(rawCookieBotConsentValues);
104+
var rawDecodedConsent = HttpUtility.UrlDecode(rawCookieBotConsentValues);
104105

105-
if(decodedConsent == null)
106+
if(rawDecodedConsent == null)
106107
{
107108
return false;
108109
}
110+
111+
// Because the CookieBot consent cookie is not actually valid JSON, we need to do some preprocessing.
112+
// Step 1: Quote property names (e.g., stamp → "stamp")
113+
var consentStep1 = Regex.Replace(rawDecodedConsent, @"(?<={|,)\s*(\w+)\s*:", m => $"\"{m.Groups[1].Value}\":");
114+
115+
// Step 2: Replace single-quoted string values with double quotes
116+
var consentStep2 = Regex.Replace(consentStep1, @"'([^']*)'", "\"$1\"");
109117

110118
// Deserialize the consent to a dynamic object
111-
var cookieBotConsentValues = JsonSerializer.Deserialize<CookieBotConsent>(decodedConsent);
119+
var cookieBotConsentValues = JsonSerializer.Deserialize<CookieBotConsent>(consentStep2);
112120
if (cookieBotConsentValues == null)
113121
{
114122
// Something went wrong with the cookieConsent deserialization
@@ -142,6 +150,7 @@ namespace Umbraco.Engage.StarterKit.CookieBot
142150
public bool Necessary { get; set; }
143151

144152
[JsonPropertyName("preferences")]
153+
145154
public bool Preferences { get; set; }
146155

147156
[JsonPropertyName("statistics")]

0 commit comments

Comments
 (0)