How to create one-click personalized links in CiviCRM emails

One of the real advantages of CiviCRM is having an integrated donation, event registration, membership, and email system where information is already in the system.  One of the best features is among the least-publicized: personalized links in emails that auto-populate the contribution, petition, event registration, or other form for the recipient.

The result is that it feels like a one-click log-in for the user, but there’s no actual log-in happening, and there doesn’t even need to be a user account for them in your content management system (CMS – Drupal, Joomla, or WordPress).  All you need is a CiviCRM contact record, and by definition, you have that if you’re emailing someone.

This method is sometimes called “checksum links” or “checksum tokens”, but as you’ll see, the checksum is really just there as a security measure.  We’re really looking for a way to use someone’s specific contact ID for a form without logging in.

Where is this useful?

Certainly, a personalized link is useful in a bulk email through CiviMail; it’s not dissimilar from the opt-out or unsubscribe link that you’re required to include.  Announcing an event, inviting people to update their contact information, or making a donation appeal seamless are all good reasons to make links personalized.

If you’re inviting one or several contacts to an event, you can use personalized links within a regular “send an email” message.

Meanwhile, one of the most powerful uses for personalized links is through scheduled reminders—automated messages triggered by dates on activities, memberships, events, or contact records.  If a membership is expiring, why not have the email link to a form pre-filled with the member’s information?  If someone’s birthday is coming up, you might invite them to set up a personal campaign page.

How CiviCRM links work

CiviCRM URLs all have similar elements across the three CMSes, even though they look different in other ways.  The pieces that tell CiviCRM what page to load are the main path and then various URL parameters.  For example, let’s look at a typical contribution page URL:

Drupal: http://www.myorganization.org/civicrm/contribute/transact?reset=1&id=99
(or without Clean URLs: http://www.myorganization.org/?q=civicrm/contribute/transact&reset=1&id=99)

Joomla: http://www.myorganization.org/index.php?option=com_civicrm&task=civicrm/contribute/transact&reset=1&id=99

WordPress: http://www.myorganization.org/mybasepage?page=CiviCRM&q=civicrm/contribute/transact&reset=1&id=99
(the “mybasepage” is commonly “civicrm”, though this will vary per site)

Note: Joomla menu items and WordPress pages/posts with shortcodes don’t look like this, but they correspond to a URL that looks like this.  You can see this when editing a CiviCRM menu item in Joomla, and the elements of the WordPress shortcode correspond to this.

Let’s break it apart.  The purple section of each is boilerplate—the part that’s the same on any CiviCRM URL for your site.  The green part—the main Drupal path if you’re using Clean URLs, the “task” parameter in Joomla, or the “q” parameter in WordPress or if you don’t have Clean URLs enabled in Drupal—determines the CiviCRM form to be shown.  An event registration form would be “civicrm/event/register”, a profile edit form would be “civicrm/profile/edit”, and so forth.

The red section—all the additional parameters—tells CiviCRM what to do with that page.  The “reset” parameter is almost always there and typically 1.  The “id” parameter in this case determines the contribution page ID.  Each contribution page will have practically the same URL except that others will have “id=1”, “id=2”, or whatever.  It’s this section that we’ll be altering.

Building the link

All that’s really needed to create a personalized link for CiviCRM is to add additional parameters to the URL that tell CiviCRM which contact is filling out the form.  If you are familiar with personalizing emails with mail-merge tokens, you’ll know that you can drop personalized values into a message pretty easily.  This is basically what will happen: instead of adding the “{contact.email_greeting}” or “{contact.first_name}” token to insert a name into the body of your message, we’ll be adding the “{contact.contact_id}” token to insert the contact ID into the URL of the link.

Let’s take the Drupal example above.  The main link is http://www.myorganization.org/civicrm/contribute/transact?reset=1&id=99, and we’ll add the “cid” parameter to indicate the ID of the contact corresponding to the recipient of the message.  After that, we’ll add a checksum token, which is also required.  This personalized URL method is sometimes called “checksum links” because of the checksum.

Why is the checksum needed?  If you were able to just add “&cid=123” to the end of a URL, you’d be able to fill a form (viewing and then editing information) as if you were contact ID 123.  You could then systematically harvest and/or alter all the contacts in a site by just walking through the IDs—”cid=124”, “cid=125”, and so forth.  The checksum is a randomly-generated string of letters and numbers that corresponds to a single contact ID.  If you visit a URL with the contact ID but with a missing or invalid checksum, the page will act as if the contact ID isn’t there.

The checksum token actually generates both the checksum itself as well as the parameter label “cs=”.  That means “{contact.checksum}” will be automatically replaced with something like “cs=1234longchecksumhere56789”.  The full URL for contribution page ID 99 with the checksum and the contact ID would be:

Drupal: http://www.myorganization.org/civicrm/contribute/transact?reset=1&id=99&cid={contact.contact_id}&{contact.checksum}

Joomla: http://www.myorganization.org/index.php?option=com_civicrm&task=civicrm/contribute/transact&reset=1&id=99&cid={contact.contact_id}&{contact.checksum}

WordPress: http://www.myorganization.org/mybasepage?page=CiviCRM&q=civicrm/contribute/transact&reset=1&id=99&cid={contact.contact_id}&{contact.checksum}

(The same modifications for WordPress base pages and Drupal without Clean URLs apply here and in all further examples.)

If a recipient’s contact ID is 123 and the corresponding checksum happens to be “998877665544332211”, the resulting URL (which will only appear in the actual email sent to them) will be (for contribution page 10 on a WordPress site):
http://www.myorganization.org/mybasepage?page=CiviCRM&q=civicrm/contribute/transact&reset=1&id=10&cid=123&cs=998877665544332211

Including it in an email

As you can see, the actual URL is long and hideous.  Thankfully, you don’t need to (and probably should never) put the naked URL in your message.  Just create a link: have the text read “donate today”, select those words, click the link button in the editor, and paste the URL in.  Because of the length and complexity, you’ll probably want to put the link together in a plain text editor first, but then it’ll be ready to go.  You can reuse the link from email to email, because even though the actual recipients’ contact IDs may be different, and the checksum will definitely change, the URL with tokens will always be the same for the same contribution page.

It is valuable, however, to always test the email by sending it to yourself.  Use the Private Browser or Incognito function of your browser to make sure you’re testing without already being logged in.

Other types of forms

Now that you have seen how a contribution form link can be personalized, let’s look at a few others.

Profiles

You’ve probably used profiles for all kinds of things within CiviCRM, such as including fields in contribution and event forms, customizing the columns used in search results, or batch editing contact records.  When used on their own, profiles are great for collecting information for new or existing contacts.

If you go to edit a profile, you can see a button for “Use (Create Mode)”.  This will give you a link to a standalone form with all the fields blank: “create mode” means that you’re presumed to be creating contacts with the form rather than editing an existing contact record.  If you modify that URL to replace “civicrm/profile/create” with “civicrm/profile/edit”, you’ll see your own information there—it’s a form for you to edit your existing information.

If you want to send an email for a contact to edit his or her information, you just need to send a link to a profile in edit mode with the contact ID and checksum tokens set.  Here are examples for profile ID 2:

Drupal: http://www.myorganization.org/civicrm/profile/edit?reset=1&gid=2&id={contact.contact_id}&{contact.checksum}

Joomla: http://www.myorganization.org/index.php?option=com_civicrm&task=civicrm/profile/edit&reset=1&gid=2&id={contact.contact_id}&{contact.checksum}

WordPress: http://www.myorganization.org/mybasepage?page=CiviCRM&q=civicrm/profile/edit&reset=1&gid=2&id={contact.contact_id}&{contact.checksum}

Note that the “gid” parameter is the profile ID (owing to the profile being a group of fields) and the “id” parameter is the contact ID.

Why not create mode?  Again, create mode presumes you’re creating new contacts.  It’s nice for a signup form for an email list, but in this case, you specifically want to edit an existing contact.  Create mode will ignore the contact ID.  All you need to do to change a create mode link to an edit mode link is to replace “create” with “edit”.

Event registration

If you want to make event registration quick and easy, add the contact ID and checksum to the URL in the mailing.  As with contribution pages, id is the event ID, and cid is the contact ID.  Get the event registration form URL from the Manage Events page.  The following links are for event ID 15:

Drupal: http://www.myorganization.org/civicrm/event/register?reset=1&id=15&cid={contact.contact_id}&{contact.checksum}

Joomla: http://www.myorganization.org/index.php?option=com_civicrm&task=civicrm/event/register&reset=1&id=15&cid={contact.contact_id}&{contact.checksum}

WordPress: http://www.myorganization.org/mybasepage?page=CiviCRM&q=civicrm/event/register&reset=1&id=15&cid={contact.contact_id}&{contact.checksum}

Petitions

For all the same reasons, it’s great to have petitions be a quick and easy process for email recipients.  When you create a petition, you’ll get a URL based upon civicrm/petition/sign, with sid equal to the petition ID.  (Why “sid”?  Petitions and surveys are two sides of the same coin in CiviCRM’s backend, so it’s the survey ID.)  Add “&cid={contact.contact_id}&{contact.checksum}” to the end, and you have a one-click petition link.  These use the example of petition ID 4:

Drupal: http://www.myorganization.org/civicrm/petition/sign?reset=1&sid=4&cid={contact.contact_id}&{contact.checksum}

Joomla: http://www.myorganization.org/index.php?option=com_civicrm&task=civicrm/petition/sign&reset=1&sid=4&cid={contact.contact_id}&{contact.checksum}

WordPress: http://www.myorganization.org/mybasepage?page=CiviCRM&q=civicrm/petition/sign&reset=1&sid=4&cid={contact.contact_id}&{contact.checksum}

Final details to note

Hopefully, you’ll find this is a straightforward process for making personalized links in emails.  Composing the link is a little bit of extra work, but you’re saving much more time:

  • your supporters don’t have to fill information all the time (that may conflict with existing information),
  • you don’t have to chase down as many duplicates, and
  • you’ll find more people will actually donate, update information, register for events, and sign your petitions.

What happens if someone forwards an email?  There’s no magic trick here.  Anyone with the link will be treated as if they’re the original recipient of the email.  However, a message appears at the top of the form greeting that person by name and including a link to click if you aren’t them.  Also, it’s usually obvious when you see someone’s information all filled in.

However, not all use cases are the same.  If your supporters tend to forward emails to people who ignore the message and decide they should change the information, you’ll have trouble using personalized links.  You could add warnings here and there, but you may end up deciding it’s not worth it, at least for some uses.  There is a token for CiviMail messages that provides a link to forward an email (generating appropriate tokens for the new recipient), but you can’t always count on people using that.

Also, if you are linking to a form collecting sensitive information, you may not want to use a personalized link to it.  A forwarding recipient would click the link and see all of the forwarder’s information.

A second concern is if a recipient’s email account is compromised.  If there are personalized links, an attacker may be able to view and/or update the victim’s information through your site.  As a security measure, CiviCRM limits the lifetime of checksums.  By default, it’s 7 days, but you can change it by going to Administer > System Settings > Misc.  The link will still work if the checksum’s lifespan has passed, but it will be as if you didn’t include the contact ID or checksum in the first place.

Contact us if you need help implementing personalized links in CiviCRM.  Need help right away?  Use Civi911 for assistance getting set up.