Implementing GDPR-compliant Double Opt-In for Email Subscriptions

General Data Protection Regulation – Overview:

The General Data Protection Regulation, also known as GDPR, is a new data privacy law introduced by the European Union. The law came into practice on May 25, 2018.

GDPR Basic Rules

The rules basically apply to anyone who makes use of personal data such as names, email addresses and other personal information.
Anyone who utilizes or processes the data will be accountable/responsible for the data being used.
Companies or individuals processing the data must comply in a way that is lawful, transparent, fair and also only for the purpose it actually got.
Data can only be used time limited and it must be processed securely.
The Law is unbounded, which means that anyone can be questioned regardless of location or even if they are not inside an EU state.
Firms or individuals who are violating the law will be fined up to €20 million ($24m) or 4% of global revenue, whichever is higher.

Salesforce – GDPR

Multiple changes need to be considered/implemented regarding usage of personal data in salesforce where the details such as Name, Addresses, Phone Numbers, Email addresses are stored in Leads, Accounts and Contacts. This article mainly focuses on informing the contacts by sending them emails about the new GDPR law, and getting consent from them regarding the usage of personal data.

Flow

Salesforce Implementation

The following components of Salesforce will be used to implement the complete process.

  1. Custom object/ fields
  2. Process builder
  3. Site
  4. Email alert
  5. Email template
  6. Apex class
  7. Visualforce page

Custom Object

A custom object named “Utility” will be created along with the following fields as shown below. This will be used to update the contact information when the user clicks on the link from the email.

Field Label API Name Data Type
Company Company__c Text(200)
Contact Contact__c Lookup(Contact)
Contact Id Contact_Id__c Text(20) (External ID) (Unique Case Insensitive)
Do Not Call DoNotCall__c Checkbox
Email Email__c Email
Email Opt Out EmailOptOut__c Checkbox
Email Updated On EmailUpdatedOn__c Date/Time
First Name FirstName__c Text(40)
Last Name LastName__c Text(80)
Phone Phone__c Phone
Phone Updated On PhoneUpdatedOn__c Date/Time
Salutation Salutation__c Picklist
Title Title__c Text(128)
Update Flag Update_Flag__c Picklist

Process Builder

The process builder initiates the process whenever there is an update in the “Utility” object to update received contact details. Please find below the complete setup:

Step 1

Step 2

Step 3

Create Websites for user

Site 1

Create a site that allows to update the contact information. When the user receives the email and clicks on the button navigate to this site. Once the user updates the information/gives consent to receive newsletters in the future, all the information will be saved directly to Salesforce. The site must be configured as below.

For the site user profile, proper permission to utility objects shall be given as below. Also the Class and visualforce pages need to be given access to the profile.

Site 2

The site below helps Salesforce to get the double confirmation from the contact and redirects to the company’s web site.

Provide access to the contact for above site’s profile as below.

VF Page

Below is a sample code snippet to get the Contact information.

</pre>
<table style="margin: 0 auto; border-spacing: 15px;">
<apex:variable var="c" value="{!RowList[0]}" />
<!--
<tr>
<td>
Anrede
<apex:inputText value="{!c.Salutation}"/></td>
<td></td>
</tr>

-->
<tr>
<td>
Vorname
<apex:inputText value="{!c.FirstName}"/></td>
<td>
Nachname
<apex:inputText value="{!c.LastName}"/></td>
</tr>
<tr>
<td>
Unternehmen
<apex:inputText value="{!c.Company}"/></td>
<td>
Position
<apex:inputText value="{!c.Title}"/></td>
</tr>
<tr>
<td>
Telefonnummer
<apex:inputText value="{!c.Phone}"/></td>
<td>
E-Mail-Adresse
<apex:inputText value="{!c.Email}"/></td>
</tr>
<tr>
<td colspan="2">
Ich erlaube der Ihre GmbH Name mich auf den folgenden Kontaktwegen zu innovativen Produkten, Veranstaltungen und Erfahrungsberichten zu informieren:</td>
</tr>
<tr>
<td colspan="2">

<apex:inputCheckbox value="{!c.optPhone}" id="Telefon"/>
<apex:outputLabel value="Telefon" for="Telefon"/>
<apex:inputCheckbox value="{!c.optEmail}" id="E-mail"/>
<apex:outputLabel value="Elektronischer Post, wie z. B. E-Mail, App-Mitteilung oder SMS" for="E-mail"/>
</td>
</tr>
<tr>
<td colspan="2">
<apex:commandButton action="{!updateContact}" value="Einverstanden" onclick="alert('Vielen Dank für Ihre Angaben.');"/>

<!--<input type="submit" name="" id="" value="Mailing weiter abonnieren" onclick="{!updateContact}"/>

-->
</td>
</tr>
</table>
<pre>

Apex Class

The class below will be responsible for getting updated contact information from the site and save the same to Salesforce.

public without sharing class DoubleOptIn {
    /*Declare Variables*/
    public List<conWrapper> RowList {get; set;}
    public List<contact> contactId;
    
    public DoubleOptIn(){
        RowList = new List<conWrapper>();
        conWrapper tr;
        contactId = [SELECT Id, Name, Salutation, FirstName, LastName, Title, Phone, Email, DoNotCall, HasOptedOutOfEmail, Company__c
                        FROM Contact 
                        WHERE Id = :ApexPages.currentPage().getParameters().get('id') LIMIT 1];
        /*Building the List of conWrappers*/
        /*Fetch the Contact and then build the List*/
        for(Contact con : contactId){
            tr = new conWrapper();
            tr.ConId = con.id;
            tr.LastName = con.LastName;
            tr.Phone = con.Phone;
            tr.Company = con.Company__c;
            //tr.Salutation = con.Salutation;
            tr.FirstName = con.FirstName;
            tr.Title = con.Title;
            tr.Email = con.Email;           
            /*Add the conWrapper to the List then and there*/
            RowList.add(tr);
        }
    }
       
    public PageReference updateContact() {
        Unsubscribe_Utility__c u = new Unsubscribe_Utility__c();
        u.Contact__c = RowList[0].ConId;
        u.Contact_Id__c = RowList[0].ConId;
        //u.Salutation__c = RowList[0].Salutation;
        u.FirstName__c = RowList[0].FirstName;
        u.LastName__c = RowList[0].LastName;
        u.Company__c = RowList[0].Company;
        u.Title__c = RowList[0].Title;
        u.Phone__c = RowList[0].Phone;
        u.Email__c = RowList[0].Email;
        u.EmailUpdatedOn__c = System.now();
        u.PhoneUpdatedOn__c = System.now();
        u.Update_Flag__c = 'Double Opt In';
        if(RowList[0].optEmail!=null){if(RowList[0].optEmail){u.EmailOptOut__c = false;} else {u.EmailOptOut__c = true;} }
        if(RowList[0].optPhone!=null){if(RowList[0].optPhone){u.DoNotCall__c = false;} else {u.DoNotCall__c = true;}}
        upsert u Contact_Id__c;
        PageReference pageRef = new PageReference('https://optanium.com/');
        return pageRef;
    }
    public PageReference createTask(){
        system.debug('Entered tak creation');
        String userId = UserInfo.getUserId();
        Task t = new Task();
        t.OwnerId = userId;
        t.Subject = 'Mass Email-DSGVO';
        t.Status = 'Completed';
        t.Priority = 'Normal';
        t.ActivityDate = date.parse(date.today().format());
        t.WhoId = contactId[0].Id;
        insert t;
        system.debug('Entered task creation' + t);
        return null;
    }   
    public class conWrapper{
        public String ConId { get; set; }
        public String Email { get; set; }
        public String Phone { get; set; }
        public String Title { get; set; }
        public String Company { get; set; }
        public String LastName { get; set; }
        public String FirstName { get; set; }
        //public String Salutation { get; set; }
        public boolean optEmail{get;set;}
        public boolean optPhone{get;set;}
    }   
}

VF Page 2

Page to redirect to the company site after clicking the double confirmation link from the email sent to the contact.

Apex Class

public without sharing class SubscribeEmails{
    public Id conId{get;set;}
    public string templateName{get;set;}
    
    public SubscribeEmails(){
        conId = apexpages.currentpage().getparameters().get('conId');
        templateName = apexpages.currentpage().getparameters().get('templateName');     
    }
    
    public PageReference ProcessContact(){
        try{ 
            Contact subContact = [select id from Contact where id=:conId limit 1];
            if(subContact != null){
                subContact.HasOptedOutOfEmail = false;
                subContact.EmailSubscribedOn__c = System.now();
                update subContact;
            }
            PageReference pageRef = new PageReference('https://company.com/bestaetigung/');
            return pageRef;
        } 
        catch(DmlException e) {
            System.debug('An unexpected error has occurred: ' + e.getMessage());
        }
        return null;
    }
}

Email Alert

Responsible for sending an email alert to the contacts once the updated information is received.

Email Template

Design your own email template containing the site URL that redirects to the web pages for accessing the visualforce page without logging in.