Building your own CMP¶
The Usercentrics SDK allows you to build a fully compliant CMP of your own. For this, we have provided an API that provides all the data and action delegates needed.
Be aware that there are implementation differences between each legal framework, due to divergent legal requirements.
General Data Protection Regulation (GDPR)¶
The European Union's General Data Protection Regulation applies to any business in the EU as well as organizations outside the EU that collect, process and store information on EU citizens, as well as non-citizens residing in the EU.
To get you started, we have provided a compliance checklist to help you understand the requirements of a GDPR CMP.
Data Source¶
UsercentricsCore.isReady { status in
let data = UsercentricsCore.shared.getCMPData()
let settings = data.settings
let services = data.services
let categories = data.categories
} onFailure: { error in
// Handle non-localized error
}
Usercentrics.isReady({
val data = Usercentrics.instance.getCMPData()
val settings = data.settings
val services = data.services
val categories = data.categories
}, { error ->
// Handle non-localized error
})
Matching Categories and Services
You may match services to categories with category.slug
== service.categorySlug
.
Content Mapping¶
To help you navigate our Data Source, please see the following content mapping tables:
CMP Component | SDK Property |
---|---|
1. Title | settings.labels.firstLayerTitle |
2. Description | settings.bannerMessage |
3. Short Description | settings.bannerMobileDescription |
4. Read More | settings.labels.btnBannerReadMore |
5. Privacy Policy Text | settings.labels.privacyPolicyLinkText |
6. Privacy Policy URL | settings.privacyPolicyUrl |
7. Imprint Text | settings.labels.imprintLinkText |
8. Imprint URL | settings.imprintUrl |
9. Language Selected | settings.language |
10. Languages Available | settings.languagesAvailable |
11. Categories Tab | settings.secondLayer.tabsCategoriesLabel |
12. Services Tab | settings.secondLayer.tabsServicesLabel |
13. Accept All | settings.labels.btnAcceptAll |
14. Deny All | settings.labels.btnDeny |
15. Save Services | settings.labels.btnSave |
Category Component | SDK Property |
---|---|
16. Category Name | category.label |
17. Category Description | category.description |
Services Component | SDK Property |
---|---|
18. Service Name | service.dataProcessor |
19. Service Description Title | settings.labels.descriptionOfService |
20. Service Description | service.descriptionOfService |
21. Processing Company Title | settings.labels.processingCompanyTitle |
22. Processing Company | service.nameOfProcessingCompany + service.addressOfProcessingCompany |
23. Data Purposes Title | settings.labels.dataPurposes |
24. Data Purposes Description | settings.labels.dataPurposesInfo |
25. Data Purposes | service.dataPurposesList |
26. Technologies Used Title | settings.labels.technologiesUsed |
27. Technologies Used Description | settings.labels.technologiesUsedInfo |
28. Technologies Used | service.technologyUsed |
29. Data Collected Title | settings.labels.dataCollectedList |
30. Data Collected Description | settings.labels.dataCollectedListInfo |
31. Data Collected | service.dataCollectedList |
32. Legal Bases Title | settings.labels.legalBasisList |
33. Legal Bases Description | settings.labels.legalBasisInfo |
34. Legal Bases | service.legalBasisList |
35. Processing Location Title | settings.labels.locationOfProcessing |
36. Processing Location | service.locationOfProcessing |
37. Retention Period Title | settings.labels.retentionPeriod |
38. Retention Period | service.retentionPeriodDescription |
39. Third Country Distribution Title | settings.labels.transferToThirdCountries |
40. Third Country Distribution | service.thirdCountryTransfer |
41. Data Recipients Title | settings.labels.dataRecipientsList |
42. Data Recipients | service.dataRecipientsList |
43. Privacy Policy Title | settings.labels.policyOf |
44. Privacy Policy | service.privacyPolicyURL |
45. Cookie Policy Title | settings.labels.cookiePolicyInfo |
46. Cookie Policy | service.cookiePolicyURL |
47. Opt Out Link Title | settings.labels.optOut |
48. Opt Out Link | service.optOutUrl |
49. History Title | settings.labels.history |
51. History | service.consent.history |
52. History Consent Given | settings.labels.yes |
53. History Consent Not Given | settings.labels.no |
54. History Explicit Consent | settings.labels.explicit |
55. History Implicit Consent | settings.labels.implicit |
56. Controller ID | status.controllerId (isReady) |
Action Delegates¶
In order to collect consent, we have provided the following 3 functions:
Accept All¶
let consents = UsercentricsCore.shared.acceptAll(consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.acceptAll(consentType = <UsercentricsConsentType>)
Deny All¶
let consents = UsercentricsCore.shared.denyAll(consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.denyAll(consentType = <UsercentricsConsentType>)
Save¶
For granular selection, you may pass specific sets of consent with an array of decisions:
let consents = UsercentricsCore.shared.saveDecisions(decisions: <[UserDecision]>, consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.saveDecisions(decisions = <[UserDecision]>, consentType = <UsercentricsConsentType>)
Consent Type
The consent type should be based on if a customer made an explicit action to provide consent, or not. Implicit can be used if the user ignores or skips the CMP. We highly recommend you only use implicit together with the denyAll()
method, which will accept only essential services.
Transparency & Consent Framework (TCF 2.0)¶
The Interactive Advertising Bureau, (IAB Europe) has created the GDPR Transparency and Consent Framework (TCF 2.0) to support publishers, technology vendors and advertisers in being compliant with EU’s GDPR and ePrivacy Directive.
Be aware that a validation process with the IAB is required, in order to become a licensed TCF 2.0 CMP provider.
IAB Data Source¶
UsercentricsCore.isReady { status in
// CMP Data
let data = UsercentricsCore.shared.getCMPData()
let settings = data.settings
let tcfSettings = settings.tcf2
// TCF Data
let tcfData = UsercentricsCore.shared.getTCFData()
let purposes = tcfData.purposes
let specialPurposes = tcfData.specialPurposes
let features = tcfData.features
let specialFeatures = tcfData.specialFeatures
let stacks = tcfData.stacks
let vendors = tcfData.vendors
// TCString
let tcString = UsercentricsCore.shared.getTCString()
} onFailure: { error in
// Handle non-localized error
}
Usercentrics.isReady({
// CMP Data
val data = Usercentrics.instance.getCMPData()
val settings = data.settings
val tcfSettings = settings.tcf2
// TCF Data
val tcfData = Usercentrics.instance.getTCFData()
val purposes = tcfData.purposes
val specialPurposes = tcfData.specialPurposes
val features = tcfData.features
val specialFeatures = tcfData.specialFeatures
val stacks = tcfData.stacks
val vendors = tcfData.vendors
// Non-TCF Data - if you have services not included in IAB
val services = data.services
val categories = data.categories
// TCString
val tcString = Usercentrics.instance.getTCString()
}, { error ->
// Handle non-localized error
})
Non-IAB Data Source¶
UsercentricsCore.isReady { status in
let data = UsercentricsCore.shared.getCMPData()
let settings = data.settings
let services = data.services
let categories = data.categories
} onFailure: { error in
// Handle non-localized error
}
Usercentrics.isReady({
val data = Usercentrics.instance.getCMPData()
val settings = data.settings
val services = data.services
val categories = data.categories
}, { error ->
// Handle non-localized error
})
Matching Categories and Services
You may match services to categories with category.slug
== service.categorySlug
.
Content Mapping¶
First Layer | SDK Property |
---|---|
1. First layer title | tcf2.firstLayerTitle |
2. First layer description | tcf2.firstLayerDescription |
3. First layer additional Info | tcf2.firstLayerAdditionalInfo |
4. First layer resurface note | tcf2.firstLayerNoteResurface |
5. Vendorlist link title | tcf2.linksVendorListLinkLabel |
6. Manage settings link title | tcf2.linksManageSettingsLabel |
7. Label purposes | tcf2.labelsPurposes |
8. Label features | tcf2.labelsFeatures |
Second Layer | SDK Property |
---|---|
1. Second layer title | tcf2.secondLayerTitle |
2. Second layer description | tcf2.secondLayerDescription |
3. Purposes tab | tcf2.tabsPurposeLabel |
4. Vendors tab | tcf2.tabsVendorsLabel |
5. Vendors who are part of TCF | tcf2.labelsIabVendors |
6. Vendors who are NOT part of TCF | tcf2.labelsNonIabVendors |
7. Non IAB purposes | tcf2.labelsNonIabPurposes |
Buttons | SDK Property |
---|---|
1. Accept all button title | tcf2.buttonsAcceptAllLabel |
2. Deny all button title | tcf2.buttonsDenyAllLabel |
3. Save button title | tcf2.buttonsSaveLabel |
General | SDK Property |
---|---|
1. Language Selected | settings.language |
2. Languages Available | settings.languagesAvailable |
3. Privacy Policy Text | settings.labels.privacyPolicyLinkText |
4. Privacy Policy URL | settings.privacyPolicyUrl |
5. Imprint Text | settings.labels.imprintLinkText |
6. Imprint URL | settings.imprintUrl |
Toggles | SDK Property |
---|---|
1. Toggle consent label | tcf2.togglesConsentToggleLabel |
2. Toggle legitimate interest label | tcf2.togglesLegIntToggleLabel |
Vendors | SDK Property |
---|---|
1. Label title | vendor.name |
2. Purpose label | tcf2.vendorPurpose |
3. Purpose Name | vendor.purposes[n].[findByPurposeId].name |
4. Legitimate interest purpose label | tcf2.vendorLegitimateInterestPurposes |
5. Legitimate Interest Purpose name | vendor.legitimateInterestPurposes[n].[findByPurposeId].name |
6. Special purpose label | tcf2.vendorSpecialPurposes |
7. Special purpose name | vendor.specialPurposes[n].[findByPurposeId].name |
8. Feature label | tcf2.vendorFeatures |
9. Feature name | vendor.features[n].[findByPurposeId].name |
10. Special Feature label | tcf2.vendorSpecialFeatures |
11. Special Feature name | vendor.specialFeatures[n].[findByPurposeId].name |
12. Cookie refresh value | vendor.cookieRefresh |
13. Cookie Age value | vendor.cookieMaxAgeSeconds |
14. Cookie storage value | vendor.usesCookie |
15. Non-cookie storage value | vendor.usesNonCookieAccess |
Purposes | SDK Property |
---|---|
1. Label title | purpose.name |
2. Legitimate interest consent | purpose.legitimateInterestConsent |
3. Legal Description | purpose.descriptionLegal |
4. Purpose Description | purpose.purposeDescription |
5. Consent | purpose.consent |
Special Purposes | SDK Property |
---|---|
1. Label title | specialPurpose.name |
2. Legal Description | specialPurpose.descriptionLegal |
3. Purpose Description | purpose.purposeDescription |
Features | SDK Property |
---|---|
1. Label title | feature.name |
2. Legitimate interest consent | feature.legitimateInterestConsent |
3. Legal Description | feature.descriptionLegal |
Special Features | SDK Property |
---|---|
1. Label title | specialFeature.name |
2. Consent | specialFeature.consent |
3. Description | specialFeature.purposeDescription |
4. Legal Description | specialFeature.descriptionLegal |
Stacks | SDK Property |
---|---|
1. Label title | stack.name |
3. Description | stack.description |
3. Purposes | stack.purposeIds |
4. Special Features | stack.specialFeatureIds |
Set CMP ID¶
When building your own TCF 2.0 CMP, it is required to have your CMP UI design certified by the IAB. Once certified, you will need to provide your CMP ID as follows:
UsercentricsCore.shared.setCMPId(id: <ID>)
Usercentrics.instance.setCMPId(<ID>)
Action Delegates¶
In order to collect consent, we have provided the following 3 functions:
Accept All¶
let consents = UsercentricsCore.shared.acceptAllForTCF(fromLayer: <TCFDecisionUILayer>, consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.acceptAllForTCF(fromLayer = <TCFDecisionUILayer>, consentType = <UsercentricsConsentType>)
Deny All¶
let consents = UsercentricsCore.shared.denyAllForTCF(fromLayer: <TCFDecisionUILayer>, consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.denyAllForTCF(fromLayer = <TCFDecisionUILayer>, consentType = <UsercentricsConsentType>)
Save¶
For granular selection, you may pass specific sets of consent with an array of TCFUserDecisions
.
let consents = UsercentricsCore.shared.saveDecisionsForTCF(tcfDecisions: <[TCFUserDecisions]>,
fromLayer: <TCFDecisionUILayer>,
serviceDecisions: <[UserDecision]>,
consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.saveDecisionsForTCF(
tcfDecisions = <[TCFUserDecisions]>,
fromLayer = TCFDecisionUILayer.FIRST_LAYER,
serviceDecisions = <[UserDecision]>,
consentType = <UsercentricsConsentType>
)
TCF 2.0 Decision Layer
Depending on your design, you might have 1 or 2 layers for collecting consent. It is required by the IAB, that you specify in which layer the consent was collected. For this, you may pass the corresponding enum value from TCF_DECISION_UI_LAYER
.
Consent Type
The consent type should be based on if a customer made an explicit action to provide consent, or not. Implicit can be used if the user ignores or skips the CMP. We highly recommend you only use implicit together with the denyAllForTCF()
method, which will accept only essential services.
California Consumer Privacy Act (CCPA)¶
The California Consumer Privacy Act of 2018 (CCPA) gives consumers more control over the personal information that businesses collect about them and provide guidance on how to implement the law. This landmark law secures new privacy rights for California consumers, including:
- The right to know about the personal information a business collects about them and how it is used and shared;
- The right to delete personal information collected from them (with some exceptions);
- The right to opt-out of the sale of their personal information; and
- The right to non-discrimination for exercising their CCPA rights.
Businesses are required to give consumers certain notices explaining their privacy practices. The CCPA applies to many businesses, including data brokers.
Data Source¶
UsercentricsCore.isReady { status in
let data = UsercentricsCore.shared.getCMPData()
let settings = data.settings
let services = data.services
let categories = data.categories
} onFailure: { error in
// Handle non-localized error
}
Usercentrics.isReady({
val data = Usercentrics.instance.getCMPData()
val settings = data.settings
val services = data.services
val categories = data.categories
}, { error ->
// Handle non-localized error
})
Matching Categories and Services
You may match services to categories with category.slug
== service.categorySlug
.
Content Mapping¶
CMP Component | SDK Property |
---|---|
1. Title | ccpa.firstLayerTitle |
2. Description | ccpa.appFirstLayerDescription |
3. Short Description | ccpa.firstLayerMobileDescription |
4. Read More | settings.labels.btnBannerReadMore |
5. Privacy Policy Text | settings.labels.privacyPolicyLinkText |
6. Privacy Policy URL | settings.privacyPolicyUrl |
7. Imprint Text | settings.labels.imprintLinkText |
8. Imprint URL | settings.imprintUrl |
9. Language Selected | settings.language |
10. Languages Available | settings.languagesAvailable |
11. Categories Tab | settings.secondLayer.tabsCategoriesLabel |
12. Services Tab | settings.secondLayer.tabsServicesLabel |
13. Do not sell my info label | ccpa.optOutNoticeLabel |
14. Save button | ccpa.btnSave |
Category Component | SDK Property |
---|---|
16. Category Name | category.label |
17. Category Description | category.description |
Services Component | SDK Property |
---|---|
18. Service Name | service.dataProcessor |
19. Service Description Title | settings.labels.descriptionOfService |
20. Service Description | service.descriptionOfService |
21. Processing Company Title | settings.labels.processingCompanyTitle |
22. Processing Company | service.nameOfProcessingCompany + service.addressOfProcessingCompany |
23. Data Purposes Title | settings.labels.dataPurposes |
24. Data Purposes Description | settings.labels.dataPurposesInfo |
25. Data Purposes | service.dataPurposesList |
26. Technologies Used Title | settings.labels.technologiesUsed |
27. Technologies Used Description | settings.labels.technologiesUsedInfo |
28. Technologies Used | service.technologyUsed |
29. Data Collected Title | settings.labels.dataCollectedList |
30. Data Collected Description | settings.labels.dataCollectedListInfo |
31. Data Collected | service.dataCollectedList |
32. Legal Bases Title | settings.labels.legalBasisList |
33. Legal Bases Description | settings.labels.legalBasisInfo |
34. Legal Bases | service.legalBasisList |
35. Processing Location Title | settings.labels.locationOfProcessing |
36. Processing Location | service.locationOfProcessing |
37. Retention Period Title | settings.labels.retentionPeriod |
38. Retention Period | service.retentionPeriodDescription |
39. Third Country Distribution Title | settings.labels.transferToThirdCountries |
40. Third Country Distribution | service.thirdCountryTransfer |
41. Data Recipients Title | settings.labels.dataRecipientsList |
42. Data Recipients | service.dataRecipientsList |
43. Privacy Policy Title | settings.labels.policyOf |
44. Privacy Policy | service.privacyPolicyURL |
45. Cookie Policy Title | settings.labels.cookiePolicyInfo |
46. Cookie Policy | service.cookiePolicyURL |
47. Opt Out Link Title | settings.labels.optOut |
48. Opt Out Link | service.optOutUrl |
49. History Title | settings.labels.history |
51. History | service.consent.history |
52. History Consent Given | settings.labels.yes |
53. History Consent Not Given | settings.labels.no |
54. History Explicit Consent | settings.labels.explicit |
55. History Implicit Consent | settings.labels.implicit |
56. Controller ID | status.controllerId (isReady) |
Action Delegates¶
CCPA is a global opted out framework. This means:
- Consent is a boolean, no granular consent of services.
- The consent is given by default and the user has to explicitly opt-out.
To collect consent for CCPA, we offer one simplified method:
Saving Consent¶
let ccpaConsents = UsercentricsCore.shared.saveOptOutForCCPA(isOptedOut: <Bool>, consentType: <UsercentricsConsentType>)
val ccpaConsents = Usercentrics.instance.saveOptOutForCCPA(isOptedOut = <Bool>, consentType = <UsercentricsConsentType>)
Consent Type
The consent type should be based on if a customer made an explicit action to provide consent, or not. Implicit can be used if the user ignores or skips the CMP.
Brazil’s Lei Geral de Proteção de Dados (LGPD)¶
LGPD applies to any business or organization that processes the personal data of people in Brazil, regardless of where that business or organization itself might be located. So, if your company has any customers or clients in Brazil, you should begin preparing for LGPD compliance.
If you are already GDPR compliant, then you have already done the bulk of the work necessary to comply with LGPD. It is only necessary that you set the appropaite Legal Basis for all your services.
Data Source¶
UsercentricsCore.isReady { status in
let data = UsercentricsCore.shared.getCMPData()
let settings = data.settings
let services = data.services
let categories = data.categories
} onFailure: { error in
// Handle non-localized error
}
Usercentrics.isReady({
val data = Usercentrics.instance.getCMPData()
val settings = data.settings
val services = data.services
val categories = data.categories
}, { error ->
// Handle non-localized error
})
Matching Categories and Services
You may match services to categories with category.slug
== service.categorySlug
.
Content Mapping¶
CMP Component | SDK Property |
---|---|
1. Title | settings.labels.firstLayerTitle |
2. Description | settings.bannerMessage |
3. Short Description | settings.bannerMobileDescription |
4. Read More | settings.labels.btnBannerReadMore |
5. Privacy Policy Text | settings.labels.privacyPolicyLinkText |
6. Privacy Policy URL | settings.privacyPolicyUrl |
7. Imprint Text | settings.labels.imprintLinkText |
8. Imprint URL | settings.imprintUrl |
9. Language Selected | settings.language |
10. Languages Available | settings.languagesAvailable |
11. Categories Tab | settings.secondLayer.tabsCategoriesLabel |
12. Services Tab | settings.secondLayer.tabsServicesLabel |
13. Accept All | settings.labels.btnAcceptAll |
14. Deny All | settings.labels.btnDeny |
15. Save Services | settings.labels.btnSave |
Category Component | SDK Property |
---|---|
16. Category Name | category.label |
17. Category Description | category.description |
Services Component | SDK Property |
---|---|
18. Service Name | service.dataProcessor |
19. Service Description Title | settings.labels.descriptionOfService |
20. Service Description | service.descriptionOfService |
21. Processing Company Title | settings.labels.processingCompanyTitle |
22. Processing Company | service.nameOfProcessingCompany + service.addressOfProcessingCompany |
23. Data Purposes Title | settings.labels.dataPurposes |
24. Data Purposes Description | settings.labels.dataPurposesInfo |
25. Data Purposes | service.dataPurposesList |
26. Technologies Used Title | settings.labels.technologiesUsed |
27. Technologies Used Description | settings.labels.technologiesUsedInfo |
28. Technologies Used | service.technologyUsed |
29. Data Collected Title | settings.labels.dataCollectedList |
30. Data Collected Description | settings.labels.dataCollectedListInfo |
31. Data Collected | service.dataCollectedList |
32. Legal Bases Title | settings.labels.legalBasisList |
33. Legal Bases Description | settings.labels.legalBasisInfo |
34. Legal Bases | service.legalBasisList |
35. Processing Location Title | settings.labels.locationOfProcessing |
36. Processing Location | service.locationOfProcessing |
37. Retention Period Title | settings.labels.retentionPeriod |
38. Retention Period | service.retentionPeriodDescription |
39. Third Country Distribution Title | settings.labels.transferToThirdCountries |
40. Third Country Distribution | service.thirdCountryTransfer |
41. Data Recipients Title | settings.labels.dataRecipientsList |
42. Data Recipients | service.dataRecipientsList |
43. Privacy Policy Title | settings.labels.policyOf |
44. Privacy Policy | service.privacyPolicyURL |
45. Cookie Policy Title | settings.labels.cookiePolicyInfo |
46. Cookie Policy | service.cookiePolicyURL |
47. Opt Out Link Title | settings.labels.optOut |
48. Opt Out Link | service.optOutUrl |
49. History Title | settings.labels.history |
51. History | service.consent.history |
52. History Consent Given | settings.labels.yes |
53. History Consent Not Given | settings.labels.no |
54. History Explicit Consent | settings.labels.explicit |
55. History Implicit Consent | settings.labels.implicit |
56. Controller ID | status.controllerId (isReady) |
Action Delegates¶
In order to collect consent, we have provided the following 3 functions:
Accept All¶
let consents = UsercentricsCore.shared.acceptAll(consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.acceptAll(consentType = <UsercentricsConsentType>)
Deny All¶
let consents = UsercentricsCore.shared.denyAll(consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.denyAll(consentType = <UsercentricsConsentType>)
Save¶
For granular selection, you may pass specific sets of consent with an array of decisions:
let consents = UsercentricsCore.shared.saveDecisions(decisions: <[UserDecision]>, consentType: <UsercentricsConsentType>)
val consents = Usercentrics.instance.saveDecisions(decisions = <[UserDecision]>, consentType = <UsercentricsConsentType>)
Consent Type
The consent type should be based on if a customer made an explicit action to provide consent, or not. Implicit can be used if the user ignores or skips the CMP. We highly recommend you only use implicit together with the denyAll()
method, which will accept only essential services.