gregh's blog

Drupal Userpoints and the big Boys

In the last two weeks I have come across three different venture backed groups that are trying to help sites 'Gamify' their member interactions.

Drupal 7 Beta, kicking tires time

I am willing to admit that I am not cutting edge guy, and neither is the company I work for. I keep up to date on new modules and processes, but rarely try out alpha labeled modules.

Drupal 6 Ultimate Community Site Guide Review

Recently I received a review copy of Drupal 6 Ultimate Community Site Guide (2nd edition) and I jotted down some notes as I went through the book. I am currently constructing a more community focus site, and I was hopeful to learn a few pointers along the way. There both ebook and paperbook versions of the book.

My general impressions is that the book tries to tackle some important site building tasks using Views, Panels, CCK, and other important contributed modules, while also focusing on the using standard core modules (and more that will be in Drupal 7 core) which is important for future proofing the site. The author, Dorien does a good job to use tackle many modules that fill out a community site, but of course you can't tackle them all in 150 pages (no User Badges, cursory mention of blogs, and Organic Groups is not fleshed out much).

Keep reading for a chapter by chapter breakdown of the book.

Drupal for Facebook, Quick posting to FB Streams

In a recent project update to our RV Parks site we wanted to add some Facebook integration points. Add a few 'Like' buttons for Facebook on pages as well as the ability to login using Facebook connect. Numerous modules can do this for Drupal, but we moved forward with Drupa for Facebook (demo site at http://www.drupalforfacebook.org) based on some other features I want to talk about here.

Drupal for Facebook also has Facebook Stream integration in a submodule, which we wanted to use to post reviews written by our users to their FB walls, or streams as they are now called. The Streams module is more of an API that you need to implement in a custom module, but a fine example is given as a recipe in the Drupal for Facebook documentation at http://drupal.org/node/685320. A great example that worked for us with a bit of our own tweaks.

But, what we really want to do is post directly to FB without the extra popup confirmation that is used the example. We wanted to speed up the workflow. To do this we need get an 'Extended Permission' from Facebook for each user. The Extended Permission contrib module that is packaged with Drupal for Facebook exposes these permission, but only on the user's profile page, which wasn't ideal for our use case.

So we need to obtain the extended permission skip the confirmation, and then we need to update the code to bypass the confirmation screen if we do have the permission. To do this we have to update the form_alter hook in the example to ask for the permission, and then update the nodeapi call to skip the confirmation if the permission is given.

Here is the updated form_alter code from the example:

function dff_custom_form_alter(&$form, $form_state, $form_id) {

   if (isset($GLOBALS['_fb']) && fb_facebook_user()) {

   $fb = $GLOBALS['_fb'];
   $fb_app = $GLOBALS['_fb_app'];

   if ($form['#id'] == 'node-form') {
     // Add checkbox to control feed publish.
     $form['dff_custom']['stream_publish'] = array(
       '#type' => 'checkbox',
       '#title' => 'Share on Facebook',
       '#default_value' => TRUE,
     );
   }
   else if ($form['form_id']['#value'] == 'comment_form') {
     // Add checkbox to control feed publish.
     $form['dff_custom']['stream_publish'] = array(
       '#type' => 'checkbox',
       '#title' => 'Share on Facebook',
       '#default_value' => TRUE,
     );
   }

   try {
       $has_perm = fb_call_method($fb, 'users.hasAppPermission', array(
       'ext_perm' => 'publish_stream',
         'uid' => $fbu,
       ));
     } catch (Exception $e) {
     fb_log_exception($e, t('Call to users.hasAppPermission(%key) failed.', array('%key' => $key)));
   }

     //If the permission has not be granted yet, add a link to a new window that asks for the permission.
     if (!$has_perm) {
     $form['dff_custom']['stream_publish']['#description'] =
       l('Auto share all reviews (skip confirmation popup)',
'http://www.facebook.com/authorize.php',
       array('query' => 'api_key='.$fb_app->apikey.'&v=1.0&ext_perm=publish_stream&next=http://www.rvparking.com/user/'.$user->uid.'&next_cancel=http://www.rvparking.com/user/'.$user->uid, 'html' => TRUE, 'attributes' => array('target' => '_blank'))
       );
     }

   }

}

Specifically the try/catch code (couched from the Extended Permissions module) is checking to see if the 'publish_stream' extended permission has already been granted by this user. If not, then a link is added to the description of the 'Share on Facebook' form element.

Next we update the hook_nodeapi function (similar edits needed for comments, not shown here).

/**
* Implementation of hook_nodeapi().
*
* Publish to facebook Walls when users submit nodes.
*/
function dff_custom_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
   if ($op == 'insert' || $op == 'update') {
     if (isset($node->stream_publish) && $node->stream_publish) {
       //dpm($node, "dff_custom_nodeapi, publishing to stream");
       // http://wiki.developers.facebook.com/index.php/Attachment_(Streams)
       $attachment = array(
         'name' => $node->title,
         'href' => url('node/' . $node->nid, array('absolute' => TRUE)),
         'description' => $node->teaser,
       );

       $user_message = t('Check out my latest post on !site...',
       array('!site' => variable_get('site_name', t('my Drupal for Facebook powered site'))));
       $actions = array();
       $actions[] = array('text' => t('Read More'),
         'href' => url('node/'.$node->nid, array('absolute' => TRUE)),
       );

       $fb = $GLOBALS['_fb'];

       $fb_session = $fb->getSession();
       $fb->api_client->session_key = $fb_session['session_key'];
       $fb->api_client->expires = 0;

       try {
         $success_data = fb_call_method($fb, 'stream.publish', array(
           'session_key' => $fb_session['session_key'],
           'message' => $user_message,
           'attachment' => $attachment,
           'action_links' => json_encode($actions),
         ));
       } catch (Exception $e) {
         drupal_set_message("NOTTTT!!! Added on FB Wall: Showing Dialog.");
         fb_stream_publish_dialog(array('user_message' => $user_message,
           'attachment' => $attachment,
           'action_links' => $actions,
           ));
       }
     }
   }

}

Now we use the try/catch method to post the update to Facebook directly. The fb_call_method function is provided by Drupal for Facebook. If the user has granted the 'publish_stream' permission, then the post will succeed, if not then we use the normal fb_stream_publish_dialog method which will create a JS popup box after the form sumbits that will ask the user if they want post to Facebook.

Now we have much more streamlined posting to Facebook workflow. If no extended permission are granted, it behaved just like the example with a popup confirmation. But now in the form we ask for the extended permission, and if granted we speed up the posting to Facebook. Good for all.

Advomatic plus Mercury is Fast

Coming out of the SF DrupalCon Cloud Hosting session, I had been looking for a hosted Mercury solution. I was waiting for Chapter Three's Panteon Mercury solution, but it has been in private beta for months.

Then I saw that Advomatic has launched a hosted Mercury solution, so I checked it out.

I will let the data speak for itself concerning the speed improvement's seen by my private Dog parks website. Here is the graph and it is easy to see when I move the hosting over.

Dog Park USA speed graph

And beyond that, it was very simple to move over the site. Just merged my Drupal 6 install into a Drupal Pressflow install, added and installed the memcache and varnish modules, and watched the load times drop.

Even if your site only has thousands of visitors a day, give them a faster site.

Updating the page cache on time

On RVParking.com, we have a detailed directory listing page. It is complex CCK node themed, with an included Google map for location. Also included are two embedded Views. One for photos (a slideshow type photo with AJAX paging) and a View of Reviews (a review node type, with fivestar voting and attached pictures among other things. Both use node references to attach them to the park.

Our Problem: Cached pages with embedded views show stale view data.

The crux on the problem is that a park page would not be rebuilt when a new review or photo was posted. At first I thought it was the view that wasn’t being updated the new photos or reviews. After even turning off the view cache, the problem persisted.

So I looked higher up the cache ladder, and figured out it was the node cache that was the issue. Of course, how would the park node cache know to expire its cache when a review or photo with a reference to this park had been added or updated. But we can tell it to using the nodeapi_hook().

function rvparks_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
     case 'insert':
     case 'update':
       if ($node->type == 'review' OR $node->type == 'park_photo') {
       $url = url('node/'. $node->field_park_reference[0]['nid'], array('absolute' => TRUE));
       // delete cache entries for that url
       cache_clear_all($url, 'cache_page');
     }
   }
}

This code fragment executes during either the insert (node create) or update (node edit) actions. It checks to see if either a photo or review node has been created. If so, then it form the full URL for the node that is in the node reference field. The Drupal caches uses the full URL to create the cache references, thus the ‘absolute’ => TRUE is needed.

The cache_clear_all() does all the work to delete the cache entry.

Now, when the RV park page is viewed after a new review is posted, the whole node cache is recreated. Problem solved.

The next step in making our site faster will be to add Boost. I am pretty sure this method will still work under Boost. About to find out.

Mashable Mobile Strategies and Drupal

Mashable recently published an HOW TO: Optimize for Mobile. They list a couple create tools that any good Drupal dev should be using if they have a mobile audiences.

But specifically, their fifth step is to use your CMS, with examples of WordPress and Drupal. Specifically they mention Mobile Tools proving they spent a least a little in researching this (or they have quick access to some Drupal talent). I have used Mobile Tools on a a few sites and it definitely a good way to go to present different displays of a website based on the mobile device. With include integration with WURFL for device detection, Mobile Tools is great.

Always glad to just stumble across references to Drupal in general technology based articles.

Views, ImageCache and an iPhone app

When developing a mobile app, be it for the iPhone, an Andriod phone or a Blackberry, having dynamic data sprinkled in the app is important. DogParkUSA.com has recently sponsored the Dog Park Finder iPhone app and they wanted a thumbnail photo in each dog park listing.

One key is that if a park gets its first photo, or a better photo, the editors wanted to be able to promote the photos to the top of the photo page, and to have it show up as the thumbnail in the iPhone app. To do this without updating the app, we used a static URL that points to a View, which displays a Imagecached image.

Imagecache was used to exactly size photos to fit in the frame used in the app, while Views allows us to have a static URL, even though the photo displayed can be changed by the editors (by using the Sticky flag). This flexibility is key to pushing the photos they select into the app without an app update.

Another Module that is key for making a mobile app is Path Redirect. This is needed because many times the URL of a page is need for a web view display. But if a page URL changes then it will break the mobile app, thus being able to use Path Redirect's ability to redirect from an old URL to a new one is great.

I can hear someone say that with the Global Redirect module you could just use 'node/44' type URLs, but we didn't like that solution because in the 'Tell a Friend' email, a URL is embedded that directs to a dog park details page, and we didn't want a 'node/44' type URL in the email.

The next few updates in the app will add in the ability to submit reviews, submit photos and read in live reviews into the app using the services module. I will write about those interesting tasks as they come.

Drupal 6 Search Engine Optimization Review

I recently had the pleasure of reading Drupal 6 Search Engine Optimization by Ben Finklea, published by Packt Publishing. As the lead developer of a small start-up that depends on organic search traffic (as well as Search Engine Marketing, SEM, campaigns) I already have a keen interest and generally thorough understanding of SEO practices in general, and SEO tricks specifically for Drupal. I approached this book wondering how much I may or may not actually learn. Gladly, it was worth the read.

Drupal 6 Search Engine Optimization is a book that any Drupal shop should have on the shelf for reference, and any budding (or experienced) Drupal dev should read to help them add value to any customer site they are building. Search engines many times send the lion's share of traffic to new sites, so building a site that search engines view favorably should always be a priority for any serious site construction project.

In a certain sense, this book is more than a Drupal book as it expounds on a few SEO topics and tools that are completely separate from Drupal. For a few site owners, this is golden as they will not have to plunk down another $20 (or euros, or pounds) for a general SEO book. In the first few chapters general marketing advise, how to set up a Google Analytics account, and even the value of viewing user activities though a click heat map are discussed. All are outside Drupal proper, but are topics that help round out the general knowledge base of the reader. The book assumes a very rudimentary level of Drupal understanding, and assumes no SEO knowledge.

Drupal's Proven Productivity Boost Explains it All

Browsing the last day's set of blog posts to Drupal Planet is proof positive that Drupal enhances productivity so much that we have extra time for leisure posting. Of course, my own contribution is equally devoid of 'professional' merit or helpful support (need to finish an SEO book review), but these all contribute to the 'Drupal Rocks!' motif of the Drupal community.

First, there is the Drupal Cube. Drive behind this Nissan Cube and the Drupalicon will be staring you right back in your windshield.

Next, there is the Great Drupalkin hunt of 2009. Check out pingVision's pumpkin/Drupalicon hybrid.

Lastly, there has been a rule change and some fun on IRC.

Seriously, if we have time to post this stuff, Drupal must rock! Hope to see more.

BTW, did you hear that the Whitehouse is using Drupal!!!

Syndicate content