How to build a custom WordPress plugin

WordPress is a big topic here at Optimyz. Over the years, of the 500+ websites we’ve built, about 450 were built with WordPress. If you’re wondering why we love WordPress so much, here are just a few reasons: It offers unmatched functionality through thousands of plugins; The content management system is versatile, especially since the Gutenberg update and new blocks; It’s easy for clients to manage their own content updates; and, best of all, it’s open source and free.

But what happens when your website requires custom functionality that can’t be handled by plugins or other tools that integrate with WordPress? For example, say you need a more complex, multi-level account management system to handle 3 or 4 types of users, each with custom functionality?

You probably guessed it – you need to build a custom WordPress plugin! We’ve built about over 100 custom plugins over the years, so we thought it would make sense to explain a little bit out our process. For anyone interested in learning the key steps to building their own WordPress plugin, read on. As long as you have at least a beginner level of development experience, including PHP, HTML, and CSS, you’re ready to get started.

1.0 WordPress

First, a few more notes about WordPress. WordPress is the most used website building platform and content management system, with an estimated 30% market share worldwide (so it must be good!) It uses PHP and MySQL and is open source software, making it 100% free. With a vast community of designers, developers, and bloggers, it’s a great choice for your next website. If you’re just getting started with website development, it’s highly recommended you learn about it.

2.0 The Basic Functionality of WordPress

This image has an empty alt attribute; its file name is coding-1024x415.jpg

WordPress plugin consists of a single file or group of files. We use plugins to improve WordPress site performance and functionality to nearly any aspect of your website. While simple plugins may offer a specific feature, such as an interactive image slider, more sophisticated powerhouse plugins, such as Woo-commerce, offer, complete e-commerce functionality wrapped up in a single plugin. There are two important factors in plugins called named actions and filters. The plugin will run specific functionality with the help of hooks.

2.1 Tools and Software

Hooks assist action to complete WordPress events like generating new users or deleting pages. We can also publish posts or load header and footer area with the help of actions. Check heck the following code, which is an action that performs preset functionality in the control panel.

add_action( 'admin_menu', ‘add_admin_menu' );

2.2 Filters

A filter function receives unmodified data and modifies it according our logic. Filters reside between the database and Chrome of your browser. The perform a function, such as the WordPress is creating a new page or post in being published.  Check the code below:

add_filter( 'comment_text',  'filter_words' );
function filter_words( $data ) {
// filter comment words and return the modified comment
}

Here, the filter function is comment_text and the callback filter is filter_words. The back filter will receive the comment as unmodified data and modify it.

Let’s Begin. Once you’ve got this far – and have a clear objective of exactly what your plugin is going to do – you’re ready to get started Visit  http://wordpress.org/ and install the latest version of WordPress. We are using here 5.2 WordPress version. Now I will build the plugin again from scratch and show you the functionality step by step.

A plugin can consist of one simple PHP file or a group of CSS, Jas and PHP files. You can find WordPress plugins in the /wp-content/plugins/directory file. You can place the plugin directly here If it contains one single PHP file. Otherwise, you should create a new folder and keep all necessary files.

First, we will create a folder and name it wp-finder-simple.  Now create a PHP file named wp-finder-simple.php and store it in the wp-finder-simple folder. Launch wp-fonder-simple.php file using an integrated development environment (IDE) application.  Next, you must add some header data, such as:

<?php
/*
Plugin Name: Finder - Free visitor analysis plugin for WordPress
Plugin URI: http://wp-finder.com/
Description: Finder will make your visitor analysis experience easier and faster than before. You can now grab all necessary data from the Google analytics and see their location, device category and demographic data. Not only that, Finder will help you to track the visitors as you have details report. And guess what It is completely free.
Version: 1
Author: Mordy Karsch
Author URL:
www.optimyzinteractive.com
License: FlohfText Domain: wp-finder-simple
*/

Next, save the wp-finder.php file. Launch your chrome browser and open the wp-admin/plugins.php file. You will find there all preset plugins what you have already saved in the wp-content/plugins/directory. You will find there a new plugin too named “Finder”. Boom!! You have done it. Congratulations!!

We’ll next code in an Object-Oriented Style (OOP) in PHP. The following code is a basic skeleton. You can use it too to develop your next plugin.

The header has informed WordPress that we are making a plug in. So technically the plugin has been already created. But it still doesn’t work, of course, since still have to code it.

class WP_finder_Simple{

 // Constructor
    function __construct() {

        add_action( 'admin_menu', array( $this, 'wpa_add_menu' ));
        register_activation_hook( __FILE__, array( $this, 'wpa_install' ) );
        register_deactivation_hook( __FILE__, array( $this, 'wpa_uninstall' ) );
    }

    /*
      * Actions perform at loading of admin menu
      */
    function wpa_add_menu() {

        add_menu_page( 'finder simple', 'Finder', 'manage_options', 'finder-dashboard', array(
                          __CLASS__,
                        'wpa_page_file_path'
                        ), plugins_url('images/wp-finder-logo.png', __FILE__),'2.2.9');

        add_submenu_page(‘finder-dashboard', 'Finder simple' . ' Dashboard', ' Dashboard', 'manage_options', 'finder-dashboard', array(
                              __CLASS__,
                            'wpa_page_file_path'
                            ));

        add_submenu_page( 'finder-dashboard', 'Finder simple' . ' Settings', '<b style="color:#f9845b">Settings</b>', 'manage_options', 'finder-settings', array(
                              __CLASS__,
                            'wpa_page_file_path'
                            ));    }    /*
    * Actions perform on loading of menu pages
    */
    function wpa_page_file_path() {    }
    /*
    * Actions perform on activation of plugin
    */
    function wpa_install() {    }
    /*
    * Actions perform on de-activation of plugin
    */
    function wpa_uninstall() {    }
}
new WP_Finder_Simple();

Are you having brain fade? Don’t worry. I’ll review the above code. WP_Finder_Simple is a class. To avoid conflict with the other plug in classes, you should choose a unique name. We use _construct() as a constrictor function to  extract new object.

new WP_Finder_Simple(); We will install and store our new project here. 

In the __construct() function, we are running multiple WordPress hooks which run callback functions and performs the required functionality:

We will use several WordPress hooks in the _construct() function to complete the necessary functionality:

add_action( 'admin_menu', array( $this, 'wpa_add_menu' ));

function wpa_add_menu() {

// statements to add menu

}

With the help of ‘admin_menu’ now we will perform callback function wpa_add_menu.

A new menu will be created on the left side of our dashboard. Now visit WordPress documentation to find ‘admin_menu’ and wpa_add_menu. You can also explore add_submenu_page.

You can have two more construct functions named register_activation_hook and register_deactivation_hook. These two hooks will help to activate and deactivate the plugin. 

Click the save button and refresh your chrome browser to reload the dashboard. Now see the magic. You will find a new file named finder on the left side of the wp admin dashboard. Finder menu consists of two sub-menus- dashboard and setting. 

+ /wp-content/plugins/wp-finder-simple/images/wp-analytics-logo.png (create an image with 16px * 16px dimensions)

+ /wp-content/plugins/wp-finder-simple/wp-finder-simple.php (main plugin file)

+ /wp-content/plugins/wp-finder-simple/css/

+ /wp-content/plugins/wp-finder-simple/includes/

+ /wp-content/plugins/wp-finder-simple/views/+ /wp-content/plugins/wp-finder-simple/lib/

The extra directories like /CSS will hold the CSS files to redesign the algorithm in the plugin and save in the separate pages. The whole procedures will be completed in the plugin dashboard and setting pages. Now scroll to the picture folder and place your logo there. Change the file name and make it /wp-content/plugins/wp-finder-simple/images/wp-finder-logo.png.

Connect API Library

We will grab the visitor’s data from Google analytics, we need need third-party APIs to collect, store and analyze ranking data. In this case, we will use APIs provided by Google. Google API Client library provides a good number of Google APIs such Google+, Google analytics drive, YouTube etc. We will collect YouTube data using Google APIs and store the data in the Google drive. 

Next, get the library (PHP version) from Google or GitHib, unzip it, and store it in the directory. Now, the file sequence will look like /wp-content/plugins/wp-finder-simple/lib/google-api-php-client-master/.

Now, we will work with the APIs. Place all APIs in the plugin file to reach Google Analytics. Next, we’ll create accounts on the Google developers console and connect it with clientID, ClientSecret, etc. Put all parameters in the_construct function and the file sequence will look like:

// Constructor
function __construct() {

    if ( !class_exists( 'Google_Client' ) ) {

        require_once dirname(__FILE__) . '/lib/google-api-php-client-master/src/Google/Client.php';
        require_once dirname(__FILE__) . '/lib/google-api-php-client-master/src/Google/Service/Analytics.php';
    }

    $this->client = new Google_Client();
    $this->client->setApprovalPrompt( 'force' );
    $this->client->setAccessType( 'offline' );
    $this->client->setClientId( '958799092305-pfb9msi30152k3lfakbgauspuqr01g1d.apps.googleusercontent.com' );
    $this->client->setClientSecret( 'SUhMQfFcAwaIHswQtmw4utyh' );
    $this->client->setRedirectUri( 'urn:ietf:wg:oauth:2.0:oob' );
    $this->client->setScopes( 'https://www.googleapis.com/auth/analytics' );
    $this->client->setDeveloperKey( 'AIzaSyAn-70Vah_wB9qifJqjrOhkl77qzWhAR_w' );

    try{

        $this->service = new Google_Service_Finder( $this->client );
        $this->wpa_connect();

    }
    catch ( Google_Service_Exception $e ) {

    }

    add_action( 'admin_menu', array( $this, 'wpa_add_menu' ) );
    add_action( 'admin_enqueue_scripts', array( $this, 'wpa_styles') );

    register_activation_hook( __FILE__, array( $this, 'wpa_install' ) );
    register_deactivation_hook( __FILE__, array( $this, 'wpa_uninstall' ) );

We have added Google_Client and Google_Service_Analytics in the directory. wpa_connect helps us to establish the connection. Save the access_token. We will use it to scratch data.

Now write the code in the file directory:

public function wpa_connect() {

    $access_token = get_option('access_token');

    if (! empty( $access_token )) {

        $this->client->setAccessToken( $access_token );

    }
    else{

        $authCode = get_option( 'access_code' );

        if ( empty( $authCode ) ) return false;

        try {

            $accessToken = $this->client->authenticate( $authCode );
        }
        catch ( Exception $e ) {
            return false;
        }

        if ( $accessToken ) {

            $this->client->setAccessToken( $accessToken );
            update_option( 'access_token', $accessToken );

            return true;
        }
        else {

            return false;
        }
    }

    $this->token = json_decode($this->client->getAccessToken());
    return true

Use pt_get_analytics_accounts to grab the web data using the Google Analytics account. pa_get_analytics_dashboard  will collect the required data within few minutes. You can use this code again if necessary to fetch Google data.

/**
* Get profiles from user Google Analytics account profiles.
*/
public function pt_get_analytics_accounts() {

        try {

            if( get_option( ‘access_token’ ) !=” ) {
                $profiles = $this->service->management_profiles->listManagementProfiles( “~all”, “~all” );
                return $profiles;
            }

            else{
                echo ‘<br /><p class=”description”>’ . __( ‘You must authenticate to access your web profiles.’, ‘wp-finder’ ) . ‘</p>’;
            }

        }

        catch (Exception $e) {
            die(‘An error occured: ‘ . $e->getMessage() . ‘\n’);
        }
}

/*
* This function grabs the data from Google Analytics
* For dashboard.
*/

public function pa_get_analytics_dashboard($metrics, $startDate, $endDate, $dimensions = false, $sort = false, $filter = false, $limit = false){

        try{

            $this->service = new Google_Service_Analytics($this->client);
            $params        = array();

            if ($dimensions){
                $params[‘dimensions’] = $dimensions;
            }
            if ($sort){
                $params[‘sort’] = $sort;
            }
            if ($filter){
                $params[‘filters’] = $filter;
            }
            if ($limit){
                $params[‘max-results’] = $limit;
            }

            $profile_id = get_option(“pt_webprofile_dashboard”);
            if (!$profile_id){
                return false;
            }

            return $this->service->data_ga->get(‘ga:’ . $profile_id, $startDate, $endDate, $metrics, $params);

        }

        catch ( Google_Service_Exception $e ) {

          // Show error message only for logged in users.
            if ( is_user_logged_in() ) echo $e->getMessage();

        }
    }

Develop A WordPress Settings Page

A setting page helps ensure flexibility for customization and promotion, so we need a setting page too to offer a good customer experience. Next, we’ll develop a settings page and connect it with our plugin. The setting page will have two tabs, one for the authentication and the other for product information. Plugin users will fetch data using the Google Analytics accounts  in the authentication tab.    

Check the following code. We will use the code to develop our setting page. You will find the code in the /includes folder named finder-setting-php.

<?php
  $wp_finder = new WP_Finder_Simple();

  if (! function_exists( ‘curl_init’ ) ) {
      esc_html_e(‘This plugin requires the CURL PHP extension’);
    return false;
  }

  if (! function_exists( ‘json_decode’ ) ) {
    esc_html_e(‘This plugin requires the JSON PHP extension’);
    return false;
  }

  if (! function_exists( ‘http_build_query’ )) {
    esc_html_e(‘This plugin requires http_build_query()’);
    return false;
  }

  $url = http_build_query( array(
                                ‘next’          =>  admin_url(‘admin.php?page=finder-settings’),
                                ‘scope’         =>  ‘https://www.googleapis.com/auth/analytics’,
                                ‘response_type’ =>  ‘code’,
                                ‘redirect_uri’  =>  ‘urn:ietf:wg:oauth:2.0:oob’,
                                ‘client_id’     =>  ‘958799092305-pfb9msi30152k3lfakbgauspuqr01g1d.apps.googleusercontent.com’
                                )
                          );

// Save access code
  if ( isset( $_POST[“save_code”]) and isset($_POST[“access_code”]) ) {

    if( $wp_finder->wpa_save_data( $_POST[“access_code”] )){
        $update_message = ‘<div id=”setting-error-settings_updated” class=”updated settings-error below-h2″><p><strong>Access code saved.</strong></p></div>’;
    }
  }

// Clear Authorization and other data
  if (isset($_POST[ “clear” ])) {

delete_option( ‘access_token’ );   
delete_option( ‘access_code’ );
    $update_message = ‘<div id=”setting-error-settings_updated” class=”updated settings-error below-h2″>
                        <p><strong>Authentication Cleared login again.</strong></p></div>’;
  }

  // Saving Profiles
  if (isset($_POST[ ‘save_profile’ ])) {

    update_option( ‘pt_webprofile_dashboard’, $_POST[ ‘webprofile_dashboard’ ] );

    $update_message = ‘<div id=”setting-error-settings_updated” class=”updated settings-error below-h2″>
                        <p><strong>Your Google Analytics Profile Saved.</strong></p></div>’;
  }

?>

<div class=”wrap”>
  <span class=’opt-title’><span id=’icon-options-general’ class=’analytics-options’><img src=”<?php echo plugins_url(‘wp-finder/images/wp-analytics-logo.png’);?>” alt=””></span>
    <?php echo __( ‘finder Plugin Settings’, ‘wp-finder’); ?>

  <?php
  if (isset($update_message)) echo $update_message;

  if ( isset ( $_GET[‘tab’] ) ) $wp_finder-> pb_settings_tabs($_GET[‘tab’]);
  else $wp_finder->pa_settings_tabs( ‘authentication’ );

  if ( isset ( $_GET[‘tab’] ) )
    $tab = $_GET[‘tab’];
  else
    $tab = ‘authentication’;

// Authentication Tab section
  if( $tab == ‘authentication’ ) {
  ?>

  <form action=”<?php echo str_replace( ‘%7E’, ‘~’, $_SERVER[‘REQUEST_URI’]); ?>” method=”post” name=”settings_form” id=”settings_form”>
    <table width=”1004″ class=”form-table”>
      <tbody>
      <?php if( get_option( ‘access_token’ ) ) { ?>
        <tr>
          <p>Do you want to re-authenticate ? Click reset button and get your new Access code.<p>

        </tr>
        <tr>
          <th><?php esc_html_e( ‘Clear Authentication’, ‘wp-finder’ ); ?></th>
          <td><input type=”submit” class=”button-primary” value=”Reset” name=”clear” /></td>
        </tr>
      <?php
      }
      else { ?>
        <tr>
          <th width=”115″><?php esc_html_e( ‘Authentication:’ )?></th>
              <td width=”877″>
                    <a target=”_blank” href=”javascript:void(0);” onclick=”window.open(‘https://accounts.google.com/o/oauth2/auth?<?php echo $url ?>’,’activate’,’width=700,height=500,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=1,left=0,top=0′);”>Click here to Authenticate</a>
              </td>
        </tr>
        <tr>
              <th><?php esc_html_e(‘Your Access Code:’)?> </th>
              <td>
                <input type=”text” name=”access_code” value=”” style=”width:450px;”/>
              </td>
        </tr>
        <tr>
          <th></th>
          <td>
            <p class=”submit”>
              <input type=”submit” class=”button-primary” value = “Save Changes” name = “save_code” />
            </p>
          </td>
        </tr>
      <?php } ?>
      </tbody>
    </table>
  </form>
  <?php
  } // endif
// Choose profiles for dashboard and posts at front/back.
if( $tab == ‘profile’ ){
  $profiles = $wp_finder->pt_get_analytics_accounts();
  if( isset( $profiles ) ) { ?>
    <p><?php esc_html_e( ‘Select profile for dashboard data.’, ‘wp-finder’ ); ?></p>

    <form action=”<?php echo str_replace( ‘%7E’, ‘~’, $_SERVER[‘REQUEST_URI’]); ?>” method=”post”>
      <table width=”1004″ class=”form-table”>
        <tbody>
          <tr>
            <th width=”115″><?php esc_html_e( ‘Dashboard :’, ‘wp-finder’ );?></th>
            <td width=”877″>
                <select name=’webprofile_dashboard’ id=’webprofile-dashboard’>
                  <?php foreach ($profiles->items as $profile) { ?>
                  <option value=”<?php echo $profile[ ‘id’ ];?>”
                              <?php selected( $profile[ ‘id’ ], get_option( ‘pt_webprofile_dashboard’ )); ?>
                              >
                              <?php echo $profile[ ‘websiteUrl’ ];?> – <?php echo $profile[ ‘name’ ];?>
                  </option>
                  <?php } ?>
                </select>
            </td>
          </tr>
          <tr>
            <th></th>
            <td>
              <p class=”submit”>
                <input type=”submit” name=”save_profile” value=”Save Changes” class=”button-primary”>
              </p>
            </td>
          </tr>
          <?php } ?>
      </tbody>
    </table>
  </form>
<?php } ?>

</div>
</div>
</div>

Develop a Dashboard Page for the Plugin

The plugin settings page is ready. Now let’s work on the dashboard page. We’ll load the set of statistics in this page collected by the Google Analytics APIs. Can you remember the number of administration menu? We have two administration menus:

1 – Finder- Dashboard and 2: Finder-Settings

We already developed a setting page for the setting menu and a dashboard page named finder-dashboard.php for the dashboard menu. Copy the code and paste into the directory page named finder-dashboard.php

<?php
$wp_findar = new WP_Finder_Simple();

$start_date_val =   strtotime(“- 30 days”);
$end_date_val   =   strtotime(“now”);
$start_date     =   date( “Y-m-d”, $start_date_val);
$end_date       =   date( “Y-m-d”, $end_date_val);

?>
<div class=”wrap”>
  <span class=’opt-title’><span id=’icon-options-general’ class=’analytics-options’><img src=”<?php echo plugins_url(‘wp-finder-simple/images/wp-analytics-logo.png’);?>” alt=””></span>
    <?php echo __( ‘finder Simple Dashboard’, ‘wp-finder’ ); ?>

  <?php

  $acces_token  = get_option( “access_code” );
  if( $acces_token ) {

  ?>
  <div id=”col-container”>
    <div class=”metabox-holder”>
      <div class=”postbox” style=”width:100%;”>
          <div id=”main-sortables” class=”meta-box-sortables ui-sortable”>
            <div class=”postbox “>
              <div class=”handlediv” title=”Click to toggle”><br />
              </div>
              <span class=”hndle”>
                <span>
                    <?php
                    echo _e(‘Complete Statistics Starting From ‘, ‘wp-finder’);
                    echo _e(date(“jS F, Y”, strtotime($start_date)));
                    echo _e(‘ to ‘, ‘wp-finder’);
                    echo _e(date(“jS F, Y”, strtotime($end_date)));
                    ?>
                </span>

              <div class=”inside”>
                <?php

              // Country stats //

                $country_stats = $wp_finder->pa_get_analytics_dashboard( ‘ga:sessions’, $start_date, $end_date, ‘ga:country’, ‘-ga:sessions’, false, 5);
                if ( isset( $country_stats->totalsForAllResults )) {
                  include ROOT_PATH . ‘/views/country-stats.php’;
                  pa_include_country($wp_finder,$country_stats);
                }

              // End Country stats //

                $city_stats = $wp_finder->pa_get_analytics_dashboard( ‘ga:sessions’, $start_date, $end_date, ‘ga:city’, ‘-ga:sessions’, false, 5);
                if ( isset( $city_stats->totalsForAllResults )) {
                  include ROOT_PATH . ‘/views/city-stats.php’;
                  pa_include_city($wp_findar,$city_stats);
                }

              // Browser stats //

                $browser_stats = $wp_finder->pa_get_analytics_dashboard( ‘ga:sessions’, $start_date, $end_date, ‘ga:browser,ga:operatingSystem’, ‘-ga:sessions’,false,5);
                if ( isset( $browser_stats->totalsForAllResults ) ) {
                  include ROOT_PATH . ‘/views/browser-stats.php’;
                  pa_include_browser( $wp_finder,$browser_stats );
                }

              // End Browser stats //

                ?>
              </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <?php
  }
  else{
    print(_e( ‘You must be authenticate to see the Analytics Dashboard.’, ‘wp-finder’ ));
  }
  ?>
</div>

Next, I’ll working with the location stats in detail for better understanding. Hopefully all is clear.

$country_stats = $wp_finder->pa_get_analytics_dashboard( 'ga:sessions', $start_date, $end_date, 'ga:country', '-ga:sessions', false, 5);
if ( isset( $country_stats->totalsForAllResults )) {
  include ROOT_PATH . '/views/country-stats.php';
  pa_include_country($wp_finder,$country_stats);
}

Write pa_get_analytics_dashboard code in the main plugin class to fetch data from different locations and devices. For example, we will command ga:country and ga:sessions to fetch necessary data on the locations, devices and demographic behavior.

We’ll pass $country_stats data to a new page named pa_include_country. The page is located in a separate file named country-stats.php in the /views folder.

Next, visit the view folder. You will find there separate files for each location and device. You can manage large number of files using this folder.  

Now launch your chrome browser and create a file in the view folder. Write the following code there:

<?php
// View of Browser Statistics
function pa_include_browser( $current, $browser_stats ) {
?>
<div class=”data_boxes”>
  <div class=”data_boxes_title”><?php echo _e(‘BROWSERS STATS’, ‘wp-finder’);?><div class=”arrow_btn”></div></div>
  <div class=”data_container”>
    <?php
    if (!empty($browser_stats[“rows”])){ ?>
      <div class=”names_grids”>
                <?php foreach ($browser_stats[“rows”] as $c_stats){ ?>
                        <div class=”stats”>
                            <div class=”row-visits”>
                                <span class=”large-count”><?php echo $c_stats[2];?></span>
                            Visits
                            </div>
                            <div class=”visits-count”>
                                <i><?php  echo $c_stats[0];?> (<?php  echo $c_stats[1];?>)</i>
                            </div>
                        </div>
                <?php } ?>
            </div>
    <?php } ?>
  </div>
  <div class=”data_boxes_footer”>
      <span class=”blk”>
        <span class=”dot”></span>
        <span class=”line”></span>
      </span>
      <span class=”information-txt”><?php echo _e(‘listing statistics of top five browsers.’, ‘wp-finder’);?></span>
  </div>
</div>
<?php } ?>

Next, create a new file in the views folder and name it city-stats.php. Write the following code there: 

<?php
// View of City wise Statistics
function pa_include_city( $current, $country_stats ) {
?>
<div class=”data_boxes”>
    <div class=”data_boxes_title”>TOP CITIES <div class=”arrow_btn”></div></div>
        <div class=”data_container”>
            <?php
            if (! empty( $country_stats[“rows”] ) ) { ?>
            <div class=”names_grids”>
                <?php foreach ($country_stats[“rows”] as $c_stats){ ?>
                        <div class=”stats”>
                            <div class=”row-visits”>
                                <span class=”large-count”><?php echo $c_stats[1];?></span>
                            Visits
                            </div>
                            <div class=”visits-count”>
                                <i><?php  echo $c_stats[0];?> </i>
                            </div>
                        </div>
                <?php } ?>

            </div>
            <?php } ?>
        </div>
    <div class=”data_boxes_footer”>
        <span class=”blk”>
            <span class=”dot”></span>
            <span class=”line”></span>
        </span>
        <span class=”information-txt”>Listing statistics of top five cities.</span>
    </div>
</div>
<?php } ?>

Create another file in the views folder and name it country-stats.php. Now write the following code:

<?php
// View of Country wise Statistics
function pa_include_country( $current, $country_stats ) {
?>
<div class=”data_boxes”>
    <div class=”data_boxes_title”>TOP COUNTRIES <div class=”arrow_btn”></div></div>
        <div class=”data_container”>
            <?php
            if (! empty( $country_stats[“rows”] ) ) { ?>

            <div class=”names_grids”>
                <?php foreach ($country_stats[“rows”] as $c_stats){ ?>
                        <div class=”stats”>
                            <div class=”row-visits”>
                                <span class=”large-count”><?php echo $c_stats[1];?></span>
                            Visits
                            </div>
                            <div class=”visits-count”>
                                <i><?php  echo $c_stats[0];?></i>
                            </div>
                        </div>
                <?php } ?>

            </div>
            <?php } ?>
        </div>
    <div class=”data_boxes_footer”>
        <span class=”blk”>
            <span class=”dot”></span>
            <span class=”line”></span>
        </span>
        <span class=”information-txt”>Listing statistics of top five countries.</span>
    </div>
</div>
<?php } ?>

Make the Plugin Better with CSS

The plugin is done. Now we need to make it better. Adding callback function in the WordPress hook we load the CSS files. The system looks like this:

add_action( ‘admin_enqueue_scripts’, array( $this, ‘wpa_styles’) );

Connect the callback function with the  __construct function:

/**
* Styling: loading stylesheets for the plugin.
*/
public function wpa_styles( $page ) {

    wp_enqueue_style( ‘wp-finder-style’, plugins_url(‘css/wp-finder-style.css’, __FILE__));
}

In our plugin, we have to style our dashboard stats using CSS. Write the following CSS code in /css/wp-finder-style.css:

You’ll want to redesign the dashboard stats using CSS. Find the page named /css/wp-finder-style.css in the WP directory. We’ll leave this out since it’s pretty lengthy.

Final Words

If you completed everything correctly, your plugin is built and ready to use! Let’s
summarize the steps we took to get here:

1) Create a plugin folder in the WP directory and store necessary header information.

2) Use OOP to create a plugin class and add plugin menus.

3) Develop an interactive structure for the plugin to deal with CSS, images, and third-party libraries.

4) Initialize Google Analytics PHP Client library from Github and connect it to your plugin.

5) Develop a WordPress setting page for your plugin.

6) Develop a customized dashboard page for the plugin.

7) Make the plugin look better using CSS.

Hopefully everything made sense and you learned the key steps to build your own WordPress
plugin. Now it is your turn – good luck!

About shekhar

Shekhar is a WordPress and Full Stack developer with deep CSS, HTML, and PHP, React, API development, and lots of other stuff.

Get in touch with Optimyz