EU Cookie Legislation and Umbraco

Introduction to law: There has been a lot of talks about EU Cookie legislation on websites. Everybody that does websites probably got at least few call from clients with questions and requests to make their websites comply. Cookie legislation also changed in the meantime which confused some. In short, what we have been getting from our client (UK client!) and their lawyers is:

There are 4 cookie categories, in broad terms:

  • Strictly necessary cookies (make the website work so no opt-in required)
  • Performance cookies (includes analytics – opt-in required)
  • Functionality cookies (remembering visitor actions etc. – opt-in required)
  • Targeting or Advertising cookies (self-explanatory – opt-in required)

The first does not require an opt-in and no’s 2 & 3 do not require a proper opt-in according to the ICC guide, with only the targeting/advertising cookies requiring the ‘tick-box’ option or similar.

One thing remains interpreted differently among our clients and that is if “Implied consent” is acceptable (for 2 & 3 at least). This means that after displaying opt-in popup message to visitors, if they ignore it and click any other link on website, this is interpreted as “implied consent” to accept cookies (and opt-in popup states that!).

What we needed to do

In short, what was requested from us was:

  1. Add “Cookie policy” page where you list exactly which cookies you use and why (do Cookie survey of website prior to this!)
  2. “Strictly necessary cookies” for a service requested by user (like .NET session cookies) can be listed on cookie privacy page but you do not need to block those
  3. Cookies that contain personal data and/or are NOT necessary for service requested by user (like Google Analytics) must get visitor’s consent to be stored!
  4. Implement implied consent

In most of our cases, only Google Analytics cookies were an issue to deal with.

Technical solution

Idea is simple. On first visit to our website we check if cookieOptIn cookie is set on visitor’s browser. If it is not set, it means visitor is here for the first time and we need to display a cookie opt-in message (we also store value “1” to the cookie now). If cookie cookieOptIn exists, we check it’s value. Value can be “2” (cookies accepted), “0” cookies refused. Depending on that value, we output Google Analytics code or not.

If cookieOptIn exists and value is “1”, as stated above this means it is a new visitor which still hasn’t opted in nor out. For clients that want “implicit consent” to be applied on their websites, we do one more check. We check if cookieOptIn is “1” AND if they came here through internal link (we check referral server variable and compare domain names). In this case we set cookieOptIn value to “2” which is the same as opting in.

Previously, we also used JavaScript for this functionality but adding/removing Google Analytics code on client side is not optimal (happens after complete page is loaded and our code executed). For Umbraco we decided to do it in Razor macro.

@helper lounchPopup() {
    <script type="text/javascript">
    jQuery(document).ready(function($) {
    $('body').append('<div id="cookiesOptInMessage">@Html.Raw(@Dictionary["cookiesOptInMessage"].Replace(Environment.NewLine, "").Replace("'", "\'"))</div>');
    });
    </script>
    string customStylesheet = String.IsNullOrEmpty(Parameter.customStylesheet) ? "" : "<link href="/css/cookiesOptIn.css" rel="stylesheet" type="text/css" />"; 
    @Html.Raw(@customStylesheet)
}

@{

  HttpCookie cookieOptIn = Request.Cookies.Get("cookieOptIn");

    @* cookie not set, set it to 1 (first time visitor) and popup message *@
    if(cookieOptIn == null) {
        cookieOptIn = new HttpCookie("cookieOptIn");
        cookieOptIn .Value = "1";
        cookieOptIn .Expires = DateTime.Now.AddDays(30);
        Response.Cookies.Add(cookieOptIn);
        @lounchPopup()

    } else {
        @* check if "optOut" button was clicked *@
        if (@Request.QueryString["cookieOptOut"] == "1") {
            cookieOptIn .Value = "0";
            cookieOptIn .Expires = DateTime.Now.AddDays(30);
            Response.Cookies.Add(cookieOptIn);
        } else {

              switch(cookieOptIn.Value){
                  @* cookie contains 1 (visitor was here before)
                    check if user clicked some link (referer) or it was an old cookie *@
                  case "1":
                      if (@umbraco.library.RequestServerVariables("HTTP_REFERER").ToLower().Replace("https://","").StartsWith(@umbraco.library.RequestServerVariables("HTTP_HOST").ToLower())) {
                        cookieOptIn .Value = "2";
                        cookieOptIn .Expires = DateTime.Now.AddDays(30);
                        Response.Cookies.Add(cookieOptIn);
                        @Dictionary["GoogleAnalyticsCode"]
                      } else {
                        @lounchPopup()
                      }
                      break;

                  @* cookie contains 2 (visitor allowed cookies). Continue as usual. Output GA code. *@
                  case "2":
                      @Dictionary["GoogleAnalyticsCode"]
                      break;

                  @* cookie contains 0 (visitor disallowed cookies). Continue without GA code output *@
                  case "0":
                      break;
              }
        }
    }

}

Notes on implementation

  • Macro should be put in master template, right where Google Analytics code is outputed, just before closing of HEAD tag.
  • macro parameter “customStylesheet” (true/false) is used. If set, Macro will also use stylesheet “/css/cookiesOptIn.css” where you can store CSS to format opt-in message, or you can set it to false and do it in your main CSS.
  • Macro uses dictionary items: GoogleAnalyticsCode (to store GA code) and cookiesOptInMessage (to store HTML of the opt-in message)
  • Inside cookiesOptInMessage you can use links to refuse cookies (in example <a href="?cookieOptOut=1">refuse</a>) or to accept cookies/continue (in example <a href="?">accept</a>)

Code is a bit messy but more than usable. Feel free to use it.

NET Media international services ltd. (NET Media međunarodne usluge d.o.o.) | OIB: 39220099203 | VAT ID: HR39220099203
Raiffeisenbank Austria d.d. Petrinjska 59, 10000 Zagreb | ŽR: 2484008-1106011288 | SWIFT: RZBHHR2X | IBAN: HR0224840081106011288
HQ: Starčevićeva 2 | Office: Kopilica 5 | 21000 Split | Republic of Croatia | T: +385 21 782 706 | F: +385 21 782 704
Registered at the Commercial Court of Split, under the No: Tt-11/5859-2 | MBS: 060277288 | Share capital 373.000,00 kn paid in whole | Board member: Mato Božić

NET Media international services ltd. (NET Media međunarodne usluge d.o.o.) | OIB: 39220099203 | VAT broj: HR39220099203
Raiffeisenbank Austria d.d. Petrinjska 59, 10000 Zagreb | ŽR: 2484008-1106011288 | SWIFT: RZBHHR2X | IBAN: HR0224840081106011288
Sjedište: Starčevićeva 2 | Ured: Kopilica 5 | 21000 Split | Republika Hrvatska | T: +385 21 782 706 | F: +385 21 782 704
Društvo je upisano u registar Trgovačkog suda u Splitu pod brojem: Tt-11/5859-2 | MBS: 060277288 | Temeljni kapital društva 373.000,00 kn uplaćen u cijelosti | Član uprave: Mato Božić

Contact us today!

You are here for a reason. Let’s talk.

Contact us