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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions