Archive for the WordPress Category

May 12th, 2005

To update or not to update?

The avid developers of WordPress have released yet another version of the blogging software. This time the release only minor, but they have changed so many files that I’m really reluctant to upgrade, as I’ve fiddled with some of the files to get Nomagid.com working perfectly for my needs.

I almost missed the upgrade, as for some reason the Dashboard in the WordPress admin pages didn’t show that article. Maybe that bug has been fixed in 1.5.1…

Maybe I should try to refactor my changes into plugins, but the current plugin architecture seems to be a bit blurry to me… And some changes are not even doable with plugins. Dang.

Oh well, better continue pondering and maybe even do something in the near future.

May 9th, 2005

Recent search strings for ShortStat

My site is frequently visited by people who find it using search engines. To better understand the dynamics of the used search phrases, I’ve used ShortStat to see the most frequently used strings.

This approach has one flaw: I don’t a decent visibility on the trends — the phrases tend to change over the time and if some phrases are dominating the result set, the newcomers may not have even a possibility to enter to the list.

To elaborate the problem, “Shortstat” is one of the most frequently used search strings to find the site, thanks to several small improvements that I’ve made. But most people find the site using terms related to travelling, such as “harald+turku” and “taco bell in shanghai”.

I’ve solved the problem by adding yet another view in ShortStat for showing recently used search terms. Follow these simple instructions to get it working on your site:

  1. First, you have to alter your ShortStat database to include a timestamp column in the search terms table. Open a connection to your database, either using mysql command line client or a web interface, and issue the following command:
    alter table si_shortstat_searchterms add ts timestamp(14);

    This adds a column that automatically updates itself to the current date and time when the row is inserted or updated.

  2. Add the following line to the configuration.php:
    $SI_display['timeformat']       = ‘H:i’;
  3. Add the contents of shortstat_recent_search_terms.txt file at the end of functions.php in your ShortStat install directory.
  4. Add the following code snippet to desired location at index.php in your ShortStat directory:
    <div class="module">
            <h3>Recent Search Strings <span>When</span></h3>
            <div><?php echo SI_getRecentKeywords(); ?></div>
    </div>

Now you should have a working system. You have to wait patiently until there has been enough search string entries to get the table filled with correct dates.

May 4th, 2005

Dissecting front page, part 3

Let’s continue the front page analysis after a longish pause. The previous article finished the left column and now it’s time to move onwards with the rightmost part of the page.

This part of the front page concentrates mostly on the reviews. Oddly enough, majority of the current visitors tend to find their way to the reviews using search engines. Maybe I write reviews from such locations or places that are interesting, but still not covered by any major travel review site.

The reviews provide also good opportunity to add some semirandom content to the front page to keep it fresh for those people that visit the site several times between two journal entries.

Top right corner

The topmost part of the right column has buttons for changing the size of the fonts (13). In Internet Explorer, there is yet another button for adding the page to favourites. If anybody knows how to do this trick in other browsers, please let me know.

The font change is done by switching the active stylesheet in JavaScript. The used fonts are defined in very small stylesheets that import a shared stylesheet that has all definitions not depending on fonts. This arrangement eases up editing and saves bandwidth.

The Reviews section (14) shows three random reviews from the most frequently visited categories: Restaurants, Accommodation and Shopping. There is a MySQL clause that is executed in a loop to produce the data. The topmost review is cut after two paragraphs and the two others have only one paragraph.

The review header (15) contains a link to the appropriate review category and basic information about the reviewed location. The title of the review is a link for the whole review. There is a similar link at the end of each review, coupled with a link to the reviews front page.

Middle right section

The Recent Reviews section (16) contains six latest reviews in the database. These are selected with one MySQL clause that sets them in the correct order based on the timestamp inserted by WordPress. Only a few fields are read and the clause has limit keyword to read the desired number of rows. The read information is prettyprinted in a loop. The data is shown in an HTML table as floats were broken in some browsers and the table just fits better for showing tabular data.

More Reviews (17) drop-down box is created again in a loop that iterates through rows resulted from a MySQL query. The query itself is complex as it has to join an SQL table onto the same table. This had to be done, as the review countries and cities are stored as WordPress custom fields. If I would have just shown cities or countries, I wouldn’t need this complexity.

The result set is ordered by the country and the city, in alphabetical order. The loop iterates through cities and when the country value changes, it prints out the previous country and all the cities in a data structure that it has been creating. Now the data structure is cleaned and new cities are piled there, until a new country pops up or the result set is exhausted. The number of reviews per country is just a sum of the reviews in cities in that country.

The big numbers (18) are generated by an SQL clause that counts the various review types from the database. The results are stored in array, and the number is picked using the name of the type in PHP code. Very simple code with lots of HTML embedded.

Bottom right section

The bottom part of the right column contains an internal banner ad (19) that hopefully lures visitors to the other parts of the site. These adds are written into one PHP file that has simple random statement to select the correct code to be shown. There is a bit of logic to prevent ad pointing to the current section. Every Nomadig.com section has a unique identifier that is known by the PHP scripts, and that identifier is checked against the identifier in the ad. If they match, the next ad is chosen instead.

This pretty much covers the cover page. There is one additional perk that is not easily visualised: There is a small pane under Other Nomadig.com Services. This pane is used to balance the left and right columns. The length of the content changes for every page load and thus the HTML may have blank spots. There is no good way to instruct browsers to stretch a div vertically to cover everything, and thus there would be areas that show pure white — the background colour of the page. This wouldn’t be a problem if the text background would be white, too. This is not the case here, so I had to do some JavaScript magic.

There is a small JavaScript snippet after that balancing div that calculates the vertical position of that div and the vertical position of the Sections div at the end of the left column, and adds their height to those numbers, respectively. This provides me the position of the lower edge of the divs. If they are not equal, and usually they aren’t, the column with smaller number will be stretched with JavaScript to fill the rest of the space.

May 2nd, 2005

Commenting in reviews section

Now all reviews under travel / reviews section have commenting possibility. This change was made to serve better those visitors that find the site through search engines, and who do not venture to the journal to comment the article.

Regarding technology, I spent better part of the weekend figuring out how to bend WordPress arm to allow using its template capabilities outside the journal section.

First and foremost, I had a huge problem of launching the template. The template selection has a hook, but you cannot insert anything to that hook outside WP code, as the function for adding hooks is not yet defined — it will be included later. I solved this by adding the function directly to the correct array (found out by reading the source).

Now the correct template file was used, but it couldn’t show any posts. It showed the title of the post on the browser title bar, but the post itself was not shown. I couldn’t figure out why and had to back out.

The next solution was to introduce a new variable in the Reviews’ PHP code and change the template’s index.php to launch another file when this variable is set. Now the reviews.php includes WP if the user requests for a single review. This worked fine and I could concentrate my efforts to make the new file inside the template directory to show reviews properly. That wasn’t hard.

Then I added comment form through normal WP template function call. This was successful, except that I couldn’t easily get rid of the trackback text. I summoned yet another ugly PHP hack to check whether that line should be printed or not.

Now the whole page looked good and I could add comments without big problems. Only small problem of sending me back to journal after adding a comment persisted. I had to comment a couple of lines in wp-comments-post.php to make the HTTP redirect to return to the original page.

The last issue was that I’ve added some elaborate and nice looking error messages in the commenting process and those wouldn’t work. The used cookies were bound to /journal/, so there were not send to /travels/reviews.php. Another change in wp-comments-post.php and problem was solved.

Finally the thing was ready. As I couldn’t find any issues after an extensive test period, I decided to launch it right away. First, of course, I had to remove a bunch of dead code that was used in the earlier versions to show the single review.

Hopefully you find the commenting possibility useful.

April 10th, 2005

Dissecting front page, part 2

Continuing from the previous article, let’s discuss about the left middle and bottom sections of the front page.

This part is usually still shown on modern computers with resolutions 1280×1024 or bigger. It may be partially hidden in 12″ laptops, depending on the selected font size.

The contents of the section are still primarily from the journal, but also photo gallery has a small section to spotlight a random gallery.

Middle section

The front page shows in total eight most recent journal posts that are not reviews. The first one is shown on the top of the page and the rest in section More in Journal. The first article is shown with one paragraph (8) and the rest without any text, just the title. If the entry is in several categories, only one of those is shown to save space.

I have picked certain articles that have value over the time. These are listed in section Staff Picks (9). The picked articles have one WordPress custom field as a marker and the front page PHP script selects those articles in alphabetical order by titles.

The photo gallery is based on my own script. The galleries are managed through a specialised admin interface and the information is stored to several files. One file contains information about galleries themselves and every gallery has one file for the images.

The front shows one random image from the galleries (10). The gallery information file is read in and a gallery is selected using rand(). That gallery file is read in and the first photo is shown. Every gallery has similar type landscape image as the first image for better look for the gallery front page and that image is used here, too.

The bottom part of the left column contains information that is not designed to invite visitors to explore new parts of the site. Instead, it acts more like a brief sitemap to show the site structure.

Bottom left section

The sections of the site (11) are listed in the same order as in the navigation menu. The main subsections are listed also. The journal categories are considered as subsections in this respect. The PHP script creates a data structure from the sections and subsections, and iterates it to produce the section table. The number of items is divided with three to create the columns. A
section is not, however, cut in the middle — all subsections are always shown under their section.

One of the sections is randomly selected and explained (12). The explanations are stored in the front page and the random number just decides which explanation to show this time.

That covers the left column. Next time, I’ll discuss more about the right column that concentrates mainly to the reviews.

April 8th, 2005

Dissecting front page, part 1

The new front page has several nifty features that are results of hours and hours of PHP coding to extract information with added value from the WordPress database and other sources within Nomadig.com.

I’ll explain the major pieces of the page and try to give a picture how the page has been put together from various pieces. As the space is limited (and maybe also your interests :), I usually skip most of the implementation details. If you are a compenent PHP programmer, you can fill in the blanks. And if you aren’t, then you shouldn’t try to do this at home.

The top left corner of the page contains information from the journal only. The next picture contains the most important dynamic elements of this part of the page.

Front page top left corner explained

The background image (1) is based on the current season. There are four images and four corresponding CSS classes that use images as backgrounds. PHP code calculates the season from the current month and selects the correct class.

The issue number (2) is the total number of published entries in WordPress database, read with a simple count() SQL clause. The date (3) is the publishing date of the latest entry, also read from the database.

The main article shows the latest published entry with its date (4) formatted with additional field for the day of the week. The entry may belong to several categories (5) that are all shown and linked to the journal.

Front page left middle section explained

The end of the latest article has a link (6) for reading the rest of the article. The front page shows the three first paragraphs of the entry.

After the first article, there is a Google ad (7) to gain some income to support the site. If Google does not serve any ads, Nomadig.com ad system is used instead to show some banner here (not that many of them currently).

In the next part we’ll discuss about the middle section of the front page: the latest articles, staff picks and gallery.

April 6th, 2005

ShortStat with lowercase search terms

I’ve recently taken more serious approach for following the search terms people use to find Nomadig.com. The reviews section seem to gather a good number of hits from Google and other search engines. This journal is also a prime candidate, as all reviews are shown here, too.

Some people either write grammatically correctly or copy’n'paste names and other terms that have uppercase letters. For example, both Spaksmannsspjarir and spaksmannsspjarir have appeared. Unfortunately, ShortStat is not able to count them as one term. Instead I have several variations of the same name in the stats.

I finally decided to do something. Fast glance to ShortStat source code revealed that I could manipulate the SQL query to be case-insensitive. This approach has the basic flaw that if the first search term has uppercase letters, those letters are stored as is in the database. All future searches would just update the count and the search terms display would look ugly.

Instead of fixing the query, I simply added one PHP line to convert the search terms into lowercase before sending anything to the database.

To have the fix, find fuction SI_sniffKeywords($url) and the following line:

if (isset($searchterms) && !empty($searchterms)) {

Add the following line below that line:

$searchterms = strtolower($searchterms);

Presto! Now you have case-independent ShortStat search terms module. There is one bummer, though. If you have used ShortStat for a while, there may be several different variations of the same terms in the database already. I’ve selected not to do anything for those entries for a while, as in the long run they will be pushed down in the display anyhow.

February 23rd, 2005

Updated to WordPress 1.5

Noticed anything strange here in journal? No? Good!

I just finalised updating to WordPress 1.5. The process was partially smooth, but as I had hacked the original WP and some plug-ins for better layout or additional features, I had to port those changes one by one.

The updating process (in case you’re interested) was the following:

  1. Backup the whole database with mysqldump.
  2. Edit the resulting file to change the database.
  3. Create new database and provide enough rights to relevant MySQL users.
  4. Pump the data in the backup to the new database.
  5. Install WordPress 1.5 to some location.
  6. Fix the config to point to the correct database.
  7. Run upgrade script provided by WordPress.
  8. Change the blog URL manually from the database. Without this fix, the admin pages would redirect to the old blog.

Now we have one running blog in the old location, seen by all visitors and another blog that is used to get things right before publishing.

  1. Create new theme.
  2. Copy layout files to the new theme and activate it.
  3. See the results and compare to the old blog.
  4. Fix an issue and go back to the previous step. Fortunately, I had marked my changes to the old source — it was relatively easy to grep them and then port them to the new code. Some changes were no longer needed, for example, the calendar has been fixed to work with Finnish weekday style.
  5. Install plugins and activate them. Add own code to the Spaminator. Some ideas were already implemented, so only 2/3 had to be ported.
  6. Change external files that use the blog database. Test them.
  7. Copy comment form layout and functionality from the old code. Change the name of the wp-comments-post.php file.
  8. Find a bug in Textile JavaScript and fix it.
  9. Test that everything works.

The new blog is running as an exact replica of the old one. It was time for the switch.

  1. Move image directory from old blog to new one.
  2. Configure new blogs URLs to point to the correct location.
  3. Rename old blog directory.
  4. Rename new blog directory.
  5. Test that everything is still okay.

Easy, isn’t it?

By the way — please inform me, if you find anything out of ordinary.