This specification extends the [[TPE]] to achieve the following:

This document is an editors' straw man reflecting a snapshot of live discussions within the Tracking Protection Working Group . It does not necessarily constitute working group consensus. This draft has been prepared using the DNT Github repository and its associated issues list. However, see the previous issue tracking system for working group decisions prior to 2017. See for a summary of changes since the first Candidate Recommendation.

Introduction

The GDPR requires that the identity of origin server is discoverable by web users, and the [[TPE]] supports this by enabling every origin server to identify itself by hosting a Tracking Status Resource (TSR) at the /.well-known/dnt/ location. This specification further requires that the information presented to a user before they agreed to a Tracking Exception, i.e. gave their informed consent for the collection and further processing of personal data derived from on-line activity, is permanently determinable from the TSR. As cookie headers SHOULD be present in the TSR request, servers can use them, or an identifier encoded in the DNT header as described in this specification, to determine what purposes the user has agreed to, and present them in a human-readable document pointed to by a new "purposes" TSR property. As cookies may not always be available to third-party requests the DNT encoded identifier could be a more reliable way to do it.

As well as introducing universal mechanisms for delivering machine-readable transparency information, and conveying a signal indicating individuals consent or otherwise for tracking in the DNT request header, the [[TPE]], via the Site-Specific Tracking Exception, introduced the ability to communicate this consent signal efficiently to embedded third-parties. Publishers can use this to signal immediately to third-parties when users have given consent, and the reverse when consent expires or is withdrawn. Under the GDPR consent must be "specific", meaning this signal must be capable of being selectively delivered to those parties to which the user has given their agreement, and this is supported by the API by allowing DNT:0 only to be sent to named embedded third-parties. Furthermore, when the user withdraws their consent, or has never given it, the opted-in/opted-out indication is restricted to a particular site - opting-out does not have to apply to the whole web, as it does when only standard third-party HTTP cookies are available.

Although a single boolean, indicating consent/no-consent, can be delivered this way, i.e. site-specifically via the DNT header, there is currently no way to do this similarly for data. HTTP cookies are intrinsically web-wide, once stored they will always be included in resource requests, whether to embedded third-parties or to first-party websites. The privacy concerns arising from this has led to cookies being increasingly blocked in third-party requests, either by the browser or by user action. Even when they are available users are much less likely to give their consent to tracking when there is no guarantee it will be constrained to one site, or a defined subset of sites. This means that if the user has agreed to site-specific tracking, say within a publishers first-party site, the persisted information has to recorded in a first-party cookie and communicated to embedded third-parties somehow. Even if this can be done in a scalable way, for example by editing the target URL with a mutually agreed encoding, the third-party could not persist it in one of its own cookies, because even if cookies were not blocked the tracking data would then be available web-wide, i.e on any site which embedded the same third-party.

This specification describes the ability for first-parties to efficiently communicate site-specific values to embedded third-party servers, but only after the user has agreed to a site-specific Tracking Exception indicating consent. This value is communicated to server in the DNT request header, and to their associated browsing contexts in the navigator.doNotTrack property.The data would be immediately available to the third-party server within the request, so there would be no need for additional round-trip delays. Like cookies, it would be available in all requests to the domain, i.e. not just to particular resources, and it would not need to be separately persisted. The value could be encoded by first-party script at any time, for any purpose for which then user had agreed, and there would be no need for the logistically complex and inefficient mechanisms needed for user-specific URL editing. The value is only transmitted to, or available to, first-party or embedded third-party servers in the context of a single site, or defined subset of the web, and this could be readily and externally verified.

As further security measures this value would only be settable when the registering API call is made within a user gesture, similar to the way the WebKit [[StorageAPI]] requestStorageAccess() is constrained, and only when the request is secure, i.e. delivered over https.

Browsers SHOULD support an ability to indicate to the user when a DNT header is carrying a site-specific value, say in the browser chrome. How this information interacts with browser specific anti-tracking features is left to browser vendors.

The Tracking Exception API has been extended to support the ability of servers to register a site-specific Tracking Exception value of "1", useful in situations where a user has not configured their browser with a general Tracking Preference, and servers are legally required to support a signal to indicate the right-to-object, for example under the GDPR's Article 21.5.'

Notational Conventions

Requirements

The key words must, must not, required, should, should not, recommended, may, and optional in this specification are to be interpreted as described in [[!RFC2119]].

Formal Syntax

This specification uses the Augmented Backus-Naur Form (ABNF) notation of [[!RFC5234]] to define network protocol syntax and WebIDL [[!WebIDL-20161215]] to define scripting APIs. Conformance criteria and considerations regarding error handling are defined in Section 2.5 of [RFC7230].

How to throw a DOMexception and the exceptions named "InvalidStateError", "SecurityError", and "SyntaxError" are defined in [[!WebIDL-20161215]].

Promise objects are defined in [[ECMASCRIPT]]; the phrases promise-call, resolve promise, reject promise, upon fulfillment, and upon rejection are used in accordance with [[PromiseGuide]].

Expressing a Tracking Preference

Expression Format

When a user has enabled a tracking preference, that preference needs to be expressed to all mechanisms that might perform or initiate tracking.

When enabled, a tracking preference is expressed as either:

DNT meaning
1 This user prefers not to be tracked on this request.
0 This user prefers to allow tracking on this request.

A user agent MUST NOT send a tracking preference expression if a tracking preference is not enabled. This means that no expression is sent for each of the following cases:

In the absence of regulatory, legal, or other requirements, servers MAY interpret the lack of an expressed tracking preference as they find most appropriate for the given user, particularly when considered in light of the user's privacy expectations and cultural circumstances. Likewise, servers might make use of other preference information outside the scope of this protocol, such as site-specific user preferences or third-party registration services, to inform or adjust their behavior when no explicit preference is expressed via this protocol.

DNT Header Field for HTTP Requests

The DNT header field is a mechanism for expressing the user's tracking preference in an HTTP request ([[!RFC7230]]). At most one DNT header field can be present in a valid request.

            DNT-field-name  = "DNT"
            DNT-field-value = ( "0" DNT-Consent / "1" )
            DNT-Consent = %x21-7E ; excludes CTL, SP
            

A user agent MUST NOT generate a DNT header field if the user's tracking preference is not enabled.

A user agent MUST generate a DNT header field with a field-value that begins with the numeric character "1" if the user's tracking preference is enabled, their preference is for DNT:1, and no exception has been granted for the target resource (see ).

A user agent MUST generate a DNT header field with a field-value that begins with the numeric character "0" if the user's tracking preference is enabled and their preference is for DNT:0, or if an exception has been granted for the target resource.

A proxy MUST NOT generate a DNT header field unless it has been specifically installed or configured to do so by the user making the request and adheres to the above requirements as if it were a user agent.

GET /something/here HTTP/1.1
Host: example.com
DNT: 1

JavaScript Property to Detect Preference

The navigator.doNotTrack property enables a client-side script with read access to the Navigator object [[!HTML51]] to determine what DNT header field value would be sent to the effective script origin, taking into account the user's general preference (if any) and user-granted exceptions applicable to the target domain when referenced by the active document's top-level browsing context.

        partial interface Navigator {
            readonly attribute DOMString? doNotTrack;
        };
      

The value is null if no DNT header field would be sent (e.g., because a tracking preference is not enabled and no user-granted exception is applicable); otherwise, the value is a string beginning with "0" or "1", possibly followed by DNT-extension characters.

Specifically, the value of Navigator.doNotTrack for a given script is either null or the string value that would be sent in a DNT field-value () in a request to a target resource at the effective script origin (the current document.domain of the script's responsible document) when that request is due to an embedded reference from this site (the document.domain of the top-level browsing context's active document).

Ideally, the value of navigator.doNotTrack ought to reflect the current set of user-granted exceptions in effect when the attribute is read.

User-Granted Exceptions

Client-side Scripting API

API to Store a Tracking Exception

When a site has obtained consent for a user-granted exception, or a user has indicated their objection to lawfully exempted tracking when their tracking preference is not enabled, a script running within an active browsing context or nested browsing context of that site can promise-call Navigator.storeTrackingException to store one or more tracking exceptions. A TrackingExData object is supplied as a parameter to define the exception's scope (the set of [site, target] duplets that encompass the granted exception) and optional information to be stored for that exception. The call returns a promise which either resolves to a TrackingExResult or is rejected with a DOMException identifying the reason for the failure.

        partial interface Navigator {
            Promise<TrackingExResult> storeTrackingException (
              TrackingExData properties
            );
        };
        dictionary TrackingExData {
           DOMString? site;
           sequence<DOMString>? targets;
           DOMString? name;
           DOMString? explanation;
           DOMString? details;
           long?      maxAge;
           DOMString  fieldValue;
        };
        dictionary TrackingExResult {
          boolean isSiteWide;
        };
        

Navigator.storeTrackingException passes a TrackingExData object. A user agent MUST ignore unknown properties of the TrackingExData object (for future extensibility). The following OPTIONAL properties are defined:

site
The referring domain scope for which the exception applies:
  • If site is undefined, null, or the empty string, the exception's referring domain scope defaults to the script domain.
  • If site is defined and equal to "*", the exception is intended to be web-wide< for the set of targets. A user agent MUST reject the promise with the DOMException named "SecurityError" if both site and any of the targets are "*".
  • Otherwise, the exception's referring domain scope is defined by a domain found in site that is treated in the same way as the domain parameter to cookies [[!RFC6265]], allowing subdomains to be included with the prefix "*.". The value can be set to a fully-qualified right-hand segment of the document host name, up to one level below TLD.
targets
An array of target domains for which the exception applies:
  • If targets is undefined or null, the user-granted exception to be stored is [site, *], meaning that the exception applies to all domains referenced by the site.
  • If targets is an empty array, the user-granted exception to be stored is [site, script domain], meaning that the exception applies only to resources that share the same domain as the effective script origin.
  • Otherwise, for each domain string in the targets array, a user-granted exception to be stored is the duplet [site, domain].
name
When defined and not null or an empty string, name is a user-readable string for naming the exception, usually descriptive of the targets or their intended purpose for this site.
explanation
When defined and not null or an empty string, explanation is a user-readable short explanation of the granted exception.
details
When defined and not null or an empty string, details is a URI reference at which further information about the granted exception can be found [[!RFC3986]].
maxAge
When defined and not null, maxAge is a positive number of seconds indicating the maximum lifetime of the grant:
  • If maxAge is supplied and not null, empty, or negative, the user agent MUST remove the stored exception no later than the specified number of seconds after being stored.
  • If maxAge is not supplied, the user agent MAY retain the stored grant indefinitely.
fieldValue
When defined and not null or an empty string, fieldValue indicates the field-value of the DNT header to be sent to all domains for which this exception applies. Only a field-value consisting of either the single character "1", or a string whose first character is "0" and which complies with the definition of a DNT-Consent value, is valid. A string whose first character is "0" can only be registered via this call when the browser is processing a user gesture in which user has given their informed consent, AND the Tracking Exception requested is site-specific (i.e. the site property is not "*"), AND the call is being executed within a secure top-level browsing context. For all other string values, or the executing browsing context is not secure, or the site property is "*", or the browser is not executing a user gesture, the user agent MUST NOT store the exception, and MUST reject the promise with a DOMException named "SyntaxError".
  • If fieldValue is equal to "1" the user agent must send a DNT header with the field-value set to "1" for all requests to domains for which this exception applies; or
  • If the first character of fieldValue is "0", the executing context is top-level, secure and processing a user gesture, and the rest of the string is a valid DNT-Consent value, the user agent MUST send a DNT header with the field-value set to fieldValue for all requests to domains for which this exception applies; or
  • If fieldValue is not defined, null or the empty string the user agent MUST send a DNT header with the field-value set to "0" for all requests to domains for which this exception applies; or
  • If fieldValue is any other value then the user agent MUST NOT store an exception and MUST reject the promise with a DOMException named "SyntaxError".

The properties name, explanation, and details are provided by the caller for the sake of potential user interfaces. If a user agent presents these properties to the user, it ought to be clear that they are provided for informational value and are less important than the exception's technical effect.

In addition to the data above, a user agent might also store ambient information about the call, such as the URI associated with the top-level browsing context, the effective script origin, a current timestamp, or other information potentially obtained from applicable tracking status resources.

The calling script domain MUST have a site-wide tracking status resource with a valid tracking status representation that includes a policy property. This allows a user agent to obtain and possibly store additional information about the caller’s controller and tracking policies at the time an exception is granted.

A user agent MAY reject the promise with a DOMException named "InvalidStateError" if it cannot determine the effective script origin or if the site corresponding to that origin does not have a site-wide tracking status resource with a valid tracking status representation.

For each site-specific exception being stored, a user agent MUST NOT store the duplets and MUST reject the promise with a DOMException named "SecurityError" if the script would not be able to set a cookie on that duplet's referring domain scope following the cookie domain rules [[!RFC6265]].

For example, a script on www.foo.bar.example.com can set the site as "bar.example.com" or "example.com", but not to "something.else.example.com" or "com".

For each web-wide exception being stored, a user agent MUST NOT store the duplets and MUST reject the promise with a DOMException named "SecurityError" if the script would not be able to set a cookie on that target domain following the cookie domain rules [[!RFC6265]]. This limits storing of a web-wide exception to scripts that share the same domain scope as the exception targets, but allows such scripts to be embedded within iframes of a common consent portal.

For any other failure, such as an incorrectly formatted parameter in the TrackingExData, the user agent MUST NOT store any of the target duplets in the database and MUST reject the promise with a DOMException named "SyntaxError".

Upon fulfillment, the user agent has added to its local database one or more site-pair duplets [site, target], each indicating that a request from that site domain to the target domain will include DNT:0 regardless of the user's general tracking preference. The fulfilled promise object contains the following TrackingExResult attribute:

isSiteWide
true if the user agent stored a potentially broader exception that applies to all domains (as opposed to just the listed targets); otherwise, false.

When a list of targets is supplied for a site-specific exception, the user agent MAY ignore that list, choosing instead to store a site-specific exception for all domains ([site, *]), if it also indicates that result by setting the returned promise's isSiteWide property to true.

User agents MAY instantiate Navigator.storeTrackingException even when Navigator.doNotTrack is null. Scripts SHOULD test for the existence of Navigator.storeTrackingException before calling the method.

There are some security concerns here regarding the ability of a script with an effective script origin matching one site being able to persist the DNT value received by resources on other (target) sites. In particular, this feature could be abused to set/unset an array of exceptions, similar to an array of bit values, and be "read" as a persistent identifier by embedding requests to those domains (which might all point to the same Internet host). However, we expect that would leave an obvious trail on the user agent, unlike other sources of fingerprinting.

Likewise, allowing an exception to be stored within an iframe of another site's page could be ripe for abuse unless the calling script ensures that it is being run within a page where it expects to be collecting user consent and where the context of that consent is consistent with the exceptions being stored.

This design is consistent with the fact that there is no technical restraint from sites calling the API without having first obtained an informed consent from the user. We are assuming that the social and regulatory environment will be sufficient to punish those who might misuse the API or abuse the scope of stored exceptions. A user agent might further limit such risks by checking for a site-wide tracking status resource when its presence is required by the API.

Communicating a Tracking Status

Tracking Status Representation

For each tracking status resource, an origin server MUST provide a valid representation using the application/tracking-status+json media type. This media type consists of a status object serialized as JSON [[!RFC7159]]. More information about the application/tracking-status+json media type can be found in .

Status Object

A tracking status representation consists of a single status object containing properties that describe the tracking status applicable to the designated resource. Most of the properties are optional and can be extended over time, as illustrated by the following Orderly schema [[Orderly]]:

object {
    string tracking;                 // TSV
    array { string; } compliance?;   // hrefs
    string qualifiers?;              // compliance flags
    array { string; } controller?;   // hrefs
    array { string; } same-party?;   // domains
    array { string; } audit?;        // hrefs
    string policy?;                  // href
    string config?;                  // href
    string purposes?;                // href
}*;

The following example representation demonstrates a status object with all of the properties defined by this specification.

{
  "tracking": "T",
  "compliance": ["https://acme.example.org/tracking101"],
  "qualifiers": "afc",
  "controller": ["https://www.example.com/privacy"],
  "same-party": [
    "example.com",
    "example_vids.net",
    "example_stats.com"
  ],
  "audit": [
    "http://auditor.example.org/727073"
  ],
  "policy": "/privacy.html#tracking",
  "config": "http://example.com/your/data"
}

Purposes Property

An origin server MAY send a property named purposes with a string value containing a URI reference to a human-readable document that describes each of the purposes for tracking implemented by this origin server.

If the origin server supports the DNT-Consent qualifier then this property MUST be supported and be dynamically generated by decoding the field-value of the request's DNT header, to highlight or otherwise indicate the specific subset of purpose the user has agreed to.

Privacy Considerations

Fingerprinting

Information communicated via the DNT header field is minimized to avoid abuse of the field for fingerprinting or as a side-channel. However, the DNT-Consent extension allows for the sending of additional information when signaling consent for tracking via DNT:0, and could be used to send persistent state information without the user's knowledge. For this reason browsers MUST NOT register a DNT-Consent value when the browsing context is insecure, the Navigator.storeTrackingException call is for a web-wide Tracking Exception, or was not processed in the context of a user gesture. Servers MUST ensure that a DNT-Consent value is only used when the user has given their consent.

Browsers SHOULD support an ability to indicate to the user in the browser chrome when a DNT header is carrying a DNT-Consent extension.