If you weren’t lucky enough to get a job with Google or Facebook, or even if you did, one of the first tasks you might be asked to do in your new career as a web developer is to create a subscription form. As part of creating this form will want to collect user information up front and then sending the user an email to have them activate their account. This is what is called a “double opt-in”. The user must take two actions, filling out the form and then clicking an activation link in their email, to confirm they want the account. In this article I will show you some code to help get you setup creating the activation email link. Then when they want to unsubscribe later you will have a mechanism in place to help them do that.
Whatever mechanism you choose to use for collecting the user’s info, at some point you will need to store that data. Often times this data goes straight into a database. What we have to make sure we do here is create a couple of extra fields in addition to the standard user information (name, email, phone etc). One field we will call “active” and this field will be “on” or “off” (or in our case 1 or 0). Are they activated or are they not?
The second field will be a “user_key” field which will hold a special random character string that we will generate. It could be an encrypted string if you wish, but I highly recommend making it a decently long random string. We want to make it is long enough that it will be fairly unique. Below is an example of a couple functions we could use to create a simple user account. Take note of our two fields. To help us with the random string we will create a function that generates random character strings for us.
/** * Generates a random token string of specified length. */ function generateRandomToken($length = 20) { $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; $charsLength = strlen($chars); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $chars[rand(0, $charsLength - 1)]; } return $randomString; } /** * Creates a brand new signup for the user and email. */ function createSignup($conn, $name, $email) { // Create our insert statement for saving the signup. Notice it has a field for our user key. // This user key can be used to activate and unsubscribe the user. $sql = "INSERT INTO user (username, email, active, user_key) VALUES(:name, :email, 0, :key);"; try { // Generate a random key for activation/unsubscribe $token = generateRandomToken(15); $stmnt = $conn->prepare($sql); $result = $stmnt->execute([':name' => $name, ':email' => $email, ':key' => $token]); if ($result) { $lastInsertId = $conn->lastInsertId(); return ['id' => $lastInsertId, 'token' => $token]; } } catch (PDOException $e) { // Do some logging of the error } return false; }
With all these functions in our article, we are assuming you have setup your own standard PDO object that connects to a database and passing it in as $conn. This code uses our function for generating a token and inserts it into the database along with the user’s other information. I have chosen to enter just their name and email but you can include as many fields as you like. The createSignUp() function is going to return an array if it is successful. This array will contain the new user ID and the generated token. If it is not successful it will return false. With these functions in place we now have our user in the database with an active field which is initially set to “off” (or “0” in this case). We have also set them up with their own unique key. We will use the ID and key to find their account later.
Now if the sign up process is successful, we are going to send the user an email containing an activation link they can click on. In addition, we will include an unsubscribe link in the email in the event that they want to be removed from our list. As a note, these links can be used anywhere really. We are just mentioning email in this article but you could put them in a dashboard or sent to the user through other means. When they click the links they will send along their ID and the key to trigger some action. If they send the ID and key to our activate.php page, it will activate them. If they send it to our unsubscribe page, it will remove them from our list.
To help facilitate building these links we can use a little function like the one I have put together below…
/** * Creates a link by appending the user and token to the URL parameters preserving other parts of the URL. * Can be used to create an activation URL or a unsubscribe URL. */ function createLink($baseUrl, $userId, $randomToken) { $urlParts = parse_url($baseUrl); if ($urlParts !== false) { $newQueryParams = http_build_query(array('user' => $userId, 'token' => $randomToken)); // Detect a fragment and if it exists, preserve it. $frag = ''; if (array_key_exists('fragment', $urlParts)) { $frag = '#' . $urlParts['fragment']; $baseUrl = str_replace($frag, '', $baseUrl); } // If there is a query string, append our new parameters to it. if (array_key_exists('query', $urlParts) && !empty($urlParts['query'])) { $baseUrl = str_replace($urlParts['query'], $urlParts['query'] . "&$newQueryParams", $baseUrl); } else { $baseUrl .= "?$newQueryParams"; } return "$baseUrl$frag"; } return ""; }
This function can be used for creating both links and all that will be changed is the base URL that we pass along. In the activation email we can put in ‘http://www.mysite.com/activate.php’ and it will come out as http://www.mysite.com/activate.php?user=USERIDHERE&token=RANDOMTOKENHERE. If we put in a URL like ‘http://www.mysite.com/unsubscribe.php’ it will tack on the parameters like before. Now in the activate.php and unsubscribe.php you can put the activateUser() and unsubscribeUser() functions to activate and unsubscribe the user respectively.
In the activate.php page we can put in a function like the one listed below which will turn on the active column for the user. It does this by using the ID and key to locate the user and then flipping their active column to 1.
/** * Activates the user account by setting active column equal to 1. */ function activateUser($conn, $userId, $token) { $sql = "UPDATE user SET active = 1 WHERE id = :userid and user_key = :key;"; try { $stmnt = $conn->prepare($sql); $stmnt->execute([':userid' => $userId, ':key' => $token]); return ($stmnt->rowCount() > 0); } catch (PDOException $e) { // Do some logging of the error return false; } }
There is nothing extremely complex here. We simply issue an UPDATE statement to turn the active field value on based on the ID and key/token passed. How you call this function can be up to you. Just make sure that the user ID and key make sense and are checked prior to giving it to this function. One check you could quickly do is check to make sure it is the correct length. When we created our key before, we made it 20 characters long. If the key provided is not that long, something went wrong.
NOTE ABOUT EMAIL CLIENTS: I have noticed that some email clients will actually lowercase all values in an email link, even if you have provided keys with capitalization. So I suggest you generate all your values that are going into the URL to be lowercase.
In the unsubscribe.php page we are going to have a similar method. However, instead of updating the user we are simply going to remove them. Now there could be an argument for simply deactivating them, and that is entirely up to you, but I usually don’t want to be contacted again once I unsubscribe and I expect my data will never ever be seen again. So you might want to consider just getting rid of it. Here is the function we can put on our unsubscribe page…
/** * Sets the user to have an active flag of 0 which means they are unsubscribed. * You could also just delete the user. Up to the user of the function. */ function unsubscribeUser($conn, $userId, $token) { $sql = "DELETE FROM user WHERE id = :userid and user_key = :key;"; try { $stmnt = $conn->prepare($sql); $stmnt->execute([':userid' => $userId, ':key' => $token]); return ($stmnt->rowCount() > 0); } catch (PDOException $e) { // Do some logging of the error return false; } }
Ok so now with all the pieces in place you are ready to sign up some users! During sign up you create an activation field (initially set to off) along with an unsubscribe key (set to a long unique lowercase value). Pass those values along from the sign up process to the createLink() function to get some URLs you can put into your emails you send off to the user. When they click the activation link it will direct them to your activate.php page and pass along their ID and key. There your code will look the user up and set the user’s active field to 1. They are now activated. At a later point they can click the unsubscribe link and again pass their ID and key along to have them removed from the table altogether (or disable them… your choice).
As you generate each email, all you will need to do is pass the user’s ID and their key to the createLink() function and insert it into the footer of the email in an automated way. You are then ready to go!
I hope you found this code, and explanation, helpful in getting you on the right track with user activation and unsubscribing. Let’s hope that you have more activations than unsubscribes! Speaking of subscriptions, don’t forget to subscribe to our newsletter so that you will receive future blog posts right to your inbox. Don’t worry, we don’t sell email addresses! Coders hate fans trying to send them a bunch of spam!
Thanks for reading! 🙂