SEO Module Alternative to Nodewords for Drupal Developers

After listening to Seth Cohn’s very inspirational speech about the Context module at the DrupalCamp NYC 8, I got inspired to play around with that module a bit more. Primarily, Context serves as alternative way for the block administration. However, Seth focused more on Context’s ability to keep variables during a page load available, without the need to use global variables or other workarounds.

One of my recent projects required very specialized SEO optimiziation. Initially, I started using the Nodewords module, which is brilliant and very easy to use. In certain areas however, I felt that Nodewords makes it harder for me as a developer to achieve my goals, so I wanted to come up with a different approach. By no means is this module supposed to be a replacement for Nodewords, it’s more of an exploration of the Context module.

Search Engine Optimization for drupal module developers

In this example, I’m primarily focusing on the head title (the title that appears in the browser for any open window) and the meta description (which will show up as a teaser in search results).

I’ve identified three different “types” or areas that often require specialized SEO optimization. These are:

  1. Nodes (per content type)
  2. Pages (created by other custom Drupal modules)
  3. Views Pages (created by the Views module)

SEO Head: A centralized module that handles head title and meta description

If you’re developing in a similar way as I am, you like to create smaller modules for each distinct functionality. In my approach for this alternative module, I am using a central module called SEO Head, which works as the central module to set the head title and meta description. This module is called at end of the page execution process by using a relatively high system weight of ‘200’ (the default being 0). By calling this module at the end, I am trying to make sure that no other module sets the head title. This module overrides the existing head title and sets the meta description.

Looking at the above list, only one of the areas is defined within the module: Nodes, per content type. By the time the SEO Head module gets called, the full node object is available, so anything (including CCK fields) can be used for the page title or meta description. See lines 17 to 35 in the source code.

In this example implementation of the SEO Head module, I am using a special text CCK field for the page title of a node of the type ‘page’ (see the file attachments below, you can install this field easily by downloading the node_page_title module, which is a Features module.). For the regular “story” node type, the body of the story is used for the meta description. These two instances are just examples of what could be done here.

Using Context: Define head title and meta description in your custom module

Instead of defining all page titles and meta descriptions in one central place, I thought it would be much ‘nicer’ to have each custom module you create for your site define their page titles and meta descriptions, if needed. In order to make this happen, I am using the Context module as a vehicle to transport any head titles and meta descriptions to the SEO Head module. This allows any module to set these values ‘remotely’, meaning directly in the module. To demonstrate this, I created a separate example module called ‘example’, see download list below. The Example module provides a page and a simple view.

For any page defined in a module, just use the context_set function (line 13 and 14 in the example module) to set head title and/or meta description, and the SEO Head title will take care of the rest.

To define head title and meta description for Views (which is currently not possible with Nodewords), you can make use of the hook_views_pre_execute hook (line 23 following).


Again, these modules are just some examples for using Context in a creative way, and aren’t meant to replace the Nodewords example in any way. I’m looking forward to some interesting discussions.

Drupal 7 Module Development – Liveblogging from Drupal Camp NYC 8

List of Changes

Converting 6.x modules to 7.x – Categorical

New Database API

  • Vendor-agnostic abstraction layer
  • Built on top of PHP’s PDO library
  • Current drivers: MySQL, PostgreSQL, SQLite, SQL Server
  • Can still write SQL. Example: $result = db_query(“SELECT nid, tilte FROM {node}”);
  • Placeholders have changed. Strings don’t have to be enclosed in single quotes any more, the Drupal database abstraction layer does that for you. Example:
    $sql = “SELECT title FROM {node} WHERE type = :type”;
    $result = db_query($sql, array(‘:type’ => ‘page’));
  • Results sets from select queries are easier to loop over (e.g. with a foreach ($result as $record) { // do stuff }.
  • Dynamic Queries possible. Example too complicated to note down in 1 minute.

hook calls

  • hook_nodeapi: no more $op
  • Replace with several individual hooks
  • Same for hook_user and hook_blocks

Views for Developers – Live Blogging from Drupal Camp NYC 8

By: Frank Carey

Question: How to integrate your custom module with all the goodie-ness of views?

Shameless Plug: I attempted to write a similar post about this in this post: Views Integration with your custom module and Overwriting Views Handlers

The custom way to integrate your module is by using hook_views_data. Using this hook, you would define how your module exposes data to views. A great alternative is using the Table Wizard module.

Example: Create Custom Watchdog View using Table Wizard

(Following list is not an actual “step by step” list, but the general idea is that Table Wizard allows us to create the array required for hook_views_data in a much simpler way than coding it by hand).

  • Select “Add existing tables”
  • Select the table you want to expose
  • Select “Provide default View”
  • Create a new table wizard entry for users
  • Create a relationship bewteen the two using the relationship and join on uid (users.uid joins with watchdog.uid)
    Options here are manual or automatic (manual: relationship needs to be added manually in the view, automatic: happens in the background without option in views interface)
  • Select the new table wizard entry that was just created and then export the views definition for it

Building Features and Exportables (The Wave of the Drupal Future) – Live Blogging from Drupal Camp NYC8

By: Frank Carey (frankcarey)

Why settings should be in the code and not the database? Common problems with Drupal

  • How to track changes?
  • How to revert back in the case of a mistake?
  • How can configurations be re-used?
  • How to work as a team?
  • How to update settings across sites?

How to accomplish this

  • Certain modules have their own import/export capabilities, such as Views, Migrate, Rules
  • Other modules use CTools export API, such as Panels, Context (current standard)
  • Use modules like Strongarm that export the variables table

Enter: Features (Features Module)

  • Features is basically an exportables manager
  • Creates a “features” module (which is just a normal module)
  • Provides GUi interface to choose what should be exported with features
  • Provides drush integration

What should a feature consist of?

  • Logical sections and “atomic” functionality
  • Examples: Blog, Photo Galleries

Features of Features

  • Shows all module dependencies, content types, image cache types and views
  • Recreate and modify an existing feature (template)
  • Export features (distribution)
  • Modify exported features distribution in the include files directly

Takeaway Notes from this presentation:

Hardcore Drupal developers know the following modules well. How could I have missed using Features so far?

Really advanced presentation. Frank: Congrats on the Sony gig 🙂

Context: Changing how to Code in Drupal – Liveblogging from Drupal Camp NYC 8

By Seth Cohn (sethcohn)

Get the Context module here:
Another great module suggestion: (not necessarily related to Context though)

What’s the idea of context

Context pays attention to what’s happening on the page while the page is being rendered. Developers used to take arguments from the final URL path, but Context is saving a lot of information (such as type, nid, uid etc.) for later use (in the page load process). This is pretty awesome, because all content (such as the full node object) is already available in the Context. In short words: Smart global variables that persist throughout the whole (Drupal) page load.

The original description from the module page: Context allows you to manage contextual conditions and reactions for different portions of your site. You can think of each context as representing a “section” of your site. For each context, you can choose the conditions that trigger this context to be active and choose different aspects of Drupal that should react to this active context.

Basic construct of a context: Add a block using Context

  • Conditions: When should this context take effect?
    Example: This context should be active any time I look at a node with the type “page”, but not on the edit form
  • Reactions: What should happen?
    Example: Show a block in a specifc region
  • Et Voila: Never use the blocks interface again

Another Example using Context Reaction: Theme

  • Condition: You’re looking at a node type “page”
  • Add a specific body class to this page

Other Conditions

  • Node tagged with a specific item
  • Looking at a specific path (including wildcards)
  • Set this context for a specific user role
  • Show this context for specific views
  • All conditions can be combined with each other and can be used with either AND or OR

Other Module Integrations:

Drupal as a Web Services Platform for iPhone

By: Jingsheng Wang (skyredwang,

Some Stats:

  • 1.67 Billion Internet users. 4 Billion Mobile Phone Users. By 2013, mobile phone users with Internet access will surpass Internet users. Or earlier.
  • iPhone has the most page requests (55%), Android next (20%) then Blackberry (12%). Rest is minor.
  • Google experienced 5x more mobile search requests from 2008 to 2010
  • Simple App: 50K to 150K for a simple mobile app

How to expose Drupal APIs to external clients?

With the Drupal Services ( Drupal Services adds a communication layer to your Drupal application. This module allows to output data in JSON, RPC etc.

Services Components:

  1. Servers (what should the output be?)
    1. XML-RPC
    2. JSON
    3. JSON-RPC
    4. REST
    5. AMFPHP
  2. Authentication
    1. API Keys
    2. Drupal Sessions (servers sessions can be re-used on mobile devices)
    3. OAuth
  3. Services
    1. Nodes
    2. User
    3. Taxonomy
    4. Files
    5. System
    6. Search
    7. Views Services
    8. Location
    9. Flag
    10. Any other infrastructure can be re-used (hook available for services module)


Configuration: JSON_Server + Key Auth + Session
POST: method:system.connect
Return: sessionID

Example URL:

Framework and Platforms

iPhone (IDE: X-Code, Language: Objective-C)
Android (IDE: Eclipse, Language, Java, C, C++)
PhoneGap (Open Source platform attempting to build cross-platform mobile apps, build apps in HTML)
Appcelerator Titanium API (Presentation from DrupalCon SF)


(list taken from

OAuth Handshake (“The future of authentication”)

Used by sites like Facebook and Flickr. 3rd-party app makes a request to grant access to data. Username and password only need sto be provided to first-party site, not 3rd-party application.

Drush Introduction – Live Blogging from Drupal Camp NYC 8

By: Robbie (

Where to start:

  • Morton the king of Denmark:
  • Development Seed Blog:


  • One doesn’t install Drush (it’s not actually a Drupal module)
  • Download and install in ~/bin
  • Add an alias to your .bash_profile (basically, telling the operating system where this lives):
    alias drush=’/Users/[username]/bin/drush/drush’
  • Video Tutorial:

What can you do with drush?

  • Install Drupal with a command
  • Log directly into mysql (on the command line)
  • Download modules right into the correct location for Drupal (a few at once)
  • Enable modules from the command line
  • Create database dumps
  • Clear your cache (selectively)

So in a nutshell: Pure command line awesomeness. Great presentation!

Beginning Drupal 7 – Live Blogging from Drupal Camp NYC 8

By Jacob Redding & Jennifer Lampton

What’s New: Overview

  • Admin Menu
  • Overlays (can be turned off)
  • FIelds
  • Image Styles (combines all the imagefield, imageapi etc.)
  • RDF
  • Theming Functions
  • New database layer (completely different abstraction layer, less direct DB queries). Goal: broader reach, including Oracle, MS SQL

What’s New: Details

  • Overlays for management and content creation functions: Never leave the actual page
  • Basic content type: Article, Basic Page. Article now has an image field included (which is part of core)
  • Tags are built in by default
  • Node attributes are styled better
  • Admin menu built (a version thereof). Can be extended with customizable shortcuts
  • Fields (CCK) built into core. Anything can be extended with additional fields, including comments, taxonomy, and users. BIG!
  • Media Configuration Section
    • Image Styles: formally image cache presets
    • File System: Possible to selectively choose a private file folder (D6 required either all files to be private or all files to be public)
  • New Themes: Bartik, Seven
  • Display of permission is smarter, e.g. admins inherit permissions from authenticated users
  • New options for case of deletion and what happens with related content. Choice can be given to the user.
  • User profiles can use global image styles (a.k.a. imagecache for users)
  • Users itself can use all fields (would use Content Profile for this in D6)
  • Drupal 7 has a module called Profile (which should not be used for new sites, as fields can be added to the user directly)
  • Modules can be installed through the Drupal interface (either through upload or direct tar archive). FTP/SSH not needed anymore.
  • Views not included, because of (technical) complexity of integration Views into core

Overall Impression

  • Look much more simplified and un-geekified
  • Easier descriptions targeted and Drupal novices
  • D7 will have a lot more distributions

Drupal Camp NYC 8: My first Drupal Camp and I can’t wait!

This is the first time I am doing an intense 2-day Drupal training in Brooklyn, NYC: DrupalCamp NYC 8. I’m unsure about what to expect, but from looking at the schedule, it looks like an intense one, as there are only about 10 minutes of breaks between the sessions 🙂

I’m reviewing the sessions right now and here’s my list of sessions I want to attend:

I can’t list all the ones I like, because they are all great, but I’m sure to post a quick update from this weekend.

Flickr integrates with Facebook. Sort of. Ok, just a tiny bit.

I feel like I’ve been waiting for this integration for years. I’m a Flickr PRO user (haaagendazs), but haven’t really used Flickr that much, since all my friends want to see my photos on Facebook, not Flickr.

We’re not quite there yet.

As a starting point, Flickr now has an option to automatically push your photo uploads on Flickr to your Facebook news feed. That’s great. However, the thumbnails in my Facebook news feed still link back to Flickr. The feature I’m expecting from Flickr is a feature that uploads my photos in the highest possible resolution to Flickr and then automatically uploads them to Facebook, so I can tag them there and allow my friends to comment on them. They surely won’t create a separate account on Flickr.

So this integration is a bit disappointing, as it doesn’t seem like Yahoo really thought this one through:

  • At first, Flickr created a new news feed entry for every photo that was uploaded. ReadWriteWeb reported about this annoying problem here:
  • To link your account, there’s an option in Flickr under the account tab ( Just activating the Facebook integration here led me to an error message that didn’t tell me what happened. With some extra searching, I found out that I needed to activate the Facebook integration in the Yahoo Pulse settings. First, I didn’t even know that I have a Yahoo Pulse account. Second, Yahoo Pulse seems to suffer from an inner struggle, because it can’t decide if it should present information to me in German or English.
  • Most disappointingly: With this Flickr/Facebook integration active, I still need to upload photos to Facebook manually so my friends on Facebook can comment and rate. Thus, it looks like I’m uploading the same photos twice, which will look confusing for my friends (or make me seem very narcissistic).

After a couple of test uploads, I’m turning this feature back off.