The purpose of this blog post is to describe the implementation of a commercial website (a rural hotel’s website) using WordPress online at www.montepuravida.com.pt. It is not a step-by-step tutorial but just a general description of what is involved.
This assignment was a legacy work done by my former company. It also suited the purpose for me to tryout the WordPress as a site development platform. Another purpose on using WordPress was to give the client a website that could be authored and managed by others, in the future.
The site uses a lot of plugins and the Underscores (“_s”) theme as the base theme. Since the website already existed but was implemented in another platform, the web design implementation was just to mimic the existing one. But no CSS or HTML was copied from the existing site, since it was not in HTML5/CSS3.
Existing site front page:
Plan
The first thing to do was to make a text document depicting the web site:
- Hosting: domains, locales, emails
- Common layout
- Pages: name, URLs, locales, content, migration notes
- Forms: fields, email addresses, Google Web Analytics event info
This document was delivered to the client so he could review the migration notes, mainly. Also, the client has a comprehensive description of the work done on this document.
After this I got to install WordPress 3.8 in my computer to build the website locally. I used Microsoft IIS on a Windows 8.1 and installed the all package using the Web Platform Installer 4.6. It was a breeze, installed everything without a hitch. I’m not going in depth into this because it’s not the blog post purpose.
Then I searched for a plugin I needed: a multi language support plugin since the site has Portuguese and Spanish versions. This was the first plugin to determine, since it may influence other options.
Plugins
Follows the list of all plugins I ended up using.
“Polylang” by Frédéric Demarle
This plugin worked great, linking together the same page in different languages. It also provides a “Language Switcher” widget showing the flags of the languages that the page is available in. So, if the user changes language using the flag icon, it is directed to the same page but in the chosen language. Also, it supports different custom URLs for different languages of a page.
It uses an approach of having individual WordPress pages for different languages, which, seems to me, is a good approach. I’ve found that other plugins store the different language content in a single page, using some questionable techniques.
“Custom Post Widget” by Johan van der Wijk
This plugin allows for having additional content (basically HTML, like the one in a page or a post) available to place in widgets or in other text content using WordPress shortcodes. Referring to the image above of the existing site, the three promotional blocks under the main image were made using this plugin. It allowed to create three “Content Blocks” that are placed in that widget area (aka “sidebar” in WordPress terminology).
“Slideshow” by StefanBoonstra
A slideshow plugin that manages a list of slideshows to place with a widget or with a shortcode. For each slideshow it has some nice options available. At the time it did not support touch sliding, though.
“Facebook” by Facebook
Allowed for the Like and Share buttons placed as widgets.
“Dynamic SiteLinks” by Hank Brekke
This plugin is about a controversial issue. By default WordPress content stores all links with absolute URLs. That gives some headache when transferring the site to another domain. Or when running the site in a development environment. But all of this is controversial. I won’t place a link in here because there are so many info about this, that I did not find a main page about this. Just look around.
This plugin hooks in when editing and saving content transforming back and forth the absolute part in URLs into a shortcode. On the database, the URLs have the shortcode that is properly translated on page output (as long as this plugin is active!).
“MCE Table Buttons” by Jake Goldman
Like the author says “Add controls for table editing to the visual content editor”. I needed to layout the hotel pricing as an HTML table. That table was created inside a “Content Block” (from the “Custom Post Widget” plugin) and is used in several pages by using a shortcode! I’m mentioning this to exemplify the interoperability of different plugins.
“Per Page Sidebars” by Brian Layman
I needed a sidebar alongside the main content but just on the home page. WordPress does not allow this exception by default, so this is where this plugin enters. On each page or post editor there is a “Custom Sidebar” settings box where we can activate the feature and indicate which sidebar should be replaced on that page or post. As soon as you enable this and save the page/post, a new widget area (a.k.a. “sidebar”) specific to that page/post appears under Appearance/Widgets. We can then place whatever widgets inside that new widget area.
“Preserved HTML Editor Markup” by Marcus E. Pope
The tinyMCE HTML editor of WordPress content editor messes up with HTML, specially when switching between the “Visual” and “Text” modes. This plugin fixes that.
“XCloner” by Liuta Ovidiu
Could not put it better than the author: “XCloner is a tool that will help you manage your website backups, generate/restore/move (…)”. Could not put it to work with SFTP, but that does not invalidate its usage, since you can transfer the files using your preferred SFTP client.
“Contact Form 7” by Takayuki Miyoshi
Allows the creation of contact forms and use them throughout the content by using shortcodes. A form is created (and edited) in plain HTML, but the plugin provides an HTML generator to simplify and accelerate the form creation. For me this was a perfect approach, since it let me make the layout the way I needed in pure HTML.
It sends emails messages on form submission that are totally customized and can refer to any of the form fields content. It can be configured to send a second email, totally separate from the first.
Also allows to configure the messages the form responds to the user. It even allows to place the code to make Google Web Analytics track an event when the form submits successfully.
“Really Simple CAPTCHA” by Takayuki Miyoshi
Adds CAPTCHA capability to the “Contact Form 7” plugin. But it seems that can be used from other plugins by using shortcodes.
“Lightbox Plus ColorBox” by Dan Zappone
Just a lightbox plugin for displaying images. It works, but does not allow to have title/captions with wrapping when its too long for the space available.
“WP Mail SMTP” by Callum MacDonald
As the author puts it: “Reconfigures the wp_mail() function to use SMTP instead of mail() and creates an options page to manage the settings.”. It allows for SSL/TLS SMTP servers like GMail.
“WordPress SEO” by Joost de Valk (Yoast) – Free version
A fully fledged SEO plugin.
“Google Analytics for WordPress” by Joost de Valk (Yoast)
Another fully fledged plugin for adding Google Analytics to the site.
“Disable Feeds” by Samir Shah
Since the site is not a blog, nor have one, there is no need to have RSS feeds. In fact, having it enabled made the links to the RSS feeds available in the page source code, and those pages were not working properly. I did not even bothered with them, since I have just disabled them using this plugin.
Settings
The first thing was to configure basic settings on the WordPress admin page. There were lot of settings and configuration to be made. The fact that this web site is not a blog influences these settings, since many of the defaults are not correct.
The only settings worth mentioning are the site URLs configuration. After inserting the URLs where the site will be online, things started running bad. The problem was that the site, on my development machine was not in that address, of course. At first, it would suffice to set the site address in the settings page to the development address I was using, but as soon as I would test the site on the production server, things would break again.
The solution was to keep the online URLs on the settings page and add some lines to the file “wp-config.php”:
// Use the current URL for the WordPress URL
define('WP_HOME','http://' . $_SERVER['HTTP_HOST']);
define('WP_SITEURL','http://' . $_SERVER['HTTP_HOST']);
Layout
Next, I decided about the layout elements:
From left to right and top to bottom:
- Logo: image hardcoded in HTML.
- Top widget area: language switcher and Facebook buttons as widgets from plugins.
- Menu: WordPress navigation menu.
- Promo Slideshow: a widget area with a slideshow (from plugin).
- Promo areas: three widget areas with content blocks (from plugin). The third area is shown blank in the image but it will collapse when empty. This areas will be hidden/shown according to a custom field (more below).
- Content: WordPress content.
- Content sidebar: a widget area (the default WordPress sidebar) with a content block (from plugin). This is only shown on the front page by means of the “Per Page Side Bars” plugin.
- Footer widget areas: two widget areas with content blocks (from plugin).
- Site info widget area: another content block (from plugin).
Except for the logo, everything comes from the CMS and is not hardcoded in the theme’s HTML, making the site’s content fully editable. This options implies that sometimes some HTML tweaking is needed in the content including simple styling. In these cases the “Preserved HTML Editor Markup” plugin is essential.
Theme
The underscores theme is a WordPress specific starter theme, based on “_s”, provided by underscores.me which accepts some simple theme branding using a form and downloads the theme already customized with that branding. It includes a resetting stylesheet.
I used LESS to make the CSS3 styling on a single file “custom.less” that generates “custom.css” and “custom.min.css”. This is included in every site’s page by adding some code to the “function.php” file, in the function “*_scripts()” (where “*” is the theme name):
wp_enqueue_style('MPVTheme-custom-style', get_template_directory_uri()
. '/custom.min.css');
On the LESS file, I have separated the layout styles from the formatting styles, since these two approaches are addressed at different stages of development and don’t interact much with each other. It also makes each style declaration less cluttered.
Using the developer tools of the browser, I started to analyze the CSS classes in use the by the site structure. Using LESS I was able to mimic the site’s hierarchical structure of classes. LESS finally makes the outlining collapse/expand of the editor useful!
While many of the content is liquid enough to adapt to narrow width devices, the menu is not and will have to be layout explicitly different for those devices. Decided to have two layouts for the menu separating them at 880px wide, the width of the original site.
Fonts
Using a custom font was a bit of a let down because of the poor anti-aliasing of fonts by Chrome running in MS Windows:
Tried several recipes that spread all over the internet to no avail (here is big discussion on the matter). The best option was to have the SVG font file specified before the WOFF one, to force Chrome to use SVG instead of WOFF. Indeed, it results in a much better rendering quality. The downside is that SVG fonts files are much bigger. In my case the SVG font file is 4x bigger than the WOFF one.
This bug is in “fixing” state since 2012 and it seems it is now (late July 2014) expected to be fixed in V37 expected to go to the stable state in July/August 2014. Since that version will eventually rollout to all Chrome browsers, I decided to leave the WOFF before the SVG. It will be ugly just for one or two months more.
The Header
On the top of the site, there is the logo and a widget area (“sidebar”) where I popped the language switcher and Facebook buttons. These needed settings within the layout so they would float to the right and that was it.
The Menu
The menu is a WP standard menu. Completely customized by authoring the site through the WP backoffice and using plain text for the menu titling.
The only customization made to the WP menu generation was the inclusion of some HTML before and after the hyperlink generation. On file header.php the menu generation became:
<?php wp_nav_menu( array(
'theme_location' => 'primary',
'before' => '<div class="item"><img class="left" src="'. get_template_directory_uri()
. '/images/menusep2.png" /><img class="right" src="'
. get_template_directory_uri()
. '/images/menusep1.png" />',
'after' => '</div>' )); ?>
This places the menu hyperlink inside a DIV element. This DIV corresponds to the menu tab. It will have a variable top margin (according to the selected menu item), the gradient and the round corners. Inside there are also two images to make the dark separators. These two are the only two images that will be used for the all menu. They were grabbed from the original site Photoshop files.
In the CSS, main settings are simply:
.menu {
display:table;
width:100%;
}
.menu li {
display:table-cell;
}
This makes the UL and LI behave like a table allowing for the menu to span to the width of its container with the tabs width proportionally divided.
But there is a problem with this approach: it is not fluid. When narrowing the browser it does not float the exceeding menu downwards, since the menu is rendered as an html table. So a different approach was taken for narrow devices. A menu button opens and closes the menu, which lays vertically, full width. The button only applies or removes a class, using JavaScript, from an all menu wrapper DIV and the CSS does the rest.
Note one difference to the original menu: it does not use double line titles. Since the standard HTML5/CSS3 is still lousy centering vertically, I opted to make all entries single line.
The menu uses CSS3 transitions to achieve some animation effects. It also uses the border-radius and linear-gradient to achieve the looks of the menu from the old site (made with images). Now only uses two images for the uneven shadow on the sides of the selected menu item.
Promo Area
The three promo areas below the slideshow are only visible on the home page. This behavior could be accomplished by using the “Per Page SideBars”:
- Leave the three widget areas blank
- On the home page, check the “Activate Custom SideBar” and also check the three options corresponding to the three widget areas (a.k.a. sidebar). This will make three new widget areas available in the site admin.
- Fill in the three widget areas that appear on the “Widgets” admin section for that page with the content needed.
But I did not implement the promo area hide/show functionality using the “Per Page SideBars”. I wanted to test a different approach, using custom fields and some PHP programming. This approach allows for selecting the visibility of the three promo areas in each page. Note that with the “Per Page SideBars” plugin approach, for each page where the promos must be visible there would be three widget areas specific for each page! All of them would have to be filled in. If the promo content would be the same for all pages, that would be redundant. If the content would vary per page, then the plugin would be the only way to go.
The idea here was to have a custom field (that is available on each page/post) to indicate where the three promo areas should be visible or not. If the custom field definition is absent from the page, the promos must not be shown.
On the “page.php” file:
<?php
$post_custom = get_post_custom();
if (array_key_exists('PromoArea', $post_custom)&& strtolower($post_custom['PromoArea'][0]) == 'visible')
{ ?>
<div class="promo-widget-area">
<?php dynamic_sidebar('PromoArea1') ?>
<?php dynamic_sidebar('PromoArea2') ?>
<?php dynamic_sidebar('PromoArea3') ?>
</div>
<?php } ?>
The code shows that the three promo areas are only output if the post has the custom field “PromoArea” with the value “visible”.
So with this approach, one have to:
- Fill in the three widget areas on the “Widgets” admin section with the content needed.
- Add the custom field “PromoArea” with the value “visible” to each page that must show the three promo areas. Only the two homepages (PT and ES), in my case.
Pages
At this point I created all the pages for the site, for both languages. Only inserted content at a later step, for now I wanted to test the navigation and language switching. The final URLs for the pages were also set at this stage, since many pages have links to other pages.
The multi-language for the pages worked beautifully and language switching too. Had only an issue with the page for the root URL (http://www.montepuravida.com) but it settled down by configuring the language plugin under “URL modification”:
and then setting the PT home page as the “front page”. Used the admin “Appearance / Customize / Static Front Page” setting. Also checked the URL in the page editor (for the front page) to be the root URL.
Widget Areas (sidebars)
The widget areas for the theme, as seen above, were created by placing two code components: the place on the HTML for the widget area; and the registration of the widget area in PHP.
<?php dynamic_sidebar('PromoSlideshow') ?>
In functions.php file, added this code to the “*_widgets_init()” function (“*” would be your theme name).
register_sidebar( array( 'name' => __( 'PromoSlideshow', 'MPVTheme' ), 'id' => 'PromoSlideshow', 'before_widget' => '<div class="widget %2$s promo-slideshow"><aside id="%1$s">', 'after_widget' => '</aside></div>', ) );
After this the widget area named “PromoSlideshow” appeared on the admin panel under “Appearance / Widgets”, in the right pane ready to drop-in some content from the left pane. This is well documented on the WordPress Codex.
After setting up all the widget areas it was time to fill them with content. There were three types of widgets:
- Plugin generated. Some plugins make widgets readily available on the left pane to drag and drop to widget areas: “Language Switcher”, “Facebook Like Button” and “Slideshow Widget”.
- Content Block. This is a widget generated by a plugin, but I’m separating from the above type because this is only an indirect way of adding HTML to the widget area, and not a specific functionality like the ones on the above type. The content is managed with the plugin own tools and referenced by the widget when it is dropped on a widget area. The difference between this method and adding a Text widget to the widget area is that with the Content Block we have access to a full HTML editor. Besides, the same Content Block entry can be used in different places without the need for entering repetitive content.
- Text. This widget was used on only one place where pure HTML was needed: a code snippet from TripAdvisor.
Content
At this point all the pages were filled in with content, images were uploaded, slideshows created.
The Content Block plugin played a vital role here too. There were some content that repeated on several pages, like the pricing table. This content was placed in only one Content Block entry and referenced on the page content by means of a WordPress “shortcode”. This plugin adds a button (“Add Content Block”) to the HTML editor (of pages and posts) to automatically add a Content Block reference.
During this phase, the formatting styles were also setup on the LESS file.
Forms
The site uses 4 forms: reservation and contact forms in both languages. Using the “Contact Form 7” plugin I created one form and tested it. Added the plugins “Really Simple CAPTCHA” and “WP Mail SMTP” and tested the form submission. Then advanced to create the other 3 forms. For creating the other language forms the plugin provides a “duplicate” functionality that became very handy.
Customizing “Not Found” Error Page
On this theme the 404 error page is located in the file 404.php. I’ve removed all the existing code to show latest posts and such. Just left the error message which is using the WordPress translation mechanism through the _e() function. For this project this was the first time I would be in need of the translation features of WordPress. I needed a translation of the error message in both PT and ES. For this I must use the provided language file of the theme (file “languages/theme.pot”) to server as a template to generate two files: one for each language I’m using on the website. When generating these two files, I would change the phrase used in 404 error page to the languages I needed. It’s pretty much all described in the article “Translating WordPress”. I used Poedit to generate the two translations files. Actually they are four, since for each language there are two files: the translated file and a compressed version of it.
Site HTML/CSS Validation
Used two tools for site HTML/CSS validation:
With the HTML there were mainly two issues:
- the Tripadvisor code. In a URL there were “&” instead of “&”.
- Duplicate ID “colophon” in the HTML.
With the CSS I’ve found many errors and warnings, but most of them on the plugins!! On my code there were only two minor errors, like forgetting an “s” in a time specification on a transition. The warnings on my code were only because of unknown vendor specific properties.
Moving the Site
The main development was made locally on my computer. But at some point I wanted to check the process of publishing the website to a production server.
“XCloner” mentioned as a WordPress plugin above, is in fact some PHP code to make backup and restore of files and a MySQL database, mainly. Its free (they sell the support) and it worked perfectly.
So, moving a WordPress site from one place to another involves:
- Move the all the files (using XCloner)
- Move the database (using XCloner)
- Change the domain of the site in the settings.
- Having built the site using the plugin “Dynamic SiteLinks” should prevent you from having to change domain in the content, but…
- Check URLs in content that still point to the older domain.
The last point is a bummer, mainly because it’s hard to detect URLs that are pointing to the original site, because that is probably still online and so serving the content. I mean: you load a page of the site at the new location. Looks perfectly. But, for example, if an image is loading from the original site, you won’t be able to tell from just looking to the site, since it would look perfect, also!
One approach to finding “old” domains, is to run a tool like the “IIS Search Engine Optimization (SEO) Toolkit” to analyze your entire site and produce reports where you can dig in for the original domain.
In my case I had no problem with the textual content of the website, but the some slideshows were using absolute URLs for the images. After I changed all of these URLs to relative, all went well.
Have fun!