Do you want to market to a European audience? You are located in Europe? Or even worse: in Germany? Then you probably want to use double-opt-in for generating waterproof email-permissions. Basically, this is not a big issue unless Salesforce Pardot is your tool of choice. Why? Simple: no double-opt-in out of the box. It even gets worse, when the user denies cookies. In this article, I outline a cookieless approach. But be warned: it is heavy stuff including API and sh*t.
No worries: after the theoretical part, I’ll give you a step-by-step guide and I’ll finish with a Whisky recommendation to celebrate your good work.
The story so far
Pardot by default manages its prospects' opt-ins via the Do Not E-Mail and Opted Out fields. Using forms or form handlers, a newly generated prospect is always opted-in. Still, jurisdiction and good conduct often demand a properly documented double opt-in by the user. Pardot does not offer a double opt-in mechanism out of the box.
While some workarounds are presented, using automation rules or engagement programs, none of them works without cookies. The need for consent for tracking cookies, even if they are presented as first-party cookies, and cross-device user journeys result in a high rate of not properly identified prospects and never confirmed double opt-ins.
The only way to get around this is by using parametrized confirmation links. Unfortunately, Pardot does not offer any unique identifier for a prospect as a merge field but the email address. This results in poorly secured and highly manipulable personalized links to be used as dynamic content in a Pardot autoresponder template.
To achieve a secure and properly working double opt-in process you need to get the web application where the Pardot form is presented to the user to work closely with the data structure of Pardot. This guide explains how.
The basic principle of Double Opt-In Tracking with Pardot
What you need to do is putting a Pardot form on your site, either as a form embedded via iframe or as a form handler. This form gathers the prospect's data and triggers via completion action an autoresponder email to the user containing a link to confirm the subscription.
Instead of relying on a custom redirect that is only able to identify the prospect via cookie, you have to use a parameterized URL that uses unique query string values to properly identify the prospect.
In the final step, this URL triggers a script that communicates via API with Pardot, uses the query string parameters to set a request, identify the user, and in case of success manipulates data for the prospect in Pardot to document the click and complete the double opt-in.
The problem: no unique identifier but the email
Pardot does not allow the internal Pardot ID as a merge value and it is not able to automatically create random strings that could be used as the identifier for a prospect. Even if you use Pardot with Salesforce and the sync is creating a lead/contact resulting in a salesforce ID, this process often turns out to be too slow. You want to send your autoresponder email immediately after the form was submitted and synchronization with your CRM might only happen minutes after this.
You will need an identifier that is available for the prospect immediately after the form was submitted. The solution here is to let the web application your form is embedded in create this unique identifier, at least for the current user session.
Remember, you can pass any value to a hidden form field, regardless if you are using forms or the form handler. You can use this ability to let the web application generate a unique id for the prospect (or to be more precise: a session id) for later use in our query string.
Why using a unique identifier anyway? The only available identifier for a prospect is the email address. But if you create a double opt-in script relying only on this parameter value as ID für the prospect, anyone figuring out your URL could opt-in any email at will. Using a unique ID paired with the email is an easy way to prevent this manipulation.
The downside of this method
By letting the web application generate a unique session ID every time the form is displayed, a new value is inserted in the data field for already existing prospects every time the user submits the form after refreshing or reentering the page. This renders any previously generated confirmation link useless. So in rare cases of users submitting the same form leaving the page, return and submit again or submitting different forms, receiving different auto responders one after another before clicking on any confirmation link, it could lead to confusion.
This behavior can be countered with the use of proper error messages and making double-opt-in confirmation only necessary when a user is previously not properly opted in. (Using dynamic content in autoresponder emails is a good way to make sure, a user needs to double opt-in only once).
Step-by-Step Guide
Step 1: Preparing Pardot Data Fields
You will need a few custom fields on your prospects to handle the process. I suggest names for those fields but feel free to rename them to any conventions your enterprise might have.
SessionID (sessionid)
Type: Text
A simple text-field to store the unique session ID generated by your forms
Permission Asked (permission_asked)
Type: Checkbox
Default value: false
This field helps you to later easily select prospects that submitted a form but never clicked the confirmation link.
Permission Given (permission_given)
Type: Checkbox
Default value: false
This field is set to true as soon as a prospect clicks the confirmation link and is properly identified. You can later use it to render dynamic content in your autoresponders for prospects who have already opted-in.
Permission Date (permission_date)
Type: Date
This field helps you to document when the permission was given. In some areas, this is mandatory if you want to legally prove that a user has opted-in.
Permission IP (permission_ip)
Type: Text
This optional field could be used to store the IP the user used when permitting you via double opt-in. In some areas, the legislation makes it necessary to properly prove permission.
Step 2: Setting up your Pardot forms
To receive the data you later need for the confirmation link, you need to add some hidden fields to your Pardot forms or your form handlers: SessionID and Permission Asked.
In the next step, you will learn how your web application will be able to prefill them with the proper values.
Step 3: Creating a Session ID and filling out hidden fields
As you need to let the web application that embeds your Pardot forms do half of the work, it is dependent on your CMS how you will be able to execute this step. But no matter what system you use, there is a way to achieve this.
First of all, you need to generate a session ID. Use your web application to generate a unique random string. I recommend to use base_convert(microtime(), 8, 36). The chance that it will be unique for the user session is good. You can also come up with any other method to generate a unique string.
Pass this string as a value to the hidden field SessionID and pass the value "true" to the hidden field Permission Asked.
This article details how to pass values to hidden fields:
https://help.salesforce.com/articleView?id=000316709&type=1&mode=1
This article details how to pass values to hidden fields with the Pardot PlugIn for WordPress using filters:
https://de.wordpress.org/plugins/pardot/#%0Afilters%0A
Example for filter (replace 54796 with the ID of your form):
function pardot_custom_append_querystring($body_html) {
return preg_replace( '/src="([^"]+)"/', 'src="$1?sessionid='.base_convert(microtime(), 8, 36).'&permission_asked=true"', $body_html );
}
add_filter( 'pardot_form_embed_code_54796', 'pardot_custom_append_querystring' );
Alternatively, depending on your CMS you can easily achieve this by writing a little plugin.
What this does: whenever a form is submitted, the prospects' data gets enriched by the two new values: a unique session id and the information that a form was submitted and permission was asked.
Step 4: Building a custom confirmation link in your autoresponder email
As a completion action for your form, you want an autoresponder email to send a confirmation link to the prospect. You can use dynamic content to prevent already opted-in prospects from receiving this same message again.
Your link should have the following syntax (when using HML in Pardot):
www.yourdomain.com/path/subscribe.php?email={{Recipient.Email}}&sid= {{Recipient.sessionid__c}}&redirect=12345
While 12345 Is the ID of the Custom Redirect you want the user to go to after clicking this link. Leave empty for default redirect to the thank you page or something like this. You can get the ID of a custom redirect if you navigate to its details view in Pardot and check the URL, i.e. https://pi.pardot.com/customUrl/read/id/12345
What it does: It uses ordinary merge tags in Pardot to build a parametrized link that contains information to identify the prospect (email), validates the prospect to its form submission (sid), and provides information about a redirect after the script has run (redirect).
Step 5: Set up your own subscription script
To properly do the magic, you need your own subscription script that calls the Pardot API and does the data manipulation for you. You can set up this script easily on your website. Simply find a path where you can run a simple PHP script and make sure, it has an accessible URL.
What it needs to do: read the values from the URL parameters and then registers for using the Pardot API.
Then request data for the prospect identified by the value of the parameter email.
Compare the session-ID stored in Pardot with the session-ID from the query string (sid). This is the step where the prospect is validated. Without this step, the script could be easily exploited.
If email and session-ID match, the script should update the field values for Permission Given and Permission Date. If you decide on also storing the IP, you can do so too.
After a successful opt-in, the script needs to retrieve the URL of the custom redirect identified by the ID you passed in the redirect parameter. Afterward, it can redirect the user to the given custom redirect.
If the opt-in was not successful, i.e. the session-ID did not match the given email, the script should redirect the user to an error page that you can set up on your website. It is helpful to explain the reason for this error on this page and remind the user that if a form was submitted more than once or different forms and not clicked any confirmation link yet, that only the last confirmation link will work.
Step 6: Make sure you only mail to Prospects with double opt-in
You need to create a suppression list that contains all prospects with Permission Given = false or empty.
Otherwise, you could also add a rule for your Segmentation List asking for Permission Given = true.
It is also possible to regularly opt-out Prospects caught in permission limbo: still, a percentage of your prospects will never confirm the double opt-in. You can easily build an automation rule that gives them like 7 days for clicking on the confirmation link and opts them out in Pardot if time has run out. But be careful with this: while Pardot allows for re-opt-in, it gets a little bit difficult to make them mailable again.
Where to go from here:
If you have set up this double opt-in process, it is advised to streamline your users' experience by using dynamic content in autoresponders, providing direct links to gated content for already identified users, and so on. You can utilize progressive forms and dynamic content on your website to make your user's lives easier.
Last but not least: time for a treat. With such a content-heavy article I thought a whisky dedicated to knowledge “passed down from generation to generation” is a perfect choice. It is also one of my favorites last winter: Laphroaig Lore. It has everything you would expect from an Islay. It has smoke, it has the taste of the sea. But it also comes with a long sweetness afterward that makes it a good reward for battling Pardot’s shortcomings.