Click here to Skip to main content
15,881,852 members
Articles / Hosted Services / Web Hosting
Article

Making a WordPress Site Interactive with Node.js

11 Dec 2014CPOL4 min read 38.9K   1  
Providing a rich, interactive experience will increase visitors returning to your website. Accomplishing this is easy with WordPress and Node.js.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

Introduction

Adding interactive capabilities to your website improves user experience and, in turn, encourages repeat visits. Providing your visitors with enhanced features, such as a second screen app or even a simple chat, enables you to engage with your audience and keep them interested in your content. There are many solutions available to make WordPress websites more dynamic, one of which is to use Node.js.

What is Node.js

Node.js is a cross-platform runtime environment for server-side development and networking applications. Written in JavaScript, Node.js applications are event-driven, lightweight and efficient - a perfect solution for data-intensive real-time applications. For more information, visit http://nodejs.org/.

Node.js has a lot of packages that can be used when building your project. With Node Package Manager, you can easily maintain these and install new ones when needed. You can also use package.json which includes fields for name and version. Utilizing package.json makes it easy to install all of the dependencies and maintain your project.

Creating the Server

The first step in this process is creating the server. Building from global variables that can be reused later can save time. So, I often start with creating variables. The main variable is config which has the port number of the Node.js server and the details of the site that is calling it. It is important to note this information, but not necessary to use it for this example.

var config = {}
    , channel = []
    , clients = [];

config.port = 9000;
config.application_host = ‘wordpress.dev';
config.application_port = 80;

Next, load the modules that are needed and start creating the web- and socket server. For this example, I’m using socket.io for the socket and the WordPress Utils code which is a project I’m currently working on. More information about this project can be found on GitHub: https://github.com/markoheijnen/node-wordpress-utils.

var app = require('http').createServer(handler),
	io = require('socket.io').listen(app),
	wordpress = require("wordpress-utils");

app.listen(config.port);

function handler(req, res) {

}

Integrate WordPress with Socket.io

Two things need to be done in order to connect WordPress to the existing code. First, enqueue the socket.io script. The script used in this example can be found at http://socket.io/.

Second, enqueue your own script to make the connection. Use wp_localized_script() to send the URL of the Node.js server and the nonce of the JSON REST API by using wp_create_nonce( 'wp_json' ). Currently the WordPress Utils code can only be used in combination with the JSON REST API plugin which can be found on GitHub: github.com/WP-API/WP-API.

You can start building your code in your own script. As an example, the basic code would look something like this:

var socket = io.connect( wp_nodejs.url, { query: { token: wp_nodejs.nonce } });

// Default callbacks
socket.on('connect', function () {
	console.log('connected');
});

socket.on('disconnect', function () {
	console.log('disconnected');
});

// Custom callback
socket.on('publish', function (data) {
	console.log(data);
});

Using Socket.io and Connecting to WordPress Users

We now have our variables set up and are ready to start writing code to interact with WordPress.

In the following code, upon connection we are passing the cookie and the token to our WordPress module for validation. It will first check if the cookie data is still valid. Once verified, it will make a call to the JSON REST API for a final check. It will also receive quite a lot of information, including permissions, from the user.

io.on('connection', function (socket) {
	clients[socket.id] = socket;

	socket.wp_user = wordpress.connect( socket.handshake.headers.cookie, socket.handshake.query.token );

	socket.wp_user.on('wp_connected', function ( data ) {
		console.log( 'connected: ' + socket.wp_user.logged_in );
	});

	socket.wp_user.on('wp_connect_failed', function ( e ) {
		console.log( 'failed' );
	});


	// When socket disconnects, remove it from the list:
	socket.on('disconnect', function() {
		delete clients[socket.id];
	});
});

The Next Steps

At this point, you have the base connecting WordPress with a Node.js server – but it doesn’t do anything, yet. The code still needs to be provided to make it function properly. In the following example, we will send a video to the user if they meet certain qualifications:

WordPress Code

This is the full class I’m currently using to connect with Node.js and send new video. The only change that can be made here is to send the cookie data and a token so you can validate the user again. In doing so, you can then make it truly secure by checking for permissions more than once.

<?php

class Nodejs {
	private static $status = null;
	private static $url    = 'http://wordpress:9000/';
	private static $key    = 'a_secret_key';

	public function __construct() {
		self::$url = home_url() . ':9000/';

		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
	}

	public function enqueue_scripts() {
		wp_enqueue_script( 'socket.io', self::$url . 'socket.io/socket.io.js' );
	}


	public static function get_url() {
		return self::$url;
	}

	public static function status() {
		if ( self::$status !== null ) {
			return self::$status;
		}

		self::$status = false;

		$response = wp_remote_get( self::$url . 'status', array( 'timeout' => 1 ) );

		if ( 200 == wp_remote_retrieve_response_code( $response ) ) {
			self::$status = true;
		}

		return self::$status;
	}

	public static function publish( $channel, $url ) {
		if ( ! self::status() ) {
			return false;
		}

		$args = array(
			'headers' => array(
				'x-request-identification' => self::$key,
				'content-type' => 'application/json'
			),
			'body' => json_encode(
				array(
					'url'     => $url
				)
			)
		);
		$response = wp_remote_post( self::$url . 'publish', $args );

		if ( 200 == wp_remote_retrieve_response_code( $response ) ) {
			return true;
		}

		return false;
	}

}

Node.js Code

On the Node.js part, we start using the handler function.

function handler(req, res) {
	if (req.url == "/status") {
		res.writeHead( 200 );
		res.end();
		return;
	}

	if( req.headers['x-request-identification'] == ‘a_secret_key’ ) {
		var fullBody = '';

		req.on('data', function(chunk) {
			fullBody += chunk.toString();
		});

		req.on('end', function() {
			if (req.url == "/publish") {
				var json = JSON.parse(fullBody);

				if( json.url ) {
					channel.url = json.url;
					io.sockets.emit('publish', { url : json.url });
				}
				else {
					 res.writeHead(500);
				}
			}

			res.end();
		});
	}

	res.writeHead( 404 );
	res.end();
}

This will send out the video that was passed from WordPress directly to all of the current users. However, you still need to send the specific video to the users by adjusting the part where the user connection has been established. To accomplish this, we add a few lines that send the YouTube URL to our new visitor.

io.on('connection', function (socket) {
	// The previous code

	if( channel.url ) {
		socket.emit('publish', { url: channel.url });
	}
}

Frontend Code

The last step is to listen to the events on the WordPress side in the JavaScript code. Then, add a listener to our publish event. I suggest adding a check there to see if a URL has been passed. If this is empty, we can see that there isn’t an active session.

socket.on('publish', function (data) {
	if( data && data.url ) {
		reload_channel_html(data.url);
	}
	else {
		reload_channel_html('');
	}
});

function reload_channel_html( link ) {
	var channel = jQuery('.channel-movie');

	if( link ) {
		if( link.indexOf('youtube.com') ) {
			link += '?autoplay=1';
		}

		channel.html('<iframe width="100%" height="315" src="' + link + '" frameborder="0" allowfullscreen></iframe>');
	}
	else {
		channel.html('Currently there is no live session.');
	}
}

Conclusion

The example in this tutorial is just one of many cool things that can be done with WordPress, especially when it comes to adding enhancements. As a starting point, I hope it provided some inspiration for you. Node.js is one of the technologies that allow you to extend the WordPress user experience. Yet there are still many more things that can be done with Node.js and WordPress.

Delivering a positive user experience is essential for achieving success online. It is important to ensure that your Web hosting package can accommodate the performance demands of your interactive WordPress website. Choosing a solution that exceeds your day-to-day requirements can ensure the availability and performance of your website. 1&1’s WordPress Hosting provides a convenient and powerful environment for even the most resource-intensive WordPress projects.

For more tips and advice on how to best use WordPress, for both beginners and advanced users, visit 1&1’s Community Portal or the 1&1 Blog.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Netherlands Netherlands
Marko Heijnen is a 1&1 WordPress Specialist and contributor to the WordPress community. He has had a hand in developing seven releases since 3.0. Some notable achievements within those contributions include working on XML-RPC in 3.4 and WP_Image_Editor in 3.5. He is also the main core developer for GlotPress and is currently creating a better open-source tool for translations. As a 1&1 WordPress Specialist, Marko is committed to improving the platform by contributing back to the community. To learn more about Marko, visit http://markoheijnen.com/ or follow him on Twitter @markoheijnen

Comments and Discussions

 
-- There are no messages in this forum --