Mobile friendly works for SEO

organic_search

In the past month this blogs traffic has structurally improved from 1800 to 2050 unique visitors on a working day. We have seen on Google’s Search Console that the organic search traffic has gone from 1000 to 1250 clicks per day (see graph above).

+25% for mobile friendly

In the past month we have seen the traffic to LeaseWeb labs increase every week with a few percent. When we analyzed the traffic we found that only the organic (non-paid) search engine traffic has grown. The only real thing we changed was the new mobile friendly layout of the site. Interesting is that the amount of mobile traffic on the site has not significantly changed. We believe this can be explained by a lifted penalty Google had given us for not being mobile friendly. Not having the penalty, causes higher ranks in Google and therefor more visitors. Apparently this penalty applies to both mobile and desktop users.

Twentyfifteen theme

We have used the WordPress built-in twentyfifteen theme for this blog. This theme is mobile friendly out-of-the-box. The only things of the theme we adjusted are the colors and the added logo. It is quite interesting to see that this default theme works well on mobile and thus scores good on Google. It is expected that this is the world’s most used website theme as WordPress is the most popular CMS and this is it’s default theme. I guess that this time it paid off to be lazy. 🙂

Move to leaseweb.com

To further increase the traffic to LeaseWeb labs we have moved the site from www.leaseweblabs.com to www.leaseweb.com/labs. We have recently made this move and it is still too early to discuss the changes we measured. We will report on the effect of this move in our next post. Stay tuned as this seems to have a positive effect as well!

New design for LeaseWeb labs!

As you can see LeaseWeb labs has gotten a complete make-over. This is part of the two day hackaton at LeaseWeb that started today. As you may notice we also moved to HTTPS (SSL). Also we have a new theme that is based on Automattic’s twentyfifteen theme. This theme has lighter colors, a larger font size and is fully responsive (much better readable on smart phones). As you can see the LeaseWeb CDN banner has been moved to the bottom.

Design: old vs. new

For comparison, this is what the old design looked like:

old_layout

And this is the new design:

new_layout

I hope you like the changes. Anyway, let me know what your thoughts are using the comments, cheers!

 

WordPress password forgotten? Part 2 (using FTP)

In Part 1 of this post we explained that WordPress is the worlds most popular blogging software and that this site runs WordPress as well. We also explained how you might you run into a WordPress site you previously installed, but have forgotten the password of. The script we presented was able to find your username, reset your password, and reset your user level so that you had “Administrator” role again. The previous post and the corresponding script required that you had SSH access. This post will show you how to do these things if all you have is FTP access.

Reset WordPress password over FTP

Running the script is easy. Change the reset password in the first line of the script. Upload the file to the directory where the wp-config.php is located and type in the URL of the file in the address bar of your browser.

Screenshot - 02112014 - 11:50:55 PM
Normally this is just your websites domain with “/wp-reset-ftp.php” added as a path.

Running the script in the browser gives the following output:

Screenshot - 02112014 - 09:57:59 PM
Enter the reset password and press “Login”.

NB: The reset password is set in the first line of the script and MUST be changed for security reasons!

Screenshot - 02112014 - 09:58:41 PM
Select the WordPress user and set the WordPress password you want to assign to the user. Now press “Submit”.

Screenshot - 02112014 - 09:58:50 PM
This is the SQL that will be executed. Press “Execute SQL” to confirm.

Screenshot - 02112014 - 09:58:54 PM
Great! The WordPress password reset script succeeded.

wp-reset-ftp.php

This is the source code of the above script:

<?php
$password = "Wj12lzSwE9cZ34QXkBM"; // IMPORTANT: Change this !!!
$title = "WordPress Password reset script";
echo "<html><body><h4>$title</h4><pre>";
function error($s) { die("<p style=\"color:red\">$s</p>"); }
if (!isset($_GET["password"])) {
  echo "<form>Password: <input name=\"password\">\n\n";
  echo "<input type=\"submit\" value=\"Login\"/></form>";
  die();
}
if (dechex(crc32($password))=="39246f99") error("change password");
if ($_GET["password"]!=$password) error("access denied");
$path = "./wp-config.php";
while (!file_exists($path)) {
  if (realpath($path) == "/wp-config.php") break;
  $path = "./.$path";
}
if (!file_exists($path)) error("wp-config.php not found");
$lines = file($path);
foreach ($lines as $line) {
  if (preg_match('/^\s*define\(/i',$line)) eval($line);
}
$mysqli = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$mysqli->set_charset(DB_CHARSET);
if ($mysqli->connect_errno) die($mysqli->connect_error);
if (!isset($_POST["user"]) && !isset($_POST["sql"])) {
$result = $mysqli->query("SELECT `user_login` FROM `wp_users`");
if ($result===false) die($mysqli->error);
$users = array();
while($row=$result->fetch_array()) $users[]=$row[0];
$result->close();
echo "<form method=\"post\">";
echo "User: <select name=\"user\">";
foreach ($users as $user) echo "<option value=\"$user\">$user</option>";
echo "</select>\n";
$default = substr(rtrim(base64_encode(sha1(microtime())),"="),0,10);
echo "Password: <input type=\"text\" name=\"pass\" value=\"$default\"/>\n";
echo "Reset administrator role: <select name=\"reset\">";
echo "<option value=\"0\">no</option><option value=\"1\">yes</option>";
echo "</select>\n\n<input type=\"submit\" value=\"Submit\"/></form>";
} elseif (!isset($_POST["sql"])) {
$p = (object)$_POST;
$sql = <<<END_OF_SQL
SET @user = '$p->user';
SET @pass = '$p->pass';
SELECT ID into @user FROM `wp_users` WHERE `user_login`=@user;
UPDATE `wp_users` SET `user_pass`=MD5(@pass) WHERE `ID` = @user;
END_OF_SQL;
if ($p->reset) $sql.= <<<END_OF_SQL

UPDATE `wp_usermeta` SET `meta_value`='a:1:{s:13:"administrator";s:1:"1";}' WHERE `user_id`=@user AND `meta_key`='wp_capabilities';
UPDATE `wp_usermeta` SET `meta_value`=10 WHERE `user_id`=@user AND `meta_key`='wp_user_level';
END_OF_SQL;
echo "<form method=\"post\">";
echo "<textarea cols=\"80\" rows=\"10\" name=\"sql\">$sql</textarea>\n\n";
echo "<input type=\"submit\" value=\"Execute SQL\"/></form>";
} else {
$mysqli->autocommit(false);
$lines = explode("\n",trim($_POST['sql']));
foreach ($lines as $query) {
  if ($mysqli->query($query)===false) error($mysqli->error);
}
if ($mysqli->commit()) echo "Executed SQL successfully\n";
else error($mysqli->error);
$mysqli->close();
}

WordPress password forgotten? Part 1 (using SSH)

According to Wikipedia, WordPress is the worlds most popular blogging software. Approximately 19% of all websites run WordPress. I cannot count the times I installed and configured WordPress. It is easy to customize using plugins, which make it do almost anything you can dream of. NB: This site runs WordPress as well.

Sometimes you come across a WordPress instance you installed a long time ago and you have forgotten the administrator username and/or password. This has actually happened to me a few times already. In this case, you can run the script below on the web servers SSH shell. It allows you to find the user and reset the password and reset the user to have the ‘Administrator’ role.

In Part 2 of this post we will show you a script that can be run if you have no SSH, but only FTP access to the web server.

Reset WordPress password over SSH

Running the script from the SSH shell gives the following output:

maurits@nuc:~$ php wp-reset-ssh.php
WordPress password reset script
1: /home/maurits/public_html/wp-config.php
Choose config file [1]:
1: Maurits
Choose WP user [1]:
Choose password [NWE0NjE2YW]:
Reset administrator role (y/N)? y
================================================================================
SET @user = 'Maurits';
SET @pass = 'NWE0NjE2YW';
SELECT ID into @user FROM `wp_users` WHERE `user_login`=@user;
UPDATE `wp_users` SET `user_pass`=MD5(@pass) WHERE `ID` = @user;
UPDATE `wp_usermeta` SET `meta_value`='a:1:{s:13:"administrator";s:1:"1";}' WHERE `user_id`=@user AND `meta_key`='wp_capabilities';
UPDATE `wp_usermeta` SET `meta_value`=10 WHERE `user_id`=@user AND `meta_key`='wp_user_level';
================================================================================
Execute this SQL (y/N)? y
Executed SQL successfully
maurits@nuc:~$

wp-reset-ssh.php

This is the source code of the above script:

<?php
echo "WordPress password reset script\n";
$files = array();
exec('locate wp-config.php',$files,$result);
if ($result!=0) {
  echo "Choose search path [.]: ";
  $path = trim(fgets(STDIN));
  if (!$path) $path = '.';
  exec("find '$path' | grep wp-config.php",$files, $result);
}
if ($result!=0 || count($files) == 0) {
  die("ERROR: could not find file 'wp-config.php'");
}
foreach ($files as $i=>$file) echo ($i+1).": $file\n";
echo "Choose config file [1]: ";
$number = trim(fgets(STDIN));
if (!$number) $number = '1';
$lines = file($files[$number-1]);
foreach ($lines as $line) {
  if (preg_match('/^\s*define\(/i',$line)) eval($line);
}
$mysqli = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$mysqli->set_charset(DB_CHARSET);
if ($mysqli->connect_errno) die($mysqli->connect_error);
$result = $mysqli->query("SELECT `user_login` FROM `wp_users`");
if ($result===false) die($mysqli->error);
$users = array();
while($row=$result->fetch_array()) $users[]=$row[0];
$result->close();
foreach ($users as $i=>$user) echo ($i+1).": $user\n";
echo "Choose WP user [1]: ";
$number = trim(fgets(STDIN));
if (!$number) $number = '1';
$user = $users[$number-1];
$default = substr(rtrim(base64_encode(sha1(microtime())),"="),0,10);
echo "Choose password [$default]: ";
$pass = trim(fgets(STDIN));
if (!$pass) $pass = $default;
$sql = <<<END_OF_SQL
SET @user = '$user';
SET @pass = '$pass';
SELECT ID into @user FROM `wp_users` WHERE `user_login`=@user;
UPDATE `wp_users` SET `user_pass`=MD5(@pass) WHERE `ID` = @user;
END_OF_SQL;
echo "Reset administrator role (y/N)? ";
$yes = trim(fgets(STDIN));
if ($yes=="y") $sql.= <<<END_OF_SQL

UPDATE `wp_usermeta` SET `meta_value`='a:1:{s:13:"administrator";s:1:"1";}' WHERE `user_id`=@user AND `meta_key`='wp_capabilities';
UPDATE `wp_usermeta` SET `meta_value`=10 WHERE `user_id`=@user AND `meta_key`='wp_user_level';
END_OF_SQL;
$bar = str_repeat("=",80);
echo "$bar\n$sql\n$bar\n";
echo "Execute this SQL (y/N)? ";
$yes = trim(fgets(STDIN));
if ($yes!="y") die("Stopped without executing SQL\n");
$mysqli->autocommit(false);
$lines = explode("\n",trim($sql));
foreach ($lines as $query) {
  if ($mysqli->query($query)===false) die($mysqli->error);
}
if ($mysqli->commit()) echo "Executed SQL successfully\n";
else die($mysqli->error);
$mysqli->close();

Popular posts for “Count per Day” WordPress plugin

popularpostsLeaseWeb Labs runs on WordPress and we are using the “Count per Day” plugin to keep track of our visitors. One big advantage of Count per Day is that it does not use cookies, but counts the amount of unique IP addresses per day. These are reported as “visitors”, while the amount of page views are reported as “reads”. In our experience this is a very simple and reliable way of measuring the visitors on our site. Especially when you enable the option “Cache: Count visits with ajax” in the Settings, because that will prevent bots from showing up in the statistics.

Some posts are better and thus more popular than other posts. When people visit your site for a certain post, they may also be interested in other popular posts. This is why we wanted the most popular posts listed in the sidebar (as you can see on the left). Since the popularity of posts is changing all the time and we did not feel like maintaining a static list of posts in menu. Count per Day has a the shortcode “CPD_MOST_VISITED_POSTS” to generate this list for you. Unfortunately this code generates the list including numbers and a heading. This is not exactly the way we like it and thus we created a WordPress widget for our (and your) convenience.

The widget can be simply dragged into a widget area and allows you to:

  • Set the title for the list
  • Set the amount of days to take into account
  • Set the maximum number of items in the list
  • Show/hide the counts for the selected period
  • Show/hide the header that explains the counts

We contacted Tom Braider (the author of this fantastic plugin) and we hope he will include the widget in a next version. Until then you can install the widget by adding the following code to “widgets.php” using the theme editor:

if (isset($count_per_day)) {

// Creating the widget
class PopularPostsWidget extends WP_Widget {

  function __construct() {
    parent::__construct(
      // Base ID of your widget
      'cpd_popular_posts_widget',
      // Widget name will appear in UI
      'Popular Posts',
      // Widget description
      array( 'description' => 'Count-Per-Day Popular Posts'));
  }

  // Creating widget front-end
  // This is where the action happens
  public function widget( $args, $instance ) {
    $title = apply_filters( 'widget_title', $instance['title'] );
    $days  = $instance['days' ]+0;
    $limit = $instance['limit']+0;
    $head  = $instance['head' ]?true:false;
    $count = $instance['count']?true:false;
    // before and after widget arguments are defined by themes
    echo $args['before_widget'];
    if ( ! empty( $title ) ) {
      echo $args['before_title'] . $title . $args['after_title'];
    }
    // This is where you run the code and display the output
    global $count_per_day;
    $html = $count_per_day->getMostVisitedPosts($days, $limit, 1, 1, 1);
    if (!$head ) $html = preg_replace('/<small>[^<]*<\/small>/','',$html);
    if (!$count) $html = preg_replace('/<b>[^<]*<\/b>/','',$html);
    echo $html;
    echo $args['after_widget'];
  }

  // Widget Backend
  public function form( $instance ) {
    $title = isset($instance['title'])?$instance['title']:'Popular Posts';
    $days  = isset($instance['days' ])?$instance['days' ]:'7';
    $limit = isset($instance['limit'])?$instance['limit']:'10';
    $head  = isset($instance['head' ])?$instance['head' ]:false;
    $count = isset($instance['count'])?$instance['count']:false;
    // Widget admin form
    ?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'days' ); ?>"><?php _e( 'Days:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'days' ); ?>" name="<?php echo $this->get_field_name( 'days' ); ?>" type="text" value="<?php echo esc_attr( $days ); ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'limit' ); ?>"><?php _e( 'Limit:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'limit' ); ?>" name="<?php echo $this->get_field_name( 'limit' ); ?>" type="text" value="<?php echo esc_attr( $limit ); ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'head' ); ?>"><?php _e( 'Show header:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'head' ); ?>" name="<?php echo $this->get_field_name( 'head' ); ?>" type="checkbox" <?php echo $head?'checked="checked"':'' ?> />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php _e( 'Show counters:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'count' ); ?>" name="<?php echo $this->get_field_name( 'count' ); ?>" type="checkbox" <?php echo $count?'checked="checked"':'' ?> />
</p>
    <?php
  }

  // Updating widget replacing old instances with new
  public function update( $new_instance, $old_instance ) {
    $instance = array();
    $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
    $instance['days' ] = ( ! empty( $new_instance['days' ] ) ) ? strip_tags( $new_instance['days' ] ) : '';
    $instance['limit'] = ( ! empty( $new_instance['limit'] ) ) ? strip_tags( $new_instance['limit'] ) : '';
    $instance['head' ] = ( ! empty( $new_instance['head' ] ) ) ? strip_tags( $new_instance['head' ] ) : '';
    $instance['count'] = ( ! empty( $new_instance['count'] ) ) ? strip_tags( $new_instance['count'] ) : '';
    return $instance;
  }
} // Class PopularPostsWidget ends here

// Register and load the widget
add_action( 'widgets_init', function (){ register_widget('PopularPostsWidget'); });

}