In this tutorial we will be taking a look at creating a User Credits System in WordPress from scratch. This can be used as as in-store credit for your users. We will be building our user credit platform based on OOP and best PHP practices.

User Credits System For WordPress

This functionality should be in a WordPress plugin. I’ll be starting this one off with our WordPress plugin generator. It’s free and can save you time when creating WordPress plugins.

Starting with the base plugin, you will have 2 primary files and some folders. We will only be working in the Init. However we will be creating and included a custom class file into the base plugin.

Setting Up The Files for Our User Credits Plugin

Start with going inside the base plugin and navigate to the inc folder. That will be in your assets folder. We want to create a php file called (class.user-credits.php). We can also go into our Init file and just copy one of the includes. Change the file name and now that class will load.

Now let’s open the users credit class file in our code editor. We want to make sure no standard HTML is sitting in that file when it loads.. wouldn’t be good. Plus we want to add a quick comment an security precaution.

<?php 
/*
*   ***** WordPress User Credits System *****
*
*	A Simple Class For In-House User Credits In WordPress
*
*/
// No Direct Access
if ( ! defined( 'WPINC' ) ) {die;} // end if

Now let’s make sure that is saved and updated as we don’t want to crash the WordPress core with errors. Now if you active the plugin so far in a local / testing WordPress setup, there shouldn’t be any issues. If you already have issues, deactivate the plugin and make sure your issues are related to this.. if not, I’d recommend setting up a test WordPress site on local host. For those ready to move forward.. let’s go!

Simple User Credits PHP Class

The user credits system for WordPress is pretty simple to create. Logically, we will organize our primary tasks within the class, then fill in the functionally to make a working user credits system for WordPress. Let’s start by planning out those main required functionalities.

1. Create A Way To Give WordPress User In-Store Credit

Luckily for us, WordPress has cut out most of the work. Just like out how our WordPress post views counter uses posts meta, each user in WordPress has user meta. User meta allows us to store any particular data point on at a user level. This means every user can have a user meta key like “ensure_user_credits”.

Using this key, we can now add user credits, subtract credits, even trade credits from user to user. It’s essentially capable of being an online banking for a custom currency in WordPress.

Writing The User Credits Class For WordPress

So we are going to focus on keeping this script simple but effective. Let’s start with the base class that will work like an app in our site. We can reach out to this class anytime we need to get user credits in WordPress.

<?php 
namespace Ensure;
*   ***** WordPress User Credits System *****
*
*	A Simple Class For In-House User Credits In WordPress
*
*/
// No Direct Access
if ( ! defined( 'WPINC' ) ) {die;} // end if


// Create the Credits Class
class Credits {
	/**
	 *
	 * Constructor
	 *
	 */
	public function __construct() {
		/*
		*	Create An Action To Tie Into Later.
		*/
		do_action( 'user_credits_loaded' );
        }
}

First we start with where our code will be stored in the scope. Using a custom namespace will keep our code out of the main namespace and easier to debug later as it grows. Because we set a namespace we can also keep our user credits PHP class name short.

So let’s start thinking about the variables or “properties” our user credits class will need. We know we will need to know the current user and how many credits this user has. I also like to have a fast way to detect of a user is logged in right inside my class. So let’s look at how we would setup these basic properties inside the user credit system class for WordPress.

// Create the Credits Class
class Credits {

	/**
	 * User Meta Key
	 *
	 * @var int
	 */	
	public $creditsKey = 'ensure_user_credits';
	
	/**
	 * Current User
	 *
	 * @var int
	 */
	public $user = null;	
	/**
	 * Easy Active User
	 *
	 * @var int
	 */
	public $activeUser = false;	
	/**
	 * Active User Credits Count
	 *
	 * @var int
	 */
	public $activeUserCredits = 0;

	/**
	 *
	 * Constructor
	 *
	 */
	public function __construct() {

        }
}

Now you may notice that we set our properties with non-user defaults. This means the current user must go through some validation within our class. This ensures the user is not able to use store credit actions in our class until they have been checked first. You also notice we have a key. We will get to that soon.

User Credits System Methods

Now we need to create a few methods to make use of the user credit system for WordPress. We need to know, how to write a user credit system that is customizable.

Let’s start with the credit system logic. Let’s list out the methods or capability we require.

  • How to get a users credit total?
  • How to display a users credit on frontend?
  • How to add or subtract from a user?
  • How to transfer credit between 2 users?

We can start by making sure we have the WordPress user validated in our WordPress users credits plugin. To do so, WordPress has a few simple ways to check.

Add setup user code

	/**
	 *
	 * Set Init User Data.
	 *
	 */
	public function set_user_data() {
		
		// Get The User Object
		$user = wp_get_current_user();
		
		// If Is User Is Logged In
		if($user->exists()){
			
			// Set The User Object
			$this->user = $user;
			
			// Set Our Easy Active User Detect
			$this->activeUser = true;
			
			// Set Our Active Users Credit Count
			$this->activeUserCredits = get_user_meta($this->user->ID,$this->creditsKey, true);
			
			// Incase The User Doesn't Have Credits 
			if(!is_int($this->activeUserCredits)){
				// Let's Make Sure The Credits Default Back To 0
				$this->activeUserCredits = 0;
			}
			
		}
	}

And to register this method when our class is called, add this just inside your construct.

		/*
		*	Setup Our User Data
		*/
		$this->set_user_data();

Here we created a simple public method for checking the user and setting up our user credit properties. We also gathered the current users credits if available. For users not yet earned credits, it should return a 0 for when the event occurs.

We need a small function to get the current users total credit count.

	/**
	 *	
	 * Get The Current Users Credit Count
	 *	 
	 */
	public function get_total() {
		return $this->activeUserCredits;
	}	

Now we need to create the most important method for a user credit system. The adding and subtracting of a users credit based on some action in your website. We will refer to this as our update credits function.

	/**
	 *	
	 * Updates User Credits Count
	 *	 
	 */
	public function update_total($difference,$operator = '-') {
		// If By Chance The Update Runs For Logged Out User Somehow, Tame Down.
		if(!$this->activeUser){
			return false;
		}
		
		// Let's Update The Users Credits
		if($operator == '-'){
			$this->activeUserCredits = $this->activeUserCredits - $difference;
		}
		if($operator == '+'){
			$this->activeUserCredits = $this->activeUserCredits + $difference;
		}
		
		// Then Update The Value
		$status = update_user_meta( $this->user->ID, $this->creditsKey, $this->activeUserCredits);
		
		// Returns A Confirmation The All Updated!
		return $status;
	}

The user credits math here is pretty strait forward. It provides the logic for adding and subtracting credits to the current users account. By default, it runs in subtract mode only requiring the amount. By adding the plus sign as the second parameter, it will do addition.

Allow WordPress Users To Exchange Credits To Other User Accounts

Similarly to sending money from your PayPal to someone else. Or from your bank to a friends. Users could potentially exchange their store credits within your website. Now this may seem a bit overboard. We thought it was a neat addition to include with such user credits tutorial.

	/**
	 *
	 * Exchange Credits Between Users
	 *
	 */
	public function exchangeBetweenUsers($recieverID,$amount,$requestType = 'send') {
		
		// Here We Make Sure The User Is Legit 
		$recievingUser = get_user_by('id',$recieverID);
		
		// A Quick Double Check To Confirm They Are In The Users Database
		if(!is_int($recievingUser->ID) || !$recievingUser->ID > 0){
			return false;
		}
		
		// Get The Recieving Users Credits Total
		$recievingUserCredits = get_user_meta( $recieverID, $this->creditsKey, true);
		
		// If This User Hasn't Had Credits Before, Set as 0; 
		if(!is_int($recievingUserCredits)){
			$recievingUserCredits = 0;
		}
		
		// Handle The Send Request
		if($requestType == 'send'){
			
			// Make Sure The Send Has The Funds
			if(!$this->activeUserCredits >= $amount){
				return array('error'=>__('Not Enouph Credits','ensure'));
			}
			
			// Update The Recievers Credits
			$recievingUserCredits = $recievingUserCredits + $amount;
			
			// Update The Current Users Credits
			$this->activeUserCredits = $this->activeUserCredits - $amount;
			
			// Then Update The Values
			// Starting With The Reciever
			$status = update_user_meta( $recieverID, $this->creditsKey, $recievingUserCredits);
			
			// If The Recievers Credits Added Properly
			if($status !== 0){
				$status = update_user_meta( $this->user->ID, $this->creditsKey, $this->activeUserCredits);
				// 
				if($status !== 0){
					return true;
				} else {
					// Backup Operations To Settle The Score
					// Let's Restore The Senders Funds
					$this->activeUserCredits = $this->activeUserCredits + $amount;
					// Then Update
					$status = update_user_meta( $this->user->ID, $this->creditsKey, $this->activeUserCredits);
					// 
					if($status !== 0){
						return true;
					} else {
						// Report The Issue To Ourselves
						$data = array(
							'recipientID'=>$recieverID,
							'senderID'=>$this->user->ID,
							'amount'=>$amount,
							'requestType'=>$requestType
						);
						// Send The Data Through The Action For Later Notification Additions Such As Emails.
						do_action('user_credits_refund_error',$data);
					}
				}
			}
		}
	}

So this method is a little deeper but still rather simple when looking at it line by line. It collect an amount, recipient ID and request type. Our app already knows who the current user is so no need for that.

First, We want to make sure the sender has the funds to send. Then, we also want to make sure the recipient is real. Plus we need some info about the recipient to do the user credits math here.

I added a check to see if the transaction was successful for removing the funds from sender. Then if the reduction from sender fails, we reduce the funds from the recipient.

This means for whatever reason, the funds transfer was incomplete and we reverted all transferred funds back to before the deal. There is also a do_action that fires if such event takes place.

We included some basic info about the user credit exchange. You could send an failed to transfer email, or admin notification using an add_action.

Making The User Credits For WordPress Class Callable.

We have our base properties and methods now for a user credits system in WordPress. However, we need to do some real world prepping to make it ready to use.

Making our PHP class easy to use is key. We start by adding our “instance” property and method. This will allows us to access the class as many times as we need while only running it once. Place this between your properties and your construct.

         /**
	 *
	 * The single instance of the class.
	 *
	 * Credits
	 *
	 */
	protected static $_instance = null;
	/**
	 *
	 * The Instance
	 *
	 */
	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

That’s it for that, nothing to crazy. Our user credits class can now run as an instance.

The Easy User Credit Access Funtion

Our class is built and we want to access it. Here we need to go to our plugin core-init.php. We want to make sure this function is registered in the global namespace. So your access function would go right below the include of your class.

/**
 * Main instance of UserCreditSystem.
 *
 * Returns the main instance of UserCreditSystem to prevent the need to use globals.
 *
 * @return Credits
 */
function UserCreditSystem() {
	return Ensure\Credits::instance();
}

Hooray!! Now let’s look at how we can use the user credits system plugin for WordPress. Below are a few examples to make sure you see how to call the user credits class properly.

/*
*	
*	Get Current User Credits Example
*	
*/
if(function_exists('UserCreditSystem')){
	UserCreditSystem()->get_total();
}	

/*
*	
*	Update Current User Example
*
*	The Current User Is Spending (333) In-Store Credits.
*	
*/
if(function_exists('UserCreditSystem')){
	UserCreditSystem()->update_total(333);
}
// - Or -
if(function_exists('UserCreditSystem')){
	UserCreditSystem()->update_total(333,'-');
}
// ----------------------------------------

/*
*
*	The Current User Is Earning (333) In-Store Credits.
*	// Must Include The (+) In Second Parameter.
*	
*/
if(function_exists('UserCreditSystem')){
	UserCreditSystem()->update_total(333,'+');
}

/*
*	
*	Exchange Example
*
*	The Current User Is Sending User ID: 23, (333) In Store Credits.
*	
*/
if(function_exists('UserCreditSystem')){
	UserCreditSystem()->exchangeBetweenUsers(23,333);	
}

Now, these functions will only do the math and update the database. You will have to determine now, what in your project revolves around a user credit system.

  • What actions allow users to earn credits in your website?
  • What can they spend the store credits on?

Need A User Credits Shortcode?

Sweet, we now have a working user credit system for WordPress. But, we want a simple shortcode to display the total credits a logged in user has. Just an example of course. I can think of a few shortcodes that a user credits system might need.

First, let’s register our action via a new method. We can create a method for loading any hooks or actions that we want to tie into.

	/**
	 *
	 * Set Init Hooks.
	 *
	 */
	public function init_hooks() {
		
		// Register Credit Shortcodes
		add_action( 'init', array($this, 'register_shortcodes'));
	}

Now let’s make sure we fire this method in our construct for the the class.

	/**
	 *
	 * Constructor
	 *
	 */
	public function __construct() {
		/*
		*	Setup Our User Data
		*/
		$this->set_user_data();
		
		/*
		*	Run Our Hooks
		*/
		$this->init_hooks();

		/*
		*	Create An Action To Tie Into Later.
		*/
		do_action( 'user_credits_loaded' );
	}

Finally, we need to register our shortcodes handler.

	/**
	 *
	 * Register Custom Shortcodes For User Credits
	 *
	 */
	public function register_shortcodes(){
		// Registered Shortcodes
		add_shortcode('ensure_user_credits',array($this,'ensure_user_credits_build'));
	}

Now let’s create the base method that will hold the shortcode markup. You can always modify it to taste but for now we will keep it simple.

	/*
	*
	*	Simple Shortcode To Show Current Users Total Credits.
	*
	*	Usage: [ensure_user_credits]
	*
	*/
	public function ensure_user_credits_build($atts, $content = null){
		extract(shortcode_atts(array(
		  "class" => '',		
		  "format" => true,		
	   	), $atts));
		ob_start(); 
		$total = $this->activeUserCredits;
		?>

		<div class="user-credits">
		<?php 
		if($format){
			$total = number_format($total);
		}
		if($total == 1){
			echo $total .' Credit';
		} else {
			echo $total .' Credits';
		}
		 ?>
		</div>

	<?php
		return ob_get_clean();
	}

As you can see, the shortcode is inside our class so we can just access the property to get the current users total credits. We created an option in the shortcode to enable or disable number format but that’s it.. FYI, number format just adds commas where you would expect in larger numbers.

You can insert this shortcode to display your users total credits anywhere you like. Just as a side note, you can most certainly build this same shortcode outside of the class. You would just use the get total method to get the number instead.

The Full WordPress User Credits Class

<?php 
namespace Ensure;
/*
*   ***** WordPress User Credits System *****
*
*	A Simple Class For In-House User Credits In WordPress
*
*/
// No Direct Access
if ( ! defined( 'WPINC' ) ) {die;} // end if



// Create the Credits Class
class Credits {

	/**
	 * User Meta Key
	 *
	 * @var int
	 */	
	public $creditsKey = 'ensure_user_credits';
	
	/**
	 * Current User
	 *
	 * @var int
	 */
	public $user = null;	
	/**
	 * Easy Active User
	 *
	 * @var int
	 */
	public $activeUser = false;	
	/**
	 * Active User Credits Count
	 *
	 * @var int
	 */
	public $activeUserCredits = 0;			
    /**
	 *
	 * The single instance of the class.
	 *
	 * Credits
	 *
	 */
	protected static $_instance = null;
	/**
	 *
	 * The Instance
	 *
	 */
	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	/**
	 *
	 * Constructor
	 *
	 */
	public function __construct() {
		/*
		*	Setup Our User Data
		*/
		$this->set_user_data();
		
		/*
		*	Run Our Hooks
		*/
		$this->init_hooks();

		/*
		*	Create An Action To Tie Into Later.
		*/
		do_action( 'user_credits_loaded' );
	}
	/**
	 *
	 * Set Init Hooks.
	 *
	 */
	public function init_hooks() {
		
		// Register Credit Shortcodes
		add_action( 'init', array($this, 'register_shortcodes'));
	}
	/**
	 *
	 * Set Init User Data.
	 *
	 */
	public function set_user_data() {
		
		// Get The User Object
		$user = wp_get_current_user();
		
		// If Is User Is Logged In
		if($user->exists()){
			
			// Set The User Object
			$this->user = $user;
			
			// Set Our Easy Active User Detect
			$this->activeUser = true;
			
			// Set Our Active Users Credit Count
			$this->activeUserCredits = get_user_meta($this->user->ID,$this->creditsKey, true);
			
			// Incase The User Doesn't Have Credits 
			if(!is_int($this->activeUserCredits)){
				// Let's Make Sure The Credits Default Back To 0
				$this->activeUserCredits = 0;
			}
			
		}
	}
	/**
	 *	
	 * Get The Current Users Credit Count
	 *	 
	 */
	public function get_total() {
		return $this->activeUserCredits;
	}	
	/**
	 *	
	 * Updates User Credits Count
	 *	 
	 */
	public function update_total($difference,$operator = '-') {
		// If By Chance The Update Runs For Logged Out User Somehow, Tame Down.
		if(!$this->activeUser){
			return false;
		}
		
		// Let's Update The Users Credits
		if($operator == '-'){
			$this->activeUserCredits = $this->activeUserCredits - $difference;
		}
		if($operator == '+'){
			$this->activeUserCredits = $this->activeUserCredits + $difference;
		}
		
		// Then Update The Value
		$status = update_user_meta( $this->user->ID, $this->creditsKey, $this->activeUserCredits);
		
		// Returns A Confirmation The All Updated!
		return $status;
	}
	/**
	 *
	 * Exchange Credits Between Users
	 *
	 */
	public function exchangeBetweenUsers($recieverID,$amount,$requestType = 'send') {
		
		// Here We Make Sure The User Is Legit 
		$recievingUser = get_user_by('id',$recieverID);
		
		// A Quick Double Check To Confirm They Are In The Users Database
		if(!is_int($recievingUser->ID) || !$recievingUser->ID > 0){
			return false;
		}
		
		// Get The Recieving Users Credits Total
		$recievingUserCredits = get_user_meta( $recieverID, $this->creditsKey, true);
		
		// If This User Hasn't Had Credits Before, Set as 0; 
		if(!is_int($recievingUserCredits)){
			$recievingUserCredits = 0;
		}
		
		// Handle The Send Request
		if($requestType == 'send'){
			
			// Make Sure The Send Has The Funds
			if(!$this->activeUserCredits >= $amount){
				return array('error'=>__('Not Enouph Credits','ensure'));
			}
			
			// Update The Recievers Credits
			$recievingUserCredits = $recievingUserCredits + $amount;
			
			// Update The Current Users Credits
			$this->activeUserCredits = $this->activeUserCredits - $amount;
			
			// Then Update The Values
			// Starting With The Reciever
			$status = update_user_meta( $recieverID, $this->creditsKey, $recievingUserCredits);
			
			// If The Recievers Credits Added Properly
			if($status !== 0){
				$status = update_user_meta( $this->user->ID, $this->creditsKey, $this->activeUserCredits);
				// 
				if($status !== 0){
					return true;
				} else {
					// Backup Operations To Settle The Score
					// Let's Restore The Senders Funds
					$this->activeUserCredits = $this->activeUserCredits + $amount;
					// Then Update
					$status = update_user_meta( $this->user->ID, $this->creditsKey, $this->activeUserCredits);
					// 
					if($status !== 0){
						return true;
					} else {
						// Report The Issue To Ourselves
						$data = array(
							'recipientID'=>$recieverID,
							'senderID'=>$this->user->ID,
							'amount'=>$amount,
							'requestType'=>$requestType
						);
						// Send The Data Through The Action For Later Notification Additions Such As Emails.
						do_action('user_credits_refund_error',$data);
					}
				}
			}
		}
	}
	/**
	 *
	 * Register Custom Shortcodes For User Credits
	 *
	 */
	public function register_shortcodes(){
		// Registered Shortcodes
		add_shortcode('ensure_user_credits',array($this,'ensure_user_credits_build'));
	}
	/*
	*
	*	Simple Shortcode To Show Current Users Total Credits.
	*
	*	Usage: [ensure_user_credits]
	*
	*/
	public function ensure_user_credits_build($atts, $content = null){
		extract(shortcode_atts(array(
		  "class" => '',		
		  "format" => true,		
	   	), $atts));
		ob_start(); 
		$total = $this->activeUserCredits;
		?>

		<div class="user-credits">
		<?php 
		if($format){
			$total = number_format($total);
		}
		if($total == 1){
			echo $total .' Credit';
		} else {
			echo $total .' Credits';
		}
		 ?>
		</div>

	<?php
		return ob_get_clean();
	}

}

Creative Ways To Use A User Credits System In WordPress

I decided to list a few creative ways that you could use a user credits plugin in WordPress.

Ways To Earn User Credits

  • Newsletter Opt-in
  • Email confirmation
  • Reading Free Content To Unlock Premium Content
  • Sharing to social media
  • Referring a friend
  • Shopping and buyer rewards

Ways To Let Users Spend Credit

Typically you already have a service or product to offer, but if your still looking for ways to let your users spend their store credit, here goes a few user credits system ideas.

  • Store Merchandise
  • Timed Coupons
  • Shoutouts
  • Retweets from official profile
  • Badges

I found that list a little harder based on every project is different. You should certainly make sure the benefits of a user store credits system are integrated in what you do!

Wrapping up

I hope this tutorial helps you understand what steps to take in order to create this type of user credit system with WordPress. If you have questions about anything here or find bugs, please leave your comments below. You can download the full version of this user credits WordPress plugin. Learn, modify & create something really cool. If you come up with some really cool User Credits System features, maybe we can include them in this posts for others to use.