Skip to content

TcfCaV1 decode: purposes off-by-one and special features never displayed #6

@FastFlorian

Description

@FastFlorian

Description

When decoding a TcfCaV1 (TCF Canada) GPP section on [iabgpp.com], two fields display incorrect values:

  • Purpose [2] "Use limited data to select advertising" shows as not set (should be true for full consent)
  • SpecialFeature [1] and [2] show as not set (should be true for full consent)

The @iabgpp/cmpapi library decodes correctly -- the bugs are in the website's decode.js UI code.

Reproduction

Paste this full-consent GPP string into the decoder:

DBABDA~BQhtCJ2QhtCJ2GEABAENCyCf_v-AAP-AAAvrBRAAUAA0ADgAKgAWgA0ACGAEsAKAAXQAzABtADuAH6AQQBCACKAEoAJ0AT4ArYBbgFwAMoAaYA5wB3AEAgJKAkwBOwCfgGKAM0AZ0Az4BrwDiAHVAP4AiYBJ4CVAE5AJ_AUeAqIBUoC3gFwgLoAXuAv8Bg4DMAGggNHAaaA2oBuIDjQHLAPEAeaA-QCAgEJAI3AR_AlKBKqCYAJggTVAmuBOYCfgFJgKWAVOAqsBYQC0QF2wL6gu3ApAAUABwAGgAQwAzABtADuAH4AQgAigBWgDKAHOAO4AgABJQCfgGKAOIAiYBOQCjwFRAKlAXQAv8BmADRwGmgOWAfIBAQCVUEwATBAnMBPwClgFTgLCAWiAu2AA.YAAAAAAAAAA

Expected: All purposes 2-10 and special features 1-2 selected.

Actual: Purpose 2 unselected, special features 1-2 unselected.

Verified with raw binary decode and [UniConsent GPP Decoder] which shows correct results.

Bug 1: Purposes off-by-one (src/js/app/decode.js ~line 230)

The CA GVL has 9 purposes starting at ID 2 (Purpose 1 is unused in TCF Canada). The <select> options are:

  • options[0] = "[2] Use limited data to select advertising"
  • options[1] = "[3] Create profiles..."

But PurposesExpressConsent is a 24-element boolean array where index 0 = Purpose 1:

  • values[0] = false (Purpose 1 -- unused)
  • values[1] = true (Purpose 2)

The loop uses i as index into both:

for (let i = 0; i < select.length; i++) {
  let option = select[i];
  if (i < values.length) {
    option.selected = values[i] === true;
  }
}

So options[0] (labeled "Purpose 2") reads values[0] (Purpose 1 = false) -- shown as unselected.

Fix: Use the option's value to index into the array:

for (let i = 0; i < select.length; i++) {
  let option = select[i];
  let idx = parseInt(option.value) - 1;
  option.selected = idx < values.length && values[idx] === true;
}

Same issue applies to PurposesImpliedConsent (~line 245).

Bug 2: Special features never displayed (src/js/app/decode.js ~line 228)

document.getElementById("tcfcav1-special-feature-express-consent").checked =
  cmpApi.getFieldValue("tcfcav1", "SpecialFeatureExpressConsent");

The element is a <select multiple>, not a checkbox. Setting .checked on a <select> does nothing -- special features are never visually selected.

Fix: Iterate over options like purposes:

let values = cmpApi.getFieldValue("tcfcav1", "SpecialFeatureExpressConsent");
let select = document.getElementById("tcfcav1-special-feature-express-consent");
for (let i = 0; i < select.length; i++) {
  let option = select[i];
  let idx = parseInt(option.value) - 1;
  option.selected = idx < values.length && values[idx] === true;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions