Monday, December 12, 2011

Let's add an online chat to the web site, or p3chat plugin for wordpress

In this article I will explain how to add an p3chat online chat solution to web sites powered by Wordpress platform.
First, let me highlight the benefits of this particular service:
  • both free edition (1 operator, 1 IM channel, 1 department) and commercial editions for advanced users (starting at $6/mo) are available.
  • the chat does not slow down page load time. Actually, the script doesn't even start loading before chat is "activated";
  • localization (interfaces in Russian, French, Spanish and more);
  • cross-browser support;
  • support for a wide range of IM protocols for chat operators (in my case -- for my travel agency representatives). This includes XMPP (jabber), ICQ, Yahoo.

Now let's proceed and try to implement this easy chat solution.

Register your account for the online chat service

 

First of all we need to  register with the service. You don't have to use your customer support representative's contact info. It's best to use your own contact info, and your password, to do that.
I used my XMPP (jabber) account within our agency domain powered by Yandex services (analogue to Google Apps).

 Let's go ahead and configure the service for our needs. The service allows the web site visitor to talk to different sites of your organization, but the free version only supports a single site. That's why I used my organization name as the site name. Now you can choose your user interface language (English is default) and customize the greeting message. It will be displayed as the first operator message when the visitor activates the chat. Free version also limits you to a single operator.

Configure the operator


 

After saving your changes, you can go ahead and configure your single operator. Set a proper operator screen name -- you don't want your visitor to talk to someone named "operator". It's far more pleasant being greeted by "Natalie". Don't forget to set the operator language (I used Russian).

Choose the chat button that will appear on your web site

Let's continue configuring the chat for our web site, and we're getting closer. Now you can configure the button that your web site visitors will see and click to activate the online chat. You can also configure the button location on the page – see "Floating button" and "Static button" sections. As you can see from the name, the floating button will be always visible on the left, right, top or bottom side of the web page, and it will not scroll when the page content is scrolled. If you use the static button, you are free to place it wherever you like. Let's say, in the "Contact Us" section.
For the button design (meaning the button image) you can either upload a custom image, or specify an existing button design URL. If your language is any other than English, you will have to worry about the button design right there as the service provides you with English design by default.

Finish configuring the service

 

For the purposes of my agency, I needed to allow visitors leaving offline messages. You can do the same by enabling "Accept offline messages" option and entering the contact email address. I entered the email alias address so that messages left by the web site visitors would be delivered to all travel agency representatives in case the particular operator is on vacation. After you specify the contact email address, you will receive a confirmation email and will need to confirm the email address.
If you wish to be able to review the whole history of conversations between visitors and operators, you will need to enable "Save the whole conversation history" option in the "Message history" section.
The last thing for you to configure is the chat window size and position. The online chat is not using pop up window technique. Using a pop up window could get your web site banned from search engines and would force  your users to go through a bunch of browser security dialogs. Instead the chat is loaded in a safe and friendly AJAX dialog (to be precise, a regular set of HTML tags with style=“position:absolute”). If you are using Russian or other international localizations, I would recommend to set the window width to no less than 320, otherwise your visitors might not see parts of the UI labels.

Integrate the chat service into your wordpress web site

In fact, the integration is quite easy -- you just need to insert the chat widget HTML code into your web site source code right before the <body> tag closure (before </body>). Another option is to manually hack the Wordpress theme files but this is not an elegant solution, and moreover you will have to repeat this work if you choose to change your theme. The best solution is to create your own plugin for p3chat integration, where you would intercept wp_footer event, and output the necessary HTML code in the event handler. What can you do if you use a theme that doesn't have a footer? Well, first of all, be informed that your theme source code is far from best practices -- and we're talking about the footer in the theme source code, not about the footer in the theme UI design. But if your theme does not have a footer (like the one I used) your solution is to use use wp_head event. Here we go. Oh and by the way it makes sense to include the buttons into the plugin. Another good idea is to implement a shortcode for static chat activation buttons in the plugin.
The only parameter that our plugin will accept is uid. All other parameters are configured directly on the p3chat web site.
Let's call our plugin p3chat.
First, let's fix the theme and add footer support to it:
?
01
02
03
04
05
06
07
08
09
10
11
12
13
               <a href="<?php bloginfo('rss2_url'); ?>" title="Subscribe to our RSS" class="rss"></a>
           <?php if(function_exists('post_notification_get_link')) { ?>
               <a href="<?php echo post_notification_get_link(); ?>" title="Receive our news by email" class="subscribe"></a>
           <?php }; ?>
               <div class="clear"></div>
       </div>
       <div id="footer">
       &copy; <?php echo date("Y");?> - <?php bloginfo('name'); ?> powered by <a href="http://wordpress.org/">WordPress</a>
       </div>
   </div></div>
<?php wp_footer(); ?>
</body>
</html>

Note the highlighted line, it was not there originally, altough it should have been there.
Below I provide the plugin source code. Plugin source code archive is here.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<?php
/*
Plugin Name: P3Chat
Plugin URI: http://sergey-s-betke.blogs.novgaro.ru/
Description: This plugin provides support for p3chat service (online chat, offline messages) on Your wordpress website
Version: 1.0
Author: Sergey S. Betke
Author URI: http://sergey-s-betke.blogs.novgaro.ru/
License: GPL2

Copyright 2011 Sergey S. Betke (email : sergey.s.betke@novgaro.ru)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

if (defined('ABSPATH') && defined('WPINC')) {

   global $wp_version;
   if ( version_compare($wp_version, "3.0", "<") || version_compare(phpversion(), "5.0.0", "<") ) {
       $pluginError = sprintf(__('P3chat plugin requires WordPress %1$s and PHP %2$s or newer. <a href="http://codex.wordpress.org/Upgrading_WordPress">Please update!</a>'), "3.0", "5.0.0");
       exit ($pluginError);
   };

   register_activation_hook ( __FILE__, array('p3chat', 'activation'     ));
   register_deactivation_hook  ( __FILE__, array('p3chat', 'deactivation'   ));
   register_uninstall_hook ( __FILE__, array('p3chat', 'uninstall'      ));

   add_action('plugins_loaded', array('p3chat', 'plugins_loaded'));

};

class p3chat {

   private static $_name;
   private static $_namespace = __CLASS__;
   private static $_folder;
   private static $_domain;
   private static $_path;
   private static $options;

   public static function activation() {
   }

   public static function deactivation() {
       unregister_setting(
           self::$_namespace,
           self::$_namespace . '_options',
           array(__CLASS__, 'validate_options')
       );
   }

   public static function uninstall() {
       delete_option(self::$_namespace . '_options');
   }

   public static function plugins_loaded() {
       self::$_folder = dirname(plugin_basename(__FILE__));
       self::$_domain = self::$_folder;
       self::$_path = WP_PLUGIN_DIR . '/' . self::$_folder . '/';

       add_action('init', array(__CLASS__, 'init'));
   }

   public static function init() {
       self::$options = self::validate_options(get_option(self::$_namespace . '_options'));
       load_plugin_textdomain(self::$_domain, false, self::$_folder . '/languages/');
       self::$_name = __('P3Chat', self::$_domain);

       add_action('admin_init', array(__CLASS__, 'admin_init'     ));
       add_action('admin_menu', array(__CLASS__, 'admin_menu'     ));
       if (self::$options['code_location'] == 'footer') {
           add_action('wp_footer',  array(__CLASS__, 'insert_widget_code'));
       } else {
           add_action('wp_head', array(__CLASS__, 'insert_widget_code'));
       };
   }

   public static function validate_options($options) {
       if (!is_array($options)) {
           $options = array();
       };

       if ($options['code_location'] != 'head')
           $options['code_location'] = 'footer';

       return $options;
   }

   public static function admin_init() {
       register_setting(
           self::$_namespace,
           self::$_namespace . '_options',
           array(__CLASS__, 'validate_options')
       );

       add_settings_section(
           self::$_namespace . '_main_options',
           __('Main Settings', self::$_domain),
           array(__CLASS__, 'option_section_main'),
           self::$_namespace . '_options_page'
       );
       add_settings_field(
           self::$_namespace . '_options[UID]',
           __('p3chat UID', self::$_domain),
           array(__CLASS__, 'option_control_UID'),
           self::$_namespace . '_options_page',
           self::$_namespace . '_main_options'
       );

       add_settings_section(
           self::$_namespace . '_extra_options',
           __('Extra settings', self::$_domain),
           array(__CLASS__, 'option_section_extra'),
           self::$_namespace . '_options_page'
       );
       add_settings_field(
           self::$_namespace . '_options[code_location]',
           __('Code in the head', self::$_domain),
           array(__CLASS__, 'option_control_code_location'),
           self::$_namespace . '_options_page',
           self::$_namespace . '_extra_options'
       );
   }

   public static function option_section_main () {
     ?>
        <p>
           <?php _e('You must obtain UID from <a href="http://p3chat.com/signup">p3chat website</a> and set it in the UID field. Other options You must set on the p3chat site.', self::$_domain); ?>
        </p>
     <?php
   }

   public static function option_control_UID() {
     ?>
           <input
               name="<?php echo self::$_namespace . '_options[UID]' ?>"
               type="text"
               maxlength="16"
               style="width: 100%"
               value="<?php echo self::$options['UID']; ?>"
           />
           <br/><?php _e('Your UID.', self::$_domain); ?>
     <?php
   }

   public static function option_section_extra () {
     ?>
        <p><?php _e('Additional settings for p3chat plugin.' , self::$_domain); ?></p>
     <?php
   }

   public static function option_control_code_location() {
   ?>
      <div>
           <label>
               <input
                   type="radio"
                   name="<?php echo self::$_namespace . '_options[code_location]' ?>"
                   value="head"
               <?php if (self::$options['code_location'] == 'head') { ?>
                   checked="checked"
               <?php } ?>
               />
               <?php _e('At the begin of pages (wp_head), when wp_footer isn`t used in the theme.', self::$_domain) ?>
           </label>
      </div>
      <div>
           <label>
               <input
                   type="radio"
                   name="<?php echo self::$_namespace . '_options[code_location]' ?>"
                   value="footer"
               <?php if (self::$options['code_location'] != 'head') { ?>
                   checked="checked"
               <?php } ?>
               />
               <?php _e('At the end of pages (wp_footer), by default.', self::$_domain) ?>
           </label>
      </div>
   <?php
   }

   public static function admin_menu() {
       add_options_page(
           __('P3Chat options', self::$_domain)
           , self::$_name
           , 'manage_options'
           , self::$_namespace . '_options_page'
           , array(__CLASS__, 'options_page')
       );
   }

   public static function options_page() {
       ?>
       <div class="wrap">
           <?php screen_icon('options-general'); ?>
           <h2><?php _e('P3Chat options', self::$_domain) ?></h2>
           <form method="post" action="options.php">
               <?php
                   settings_fields(self::$_namespace);
                   do_settings_sections(self::$_namespace . '_options_page');
               ?>
               <p class="submit">
               <input name="Submit" type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
               </p>
           </form>
       </div>
       <?php
   }

   public static function insert_widget_code() {
       ?><script type="text/javascript" src="http://p3chat.com/widget/uid/<?php echo self::$options['UID']; ?>"></script>
<?php
   }

}
?>
I will not paste the readme.txt content here, you can find it in the archive .
As you can see, this plugin is not something very sophisticated. Note that at this point, it will only work provided the theme supports wp_footer.

You can take a look at the live implementation p3chat + wordpress integration if you visit the "Enjoyable voyage" “travel agency web site”. At this screenshot you can see how the web site looks like, and the chat activation button on the left. Yeah I haven't changed the button design yet but I'm going to do that in the coming days. The button you can see at this picture will look this way in case the operator is currently online. If the operator is offline, the button change it look and feel to "offline mode" or can be hidden altogether. You can configure this in the p3chat service settings.

 

4 comments:

  1. So, you recommend creating your own custom plugin for every individual site, as opposed to using the p3chat plugin for WordPress?
    http://wordpress.org/extend/plugins/p3chat/

    ReplyDelete
  2. No, an example of already written plugin for wordpress presented here and you just need to use it.

    ReplyDelete
  3. hmm, I added the widget for p3chat manually many times. First time I know that you have a plugin for WordPress. Thanks for sharing

    ReplyDelete