Updating your default Consent Texts

A mailer, member database, and so much more, for digital activism.

Updating your default Consent Texts

If you are unfamiliar with how Identity (and Speakout) represent and configure consents, it is recommended that you read the documentation on User Consent in these systems before proceeding:

This document runs through the process of updating Consents. This is easiest through a more concrete example, so for the purposes of this document we will assume an organisation has two primary consents:

  1. A privacy policy, which users implicitly consent to by using the organisations website and submitting their data
  2. An opt-in to being contacted by email, which a user must explicitly give consent to when submitting data, via a radio button, checkbox, or other means

In this document we will tackle how to update both of these, dealing with the changes required in Identity, Speakout, and Controlshift (if you are using Controlshift).

Important Note: The exact consents required by organisations will be different. What follows is just an example for demonstration. There may be specific legislation which you need to consider regarding the method of consent required for data processing and/or communicating with users, and how this consent must be stored. You should satisfy yourself that the method of obtaining and storing consent in Identity, Speakout & Controlshift meets the legal requirements of your jurisdiction before you proceed!

Updating a Privacy Policy

First, you will need to publish your new privacy policy on your website. In order to accurately track exactly which version of a privacy policy each user has seen and (implicitly) consented to while taking action, the recommended approach is to use versioned / dated links, eg:

This means that when a user submits data we can track the privacy policy version they were linked to.

For any areas of your website which link to your Privacy Policy, but are not tracked, it is recommended to use a generic privacy-policy link, which forwards to the latest version of the policy. Eg. you may include a link to the privacy policy in the footer of your website, etc.

Identity

Step 1: Create a new ConsentText object in Identity’s Ruby console using the template below. Note this is a template only, the exact consent text will depend on your organisation. If you are only making changes to the legal text of your privacy policy, you will most likely want to use the same consent_short_text as your active privacy policy, and update the link to the new version of the legal text.

ConsentText.create!(
  public_id: 'privacy-policy-17-02-20',
  consent_short_text: 'I consent to the <a href="https://{ your website }/privacy-policy-17-02-20" target="_blank">privacy policy</a>',
  full_legal_text_link: 'https://{your_website}/privacy-policy-17-02-20'
)

Normally, simply agreeing to an organisations privacy policy will not have any immediate effect (such as subscribing the user to a mailing list, etc). It is simply something which needs to be recorded for legal reasons. Therefore, no PostConsentMethod records are normally required when setting up or updating a privacy policy.

Speakout

Step 1: Create the same ConsentText object in Speakout’s Padrino console. It is critical that you use EXACTLY the same public_id, consent text wording, and link in both Identity & Speakout, otherwise what is displayed to the user in Speakout, and what is stored in the Identity CRM will not match!

ConsentText.create!(
  public_id: 'privacy-policy-17-02-20',
  consent_short_text: 'I consent to the <a href="https://{ your website }/privacy-policy-17-02-20" target="_blank">privacy policy</a>',
  full_legal_text_link: 'https://{your_website}/privacy-policy-17-02-20'
)

Step 2: Update the default privacy policy used by your org in Speakout. There are multiple ways to do this.

Different configurations for displaying consent are stored in the ConsentConfiguration table. Check if your org is using this table for it’s default configuration by running this on the Padrino Console:

ConsentConfiguration.where(default_consent: true)

If a record is returned, you should either update your existing default ConsentConfiguration record to use the new privacy policy, or you may wish to create a new ConsentConfiguration using the new privacy policy, and set this as the default (setting default_consent to false on the old record).

If no record is returned, and your org has consent configuration stored in your Settings file (usually named settings.YOUR-ORG-NAME.yml), then it is easiest to simply amend your Settings file with the new privacy policy public_id. Once amended, you will need to deploy the new Speakout code to your Production Speakout instance.

Either way, you should consult the Speakout Documentation on Consent Configurations for guidance on the exact JSON/yaml to use to configure your default consent configuration appropriately.

Note, if you have both a default ConsentConfiguration record, and consents setup in your Settings file, the ConsentConfiguration database record takes precedence.

Step 3: Validate your Speakout -> Identity Consent setup.

First, check Speakout is displaying your new Privacy Policy wording (the consent_short_text) on campaigns.

Then, validate that when taking a Speakout action, the action & consent data is sync’d to Identity as expected. The following SQL can be used against the Identity database to verify this. Ensure the member_action_consent.consent_text_id links to your new privacy policy ConsentText:

SELECT mac.*
FROM member_action_consents mac
JOIN member_actions ma ON mac.member_action_id = ma.id
JOIN members m ON ma.member_id = m.id
WHERE m.email = '<email_you_signed_with>'
AND ma.created_at > '<todays_date>';

ControlShift

If you also use ControlShift, you will probably want to update the Privacy Policy used on the ControlShift platform as well.

Login to your ControlShift instance, and visit: https://{your_controlshift_site}/org/consent_content_versions

You will see a table of ‘Consent Versions’. Consent Versions in ControlShift consist of a combination of a version of the Privacy Policy, the Terms of Service, and the Data Processing Consent Label. If you have updated your Privacy Policy, this likely means you need to update two things:

  1. The “Privacy Policy”, which is actually the full Privacy Policy terms. This is stored on Controlshift so users who have started petitions may print out forms to collect paper signatures, and the full Privacy Policy for the organisation should be attached for people to read.
  2. The “Data Processing Consent Label”, which is the short text about your privacy policy, usually including a link to the full privacy policy hosted on your website. This is displayed under the ‘Sign’ button on the ControlShift website.

Unfortunately, as soon as either of these is updated, the change goes live, and a new ‘Consent Version’ is immediately created. There is no way to ‘atomically’ update both the Privacy Policy and the Data Processing Consent Label, meaning if both need updating, you will always have a middle ‘junk’ Consent Version created.

Step 1: Update the “Data Processing Consent Label” by clicking the current version in the ControlShift UI, and editing the text as necessary. It is critical that you use EXACTLY the same wording here as you used for the ConsentText.consent_short_text in Identity, otherwise what is displayed to the user on ControlShift, and what is stored in the Identity CRM will not match!

Step 2: Update the “Privacy Policy” by clicking the current version in the Controlshift UI, and editing the text as necessary. It should match the privacy policy published on your website (eg. the text at https://{your_website}/privacy-policy-17-02-20 )

Step 3: Add external_id labels to the new ‘Consent Versions’ in the Controlshift UI. It is recommended that you name these to match your ConsentText.public_id - but since you may have multiple ‘Consent Versions’ in Controlshift which map to a single ConsentText, you may want to add -v1, -v2, etc. In the above example, editing both the “Data Processing Consent Label” and “Privacy Policy” would result in 2 new ‘Consent Versions’, so we would name them privacy-policy-17-02-20-v1 and privacy-policy-17-02-20-v2.

Step 4: Link the new ControlShift ‘Consent Versions’ to the correct ConsentText in Identity.

To do this, we must create a ControlshiftConsent record, and a ControlshiftConsentMapping record, for each new ‘Consent Version’ in Controlshift (in this case, two new versions were created). A ControlshiftConsent record is simply Identity’s model of a ‘Consent Version’ in the ControlShift platform, while ControlshiftConsentMapping records link a single ControlshiftConsent to one or more ConsentText, including data about how a user opted in or out.

In the Identity Rails Console, run the following:

cc_v1 = ControlshiftConsent.find_or_create_by!(
  controlshift_consent_type: 'consent_content_version',
  controlshift_version_id: FIND_ME_IN_THE_CSL_UI,
  controlshift_consent_external_id: 'privacy-policy-17-02-20-v1'
)
ControlshiftConsentMapping.create!(
  controlshift_consent_id: cc_v1.id,
  consent_text: ConsentText.find_by(public_id: 'privacy-policy-17-02-20'),
  method: "implicit",
  opt_in_level: "implicit",
  opt_in_option: "",
  opt_out_level: "none_given",
  opt_out_option: ""
)

cc_v2 = ControlshiftConsent.find_or_create_by!(
  controlshift_consent_type: 'consent_content_version',
  controlshift_version_id: FIND_ME_IN_THE_CSL_UI,
  controlshift_consent_external_id: 'privacy-policy-17-02-20-v2'
)
ControlshiftConsentMapping.create!(
  controlshift_consent_id: cc_v2.id,
  consent_text: ConsentText.find_by(public_id: 'privacy-policy-17-02-20'),
  method: "implicit",
  opt_in_level: "implicit",
  opt_in_option: "",
  opt_out_level: "none_given",
  opt_out_option: ""
)

Step 5: Validate your ControlShift -> Identity Consent setup.

First, check ControlShift is displaying your new “Data Processing Consent Label” on campaigns (which should match the ConsentText.consent_short_text value for your updated Privacy Policy).

Then, validate that when taking a ControlShift action, the action & consent data is sync’d to Identity as expected. The following SQL can be used against the Identity database to verify this. Note, ControlShift actions may take a few minutes to sync across to Identity. Ensure the member_action_consent.consent_text_id links to your new privacy policy ConsentText:

SELECT mac.*
FROM member_action_consents mac
JOIN member_actions ma ON mac.member_action_id = ma.id
JOIN members m ON ma.member_id = m.id
WHERE m.email = '<email_you_signed_with>'
AND ma.created_at > '<todays_date>';

Identity

Step 1: Create a new ConsentText object in Identity’s Ruby console as follows:

ConsentText.create!(
  public_id: 'contact-consent-17-02-20',
  consent_short_text: 'Do you agree to being contacted about this & other important campaigns? You can unsubscribe anytime.',
  full_legal_text_link: ''
)

Step 2: Create appropriate PostConsentMethod records in Identity’s Ruby Console.

Since agreeing to this new ConsentText should subscribe a user, and disagreeing should unsubscribe the user, we also need PostConsentMethod records to carry this out:

PostConsentMethod.create!(
  consent_text: ConsentText.find_by(public_id: 'contact-consent-17-02-20'),
  min_consent_level: 1,
  max_consent_level: 1,
  method: 'email_unsubscribe'
)
PostConsentMethod.create!(
  consent_text: ConsentText.find_by(public_id: 'contact-consent-17-02-20'),
  min_consent_level: 4,
  max_consent_level: 4,
  method: 'email_subscribe'
)

In this case, we’re configuring Identity to call the email_unsubscribe method if a user gives a consent_level of 1 (None Given), and call the email_subscribe method if a user gives a consent_level of 4 (Explicit Opt-In). More information about the different levels of consent is available here.

Speakout

Step 1: Create the same ConsentText object in Speakout’s Padrino console. It is critical that you use EXACTLY the same wording in Identity & Speakout, otherwise what is displayed to the user, and what is stored in the Identity CRM will not match!

ConsentText.create!(
  public_id: 'contact-consent-17-02-20',
  consent_short_text: 'Do you agree to being contacted about this & other important campaigns? You can unsubscribe anytime.',
  full_legal_text_link: ''
)

Step 2: Update the default contact consent used by your org in Speakout. There are multiple ways to do this.

Different configurations for displaying consent are stored in the ConsentConfiguration table. Check if your org is using this table for it’s default configuration by running this on the Padrino Console:

ConsentConfiguration.where(default_consent: true)

If a record is returned, you should either update your existing default ConsentConfiguration record to use the new contact consent, or you may wish to create a new ConsentConfiguration using the new contact consent, and set this as the default (setting default_consent to false on the old record).

If no record is returned, and your org has consent configuration stored in your Settings file (usually named settings.YOUR-ORG-NAME.yml), then it is easiest to simply amend your Settings file with the new contact consent public_id. Once amended, you will need to deploy the new Speakout code to your Production Speakout instance.

Either way, you should consult the Speakout Documentation on Consent Configurations for guidance on the exact JSON/yaml to use to configure your default consent configuration appropriately.

Note, if you have both a default ConsentConfiguration record, and consents setup in your Settings file, the ConsentConfiguration database record takes precedence.

Step 3: Validate your Speakout -> Identity Consent setup.

First, check Speakout is displaying your new Email Contact Consent wording (the consent_short_text) on campaigns, and that it has the expected method of consenting (eg. a checkbox, radio buttons, etc).

Then, validate that when taking a Speakout action, the action & consent data is sync’d to Identity as expected. The following SQL can be used against the Identity database to verify this. Ensure the member_action_consent.consent_text_id links to your new contact consent ConsentText, and that the consent_level is accurate, depending on whether you opted in or not:

SELECT mac.*
FROM member_action_consents mac
JOIN member_actions ma ON mac.member_action_id = ma.id
JOIN members m ON ma.member_id = m.id
WHERE m.email = '<email_you_signed_with>'
AND ma.created_at > '<todays_date>';

Finally, validate that the member subscription record has been updated appropriately. It is recommended you take action multiple times, perhaps with multiple emails, to verify both the opt-in and opt-out path are working correctly:

SELECT ms.*
FROM member_subscriptions ms
JOIN members m ON ms.member_id = m.id
WHERE m.email = '<email_you_signed_with>';

ControlShift

If you also use ControlShift, you will probably want to update the Email Opt-In Type used on the ControlShift platform as well.

Step 1: Create a new Email Opt In Type.

Login to your ControlShift instance, and visit: https://{your_controlshift_site}/org/email_opt_in_types

We are interested in updating the Active Web Form, so click on ‘Update’ next to this.

Select the type of behaviour you want to use to obtain consent (eg. ‘Pre-checked checkbox’, ‘Radio Buttons’, etc) and update the text fields below. It is critical that you use EXACTLY the same wording for the “Web Form Email Opt-in Label” as you used for the ConsentText.consent_short_text in Identity, otherwise what is displayed to the user on ControlShift, and what is stored in the Identity CRM will not match!

If using Radio Buttons, you should also ensure that the “Radio Opt In Yes Label” and “Radio Opt In No Label” also match the radio button labels you used in Speakout, although these can be configured appropriately later if they do not match.

Step 2: Ensure the new Email Opt In Type has an external_id. These can be set by visiting https://{your_controlshift_site}/org/email_opt_in_types/advanced - it is recommended that you name this to match your ConsentText.public_id, so we would name it contact-consent-17-02-20.

Step 3: Link the new ControlShift ‘Email Opt-In Type’ to the correct ConsentText in Identity.

To do this, we must create a ControlshiftConsent record, and a ControlshiftConsentMapping record, for each new ‘Email Opt-In Type’ in Controlshift. A ControlshiftConsent record is simply Identity’s model of an ‘Email Opt-In Type’ in the ControlShift platform, while ControlshiftConsentMapping records link a single ControlshiftConsent to one or more ConsentText, including data about how a user opted in or out.

Assuming you used Radio Buttons in the ControlShift UI, run the following in the Identity Rails Console:

cc = ControlshiftConsent.find_or_create_by!(
  controlshift_consent_type: 'email_opt_in_type',
  controlshift_version_id: FIND_ME_IN_THE_CSL_UI,
  controlshift_consent_external_id: 'contact-consent-17-02-20'
)
ControlshiftConsentMapping.create!(
  controlshift_consent_id: cc.id,
  consent_text: ConsentText.find_by(public_id: 'contact-consent-17-02-20'),
  method: "csl_radio_buttons",
  opt_in_level: "explicit_opt_in",
  opt_in_option: "THIS TEXT SHOULD MATCH THE 'Radio Opt In Yes Label'",
  opt_out_level: "none_given",
  opt_out_option: "THIS TEXT SHOULD MATCH THE 'Radio Opt In No Label'"
)

Step 4: Validate your ControlShift -> Identity Consent setup.

First, check ControlShift is displaying your new “Email Opt-In Type” on campaigns (which should match the ConsentText.consent_short_text value for your new contact consent wording).

Then, validate that when taking a ControlShift action, the action & consent data is sync’d to Identity as expected. The following SQL can be used against the Identity database to verify this. Note, ControlShift actions may take a few minutes to sync across to Identity. Ensure the member_action_consent.consent_text_id links to your new contact consent ConsentText:

SELECT mac.*
FROM member_action_consents mac
JOIN member_actions ma ON mac.member_action_id = ma.id
JOIN members m ON ma.member_id = m.id
WHERE m.email = '<email_you_signed_with>'
AND ma.created_at > '<todays_date>';

Finally, validate that the member subscription record has been updated appropriately. It is recommended you take action multiple times, perhaps with multiple emails, to verify both the opt-in and opt-out path are working correctly:

SELECT ms.*
FROM member_subscriptions ms
JOIN members m ON ms.member_id = m.id
WHERE m.email = '<email_you_signed_with>';