Build a custom WordPress competitions plug-in

Learn how to build your own custom WordPress plugin to manage and run a competition on your site



Everybody loves entering competitions, especially when they win! In reality the winning part rarely happens, but most people can remember a time when they have been lucky. It’s for this reason that many people still enter competitions over and over again to seek out that rush of potentially winning something. This is good news for people who run websites, as competitions can serve as a handy tool to gather key information about your visitors which you can use to your advantage. It enables you to capture data about your audience.

Have you ever wondered what the actual demographic of your site was? Then run a competition that requires them to fill out a form with specific information about themselves. Within a few days you will have some accurate, reliable data about your audience. Perhaps you want to increase the number of people that receive your newsletter? Capturing email addresses via a competition is a simple solution. Follow these steps to build a fully functioning competitions module for your WordPress site.


Let’s start coding

When building any plug-in for WordPress it is important to define constants which you may want to refer to in the future. Here, we will define various things such as database table names and the plug-in title used for the admin sidebar.

001 global $wpdb;
 002 define(‘COMPETITIONS_TITLE’, ‘Competitions Plugin’);
 003 define(‘COMPETITIONS_SLUG’, ‘competitions_plugin’);
 004 define(‘COMPETITIONS_TABLE’, $wpdb->prefix . ‘competitions’);
 005 define(‘COMPETITION_ENTRIES_TABLE’, $wpdb->prefix . ‘competition_entries’);
 006 define(‘COMPETITIONS_DOCROOT’, dirname(__FILE__));
 007 define(‘COMPETITIONS_WEBROOT’, str_replace(getcwd(), home_
 00 8url(), dirname(__FILE__)));

Hooks and includes

Every WordPress plug-in should use ‘hooks’ that install and uninstall the plug-in. We define those here as well as including the install, model and controller scripts that are the meat and bones of the plug-in. Using the ‘add_action’ method we can add an admin link in the sidebar that will link to our plug-in admin page. Code can be found on the resource disc.

Create some database tables

You will require two separate tables for this plug-in to work. One that stores data about the competitions you are running, such as the questions and answers, and another table which will be used to record the actual entry data of the users that have entered.

001function competitions_install () { global $wpdb;
 002 require_once ABSPATH . ‘wp-admin/includes/upgrade.php’;
 003 dbDelta(‘
 005 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 006 `competition_name` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 007 `question_1` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 008 `answer_1_option_1` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 009 `answer_1_option_2` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 010 `answer_1_option_3` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 011 `correct_answer_1` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, 
 012 `closing_date` DATETIME DEFAULT NULL,
 013 PRIMARY KEY (`id`),
 014 UNIQUE KEY `id` (`id`)

Allow for easy uninstallation

Sometimes we may want to remove a plug-in, so it’s a good idea to provide some functionality that will allow you to do this with ease. Not only do we want to remove unwanted code, but we probably do not want unused database tables lying around. We can remove the database tables that were created during the installation process by simply using a ‘DROP TABLE’ SQL statement. The code for this step is on the resource disc.

Backend form

We need a way of entering competition details. To do this we first require a form with some typical information that you would normally associate with a competition. This plug-in enables you to set three multiple choice answers for a given question. You can also set a closing date and allow it to run over a specific time period.

Using the generated shortcode

When you’ve entered all the info needed to configure a competition, the info you provided is then saved to the competition’s table. A short-code is then generated which when inserted into a post will display the competition.

Editing a competition

You can quite easily make changes to an existing competition that
you have, should you wish to make any slight alterations to the information that you have already saved earlier in the tutorial. Under the Edit/Delete competition section simply click on the Edit button. This will now pre-fill the form with the saved data you have already entered. This is all controlled from the competitions_main function which can be found within the controller.php script.

001// Update data
 002if (isset($_POST[‘competitions_update_data’])) {
 003 $id = $_GET[‘id’];
 004 competitions_table::update($id,$_POST); 
 005 $location = strtok($_SERVER[“REQUEST_URI”], ‘&’);
 006 wp_redirect( $location );

The competitions_main function

The competitions_main function is the backbone of the plug-in, and is found within the controller.php script. We use this function primarily for adding/editing and deleting competition data. All of its functionality can be rendered via one template named main.php. The methods it employs can be found within the model.php script and are all declared as public static functions, which means that they can be called from outside the scope of the script in which it resides.

001//Inserts competition data when form is submitted
 002public static function insert ($row) {
 003 global $wpdb;
 004 return $wpdb->insert(COMPETITIONS_TABLE, array( 
 005 ‘competition_name’=> stripslashes_ deep($row[‘competition_name’]), 
 007 ‘question_1’=> stripslashes_
 009 ‘answer_1_option_1’=> stripslashes_ deep($row[‘answer_1_option_1’]),
 010 ‘answer_1_option_2’=> stripslashes_deep($row[‘answer_1_option_2’]),
 011 ‘answer_1_option_3’=> stripslashes_ deep($row[‘answer_1_option_3’]),
 012 ‘correct_answer_1’=> stripslashes_deep($row[‘correct_013answer_1’]),
 014 ‘closing_date’=> stripslashes_deep($row[‘closing_ date’]) 

Downloading entry data

Another piece of administration functionality which needs to be added is the ability to download and view the details of the people that have entered the competition. We can do this by querying both of our database tables. The only information we need is the personal details of every user and the answer they gave for the question that was asked. It’s also a good idea to include the correct answer of question so you can easily pick a winner.

Create the CSV file

To view the entry information simply click the ‘download entries’ button on the competition you wish to view. This can be found in the Edit/Delete section under the form. Once clicked it will initiate the competitions_main function and grab all the data using the SQL query shown in the previous step. We then create a new CSV file and write to it using a built in PHP function called fputcsv.

001 if (!empty($compEntries))
 002 $fileName = strtolower($compEntries[0][‘competition_name’]); 003 $fileName = str_replace(“ “, “_”, $fileName);
 004 $fp = fopen(‘../competition_entries/’.$fileName.’.csv’, ‘w’);
 005 $coloumTitles[‘0’][‘competition_name’] = ‘Competition Name’; 
 006 $coloumTitles[‘0’][‘correct_answer_1’] = ‘Correct Answer’;
 007 $coloumTitles[‘0’][‘answer’] = ‘Answer’; 
 008 $coloumTitles[‘0’][‘forename’] = ‘Forename’;
 009 $coloumTitles[‘0’][‘surname’] = ‘Surname’;
 010 $coloumTitles[‘0’][‘email’] = ‘Email’;
 011 $compEntries = array_merge($coloumTitles,$compEntries);
 012 foreach ($compEntries as $fields) {
 013 fputcsv($fp, $fields); }
 014 fclose($fp); 
 015 header(‘location:http://’.$_SERVER[‘SERVER_NAME’].’/ competition_entries/’.$fileName.’.csv’);

Displaying the amount of entries

Another handy feature of this plug-in is the ability to view the amount of people that have entered the competition without the need to download the CSV file. This information can be found at the top left of the competition box. We can display this information to the user by querying the number of rows in the competition_entries table.

Active/inactive competitions

Some people may want to run multiple competitions on their website. Therefore it is important to keep track of your competitions and know which ones are currently running and which ones have expired. To make this obvious to the user, change the expired competition boxes to red and the active ones to green.

001$time = strtotime($data[‘closing_date’]);
 002//Chance css class if comp has expired
 003if ($time >= time())
 004 $compBoxClass = ‘competitionBox’;
 005 $statusText = ‘Active’; }
 006 else
 007 $compBoxClass = ‘inactiveBox’;
 008 $statusText = ‘Expired’;

The front-end

Let’s move on to the frontend now. The function responsible for actually displaying the competition to the user is called insert_competition
and is found within the controller.php script. First of all we extract the competition ID from the shortcode and grab the competition information from the database.

Loop through our data

Once we have executed our SQL we can put the resultset into an array and loop through each element. It’s a good idea to check if we actually have any competition data returned from our SQL query, because if we don’t it’s likely that the competition has expired as one of the conditions in the SQL was that the closing date had to be in the future. Wrap your loop in an IF statement and only loop through the array if it is not empty.

001 if (!empty($competitionSQL))
 002 foreach ($competitionSQL as $competitionData)
 003 $id = $competitionData->id;
 004 $competition_name = $competitionData->competition_name;
 005 $question_1 = $competitionData->question_1;
 006 $answer_1_option_1 = $competitionData->answer_1_option_1;
 007 $answer_1_option_2 = $competitionData->answer_1_option_2;
 008 $answer_1_option_3 = $competitionData->answer_1_option_3;
 009 $correct_answer_1 = $competitionData->correct_answer_1;
 010 $closing_date = $competitionData->closing_date;

Displaying the competition

Now we have fetched our competition from the database and looped through each element we can now display this information to the user. To do this we need to write some HTML that uses the PHP variables populated with the information we fetched from the database. We also require a CSS file to give the output some style, not forgetting some JavaScript to validate the data the user enters.

Validating user input

Sometimes website users can be pretty stupid. It is always worth putting in some sort of validation to prevent them from missing out vital fields and mistyping email addresses. In this example we use some JavaScript to make sure all fields are filled out correctly. The JavaScript is triggered when it detects that the ‘Enter Now’ button is clicked.

001 if (comp_firstname == “First Name”) 
 002 $(“label#comp_firstname_comp_error”).show(); 
 003 $(“.errorSpacer”).show(); 
 004 $(“input#comp_firstname”).focus(); 
 005 return false; 

Validating email addresses

To double check the user has provided an email address is the easy part – we can do that by checking to see that the email input is empty. Next we have to see if the data provided is actually an address. We can do this by using regular expressions combined with the JavaScript ‘test’ method.

Using Ajax

Ajax is a useful tool for posting data to a PHP script without the need to refresh the page. We can use Ajax here to post the data from the competition form to a PHP script for processing. Once this action has been performed we can feed back to the user that their entry has been received, and hide the input fields to prevent multiple entries.

Deleting old competitions

As time goes on your old competitions will start to clutter up the screen. When you no longer want your competition/entry data simply click on the ‘delete competition’ button. This will trigger a simple piece of SQL that erases all your competition and entry data. See the code on the resource disc at the back of the mag.

That’s it!

Have a look around the code on the disc and install the plug-in. Try running a competition on your website and see if you manage to obtain some details about your user demographic. Use the emails that your form has captured to your advantage and remember you don’t have to break the bank when it comes to your prizes. Running a competition can be a very cost-effective way of increasing your potential reach.