Automatic subscribers recognition in LiveAgent Knowledgebase for WordPress

In this example we'll show you how can you implement recognition of your subscribers in WordPress as regular customers in LiveAgent. As a result, your subscribers can visit LiveAgent Knowledgebase and see their own tickets and interact with them.
 
Goal:
Each subscriber will be registered also in LiveAgent with his email. As a result, after login in WordPress they can move freely to LiveAgent Knowledgebase and work with their tickets.
 
Requirements:
- your WordPress installation and your LiveAgent installation are on the same domain. For example shop.mydomain.com and support.mydomain.com
- API v1 Key
 
WordPress plugin code:
<?php
/*
Plugin Name: Custom LiveAgent example
Plugin URI: https://www.qualityunit.com/liveagent
Description: Example - How to authenticate subscribers from Wordpress into LiveAgent (on the same domain) as registered visitors
Author: QualityUnit
Version: 1.0.0
Author URI: https://www.qualityunit.com
License: GPL2
*/


if (!class_exists('liveAgentExampleThree')) {
    class 
liveAgentExampleThree
    
{
        const 
LIVEAGENT_URL 'https://mysupport.exmple.com/';
        const 
API_KEY '2afeca3e74c8c8ff60fed782053ec44a'// API v1
        
        
//we will use login/logout wordpress hooks
        
public function __construct()
        {
            
add_action('wp_login', array(
                
$this,
                
'handleLogin'
            
));
            
add_action('wp_logout', array(
                
$this,
                
'handleLogout'
            
));
            
add_action('user_register', array(
                
$this,
                
'handleSignup'
            
));
        }
        
        public function 
handleLogin($login)
        {
            
$user get_user_by('login'$login);
            if (
$user == null) {
                return;
            }
            if (!
in_array('subscriber'$user->roles)) {
                
// in case I'm not a subscriber - end
                
return;
            }
            
$laUser $this->getVisitorInfo($user->get('user_email'));
            if (
$laUser == null) {
                return;
            }
            
/* if I retrive valid response from LiveAgent, I can register "remember me" cookie. 
             * Wordpress and LiveAgent are on the same domain so one cookie is enough
             */
            
setcookie($laUser->browsercookiename$laUser->authtokentime() + 60 60 24 356'/');
        }
        
        public function 
handleSignup($user_id)
        {
            
//let's load newly created user
            
$user = new WP_User($user_id);
            
            
// fill all basic fields - you can find more in complete API reference here: https://support.qualityunit.com/840770-Complete-API-reference
            
$data = array(
                
'role' => 'R',
                
'name' => $user->user_firstname ' ' $user->user_lastname,
                
'email' => $user->user_email,
                
'apikey' => self::API_KEY
            
);
            
            
//we will create POST call to customers entity
            
$ch curl_init(self::LIVEAGENT_URL 'api/customers');
            
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
            
curl_setopt($chCURLOPT_POSTtrue);
            
curl_setopt($chCURLOPT_POSTFIELDS$data);
            
$response curl_exec($ch);
            
//here we can handle error result
        
}
        
        public function 
handleLogout($user_id)
        {
            
$user = new WP_User($user_id);
            if (
$user == null) {
                return;
            }
            if (!
in_array('subscriber'$user->roles)) {
                return;
            }
            
$laUser $this->getVisitorInfo($user->get('user_email'));
            if (
$laUser == null) {
                return;
            }
            
//on logout we must destrou our "remember me" cookie and also our session cookie from LiveAgent.
            
setcookie($laUser->browsercookiename''time() - 3600'/');
            
setcookie('visitor_la_sid'''time() - 3600'/');
        }
        
        
        private function 
getVisitorInfo($visitorEmail)
        {
            
//here we use entity customers
            
$ch curl_init(self::LIVEAGENT_URL 'api/customers/' urlencode($visitorEmail) '&apikey=' self::API_KEY);
            
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
            
$rawResult curl_exec($ch);
            if (!
$rawResult) {
                return 
null;
            }
            
            
$result json_decode($rawResult);
            if (!isset(
$result->response)) {
                return 
null;
            }
            if (isset(
$result->response) && isset($result->response->statuscode) && $result->response->statuscode != 0) {
                return 
null;
            }
            return 
$result->response;
        }
    }
}


$liveagent = new liveAgentExampleThree();
?>
 
Explanation
 
The most interesting part is the method getVisitorInfo()We are trying to load a specific visitor entity from all customers in LiveAgent: .../customers/specific_visitor@email
$ch curl_init(self::LIVEAGENT_URL 'api/?handler=customers/' urlencode($visitorEmail) '&apikey=' self::API_KEY);
 
We use another API call in handleSignup() method, but we must prepare POST data first:
$data = array(
    'role' => 'R',
    'name' => $user->user_firstname ' ' $user->user_lastname,
    'email' => $user->user_email,
    'apikey' => self::API_KEY
);
$ch curl_init(self::LIVEAGENT_URL 'api/customers');
 
And now we can launch and handle POST request:
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
curl_setopt($chCURLOPT_POSTtrue);
curl_setopt($chCURLOPT_POSTFIELDS$data);
$response curl_exec($ch);
 
Note: Do not forget to attach apikey to all your API requests.
 
Other processing is practically the same as in this SSO example.
 
You can find out more about this call (complete syntax, mandatory and optional fields and example results in XML and JSON format) in our API reference.
 

My LiveAgent and my WordPress are on different domains. What then?

If your two installations are on completely different domains, then the above example won't work. You have to extend it a little. The key would be to put an authentication cookie from your WordPress domain to your LiveAgent domain. 
LiveAgent has a mechanism for this using JavaScript and frames. The security here is guaranteed by sending only a security hash through an iFrame. Also, only registered LiveAgent user can be successfully logged in. You have to provide their authentication cookie and their email. Also you need setup an SSO API key in your LiveAgent. Let's see this process in an extended WordPress example plugin code below.
 
Requirements:
- API v1 Key
- SSO API key
- LiveAgent version 5.24 and above
<?php
/*
Plugin Name: LiveAgent example Two
Plugin URI: https://www.qualityunit.com/liveagent
Description: Example 2 - How to authenticate subscriber from Wordpress into LiveAgent customer portal (on different domains) as registered visitors
Author: QualityUnit
Version: 1.0.3
Author URI: https://www.qualityunit.com
License: GPL2
*/


if (!class_exists('liveAgentExampleTwo')) {
    class 
liveAgentExampleTwo
    
{
        const 
LIVEAGENT_URL 'https://mysupport.exmple.com/';
        const 
API_KEY '4a46eb8373c39a8d70d496a94b53fe89'; // API v1
        const SSO_KEY 'a48c6a5d8d70d496a94b5d2a2cfe2a4a';
 
        const ALLOWED_ROLES array('subscriber', 'editor'); // only affiliates with these roles will be automatically logged in
        //processing of the auth - we need to run JavaScript code
        
public function processAuth()
        {
            
/* we will use LiveAgent standard tracking code
             * note: if you already have LiveAgent button on your page, you won't need this peace of code. Just make sure
             * that rest of it is above your button code (so trackjs.php can fully load) 
             */
            
echo '<script type="text/javascript" id="la_x2s6df8d" src="'.self::LIVEAGENT_URL.'scripts/track.js"></script>';
            
$actions get_option('la_actions');
            if (
$actions == null) {
                return;
            }
            
//now bit magic - we process all actions in queue.
            
foreach ($actions as $action) {
                
//if we have logout action here then proceed
                
if ($action['action'] == 'logout') {
                    
$user get_user_by('login'$action['user']);
                    if (empty($user)) {
                      continue;
                    }
                    
$result $this->logoutVisitor($user);
                    if (
$result === true) {
                        
$this->clearAction('logout'$action['user']);
                        break;
                    }
                }
                if (
$action['action'] == 'login') {
                    
//if we have login action here, lets be sure its really me
                    
$user wp_get_current_user();
                    if (
$action['user'] != $user->get('user_login')) {
                        continue;
                    }
                    
$result $this->loginVisitor($user);
                    if (
$result === true) {
                        
$this->clearAction('login'$user->get('user_login'));
                        break;
                    }
                }
            }
        }
        
        
//clear actions queue
        
private function clearAction($actionName$login)
        {
            
$actions get_option('la_actions');
            
$clearedActions = array();
            foreach (
$actions as $key => $action) {
                if (
$action['user'] = !$login && $action['user'] != '' && $action['action'] == $actionName) {
                    
$clearedActions[] = $actions[$key];
                }
            }
            
update_option('la_actions'$clearedActions);
        }
        
        private function 
createMagicHash($userEmail$userAuthToken)
        {
            return 
md5($userEmail $userAuthToken self::SSO_KEY);
        }
        
        
//logout JavaScript
        
private function logoutVisitor($user)
        {
            if (empty($user)) {
                return;
            }
            
//load visitor info
            
$visitorInfo $this->getVisitorInfo($user->get('user_email'));
            if ($visitorInfo === null) {
                echo '<!-- Error: No visitor loaded by user email -->';
                return false;
            }
            
//create magic hash
            
$hash $this->createMagicHash($user->get('user_email'), $visitorInfo->authtoken);
            
//call logout function from our tracking JavaScript
            
echo '<script type="text/javascript">
            LiveAgentTracker.logoutUserOnServer(\'' 
$hash '\');
            </script>'
;
            return 
true;
        }
        
        
//login JavaScript
        
private function loginVisitor($user)
        {
            
//load visitor info
            
$visitorInfo $this->getVisitorInfo($user->get('user_email'));
            if ($visitorInfo === null) {
                echo '<!-- Error: No visitor loaded by user email -->';
                return false;
            }


            //create magic hash
            
$hash        $this->createMagicHash($user->get('user_email'), $visitorInfo->authtoken);
            
//call login function from our tracking JavaScript
            
echo '<script type="text/javascript">
            LiveAgentTracker.loginUserOnServer(\'' 
$hash '\',\'kb\');
            </script>'
;
            return 
true;
        }
        
        
//add new action to action queue
        
private function addAction($actionName$login)
        {
            
$actions get_option('la_actions');
            if (
$actions == null) {
                
$actions = array();
            }
            
            
$actions[] = array(
                
'action' => $actionName,
                
'user' => $login
            
);
            
update_option('la_actions'$actions);
        }
        
        
//WP login hook
        
public function handleLogin($login)
        {
            
$user get_user_by('login'$login);
            if (
$user == null) {
                return;
            }
            if (!
in_array($user->roles[0], self::ALLOWED_ROLES)) {
                return;
            }
            
$this->addAction('login'$login);
        }
        
        
//WP logout hook
        
public function handleLogout($user_id)
        {

                       $user = new WP_User($user_id);
            
$this->addAction('logout'$user->get('user_login'));
        }
        
        
//API call for getting visitor info
        
private function getVisitorInfo($visitorEmail)
        {
            
//here we use entity customers
            
$ch curl_init(self::LIVEAGENT_URL 'api/?handler=customers/' urlencode($visitorEmail) '&apikey=' self::API_KEY);

            curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
            
$rawResult curl_exec($ch);
            if (!
$rawResult) {
                echo '<!-- Could not load visitor info: cURL error: '.curl_error($ch).' -->';
                return 
null;
            }
            
            
$result json_decode($rawResult);
            if (!isset(
$result->response)) {
                return 
null;
            }
            if (isset(
$result->response) && isset($result->response->statuscode) && $result->response->statuscode != 0) {
                return 
null;
            }
            return 
$result->response;
        }
        
        
/*
         * WordPress stuff
         */
        
        
public function settingsInit()
        {
            
register_setting('la_general''la_actions');
        }
        
        public function 
__construct()
        {
            
add_action('admin_init', array(
                
$this,
                
'settingsInit'
            
));
            
add_action('wp_login', array(
                
$this,
                
'handleLogin'
            
));
            
add_action('wp_logout', array(
                
$this,
                
'handleLogout'
            
));
            
add_action('wp_footer', array(
                
$this,
                
'processAuth'
            
), 99);
            
add_filter('admin_footer_text', array(
                
$this,
                
'processAuth'
            
), 99);
            
add_filter('logout_url', array(
                
$this,
                
'logoutUrl'
            
));
        }
        
        
//we need to redirect used after logout right to main page
        
public function logoutUrl($logout_url)
        {
            
$redir get_option('siteurl');
            return 
$logout_url '&amp;redirect_to=' urlencode($redir);
        }
        
        
    }
}


$liveagent = new liveAgentExampleTwo();
?>
 
Explanation
Basically, we need to run JavaScript code (to write auth cookie to another domain) after login/logout in WordPress. This won't be possible for users who does not allow 3rd party cookies in their browsers so you might consider letting them know.
That is a bit complicated and can not be done directly so we created actions queue. Just after login/logout we add an action to this queue. When user is redirected finally to some WordPress page (or admin panel) we will check this action queue and login/logout user to/from LiveAgent.
 
We use LiveAgent tracker javascript code to perform login/logout actions:
<script type="text/javascript" id="la_x2s6df8d" src="https://mysupport.exmple.com/scripts/track.js"></script>
 
Note: If you already have LiveAgent button on your page you don't need this because the code is already there. Just make sure that login/logout javascript calls are bellow your button code.
 
Login and logout JavaScript code:
<script type="text/javascript">
    LiveAgentTracker.loginUserOnServer('magic_hash', 'kb');
</script>
 
<script type="text/javascript">
    LiveAgentTracker.logoutUserOnServer('magic_hash');
</script>
 
Magic hash here is an MD5 hash of user email, user auth token and your SSO key - see createMagicHash method in the example above.
 
NOTE: If you are testing this with your localhost installation of WordPress please make sure your cURL is set to use a certificate (as the communication with the API is through HTTPS).