Tag: kranthi

How To Use Custom Post Types To Organize Online Marketing Campaigns


  

Custom post types add a level of flexibility to WordPress that makes this open-source Web development platform more useful on many levels. Whenever I have been faced with a Web-based task, especially one that involves organizing information, the first thing I do is examine WordPress to determine if it can handle the job. It usually can.

Making Dollars
Image Source

As an Internet marketer and analyst, I need to be able to organize online marketing campaigns in a way that is trackable in Google Analytics. This is the perfect task for WordPress custom post types.

In this article, we’ll explain how to create a WordPress plugin that enables you to organize Internet marketing campaigns using trackable URLs, shortened versions of those URLs, and trackable QR codes that you can also use for offline marketing activities.

We’ll show you how to create this plugin in a way that maximizes ease of use and functionality. If you have other methods that you have found useful, please share them in the comments. Also, let’s remember that we are standing on the shoulders of WordPress developers who have laid the foundation for easier coding.

Here are the criteria for our custom post type plugin:

  • It must provide a form in which users can specify a landing page to be tracked, the anchor text or content, the term (if this link is a PPC ad), and any additional information about this link.
  • It must provide three custom taxonomy types, so that users can select the URL variables for source, medium and campaign name. This is a taxonomy type because they will be reusable across campaigns and posts.
  • It must be organizable in the admin area and be displayed in the user interface.
  • The output must include a Google Analytics campaign-trackable URL, the information about the URL in human-readable format, a shortened version of the URL using a URL shortener, and a QR code of the shortened URL.

The File Structure

This plugin will use three files. To set up the structure, create a plugin folder named campaign-tracker. Inside the campaign-tracker folder, create the following three PHP files:

  • campaign-tracker.php
  • ga-functions.php
  • campaign-template.php

After you have created the files, we are ready to start adding the code.

The Plugin File

The main plugin file will be campaign-tracker.php. The content of this file will begin the standard way, by providing WordPress with the information that it needs to recognize it is as plugin. We then dive into setting up the CampaignTracker10 class and functions. We will set up our campaign custom post type and register the taxonomies that we will need. We will also initiate our admin interface.

   <?php
   /*
   Plugin Name: Campaign Tracking 1.0
   Plugin URI: http://www.convergeconsulting.org
   Description: Google Analytics Campaign Tracking system for WordPress 3.0 and above.
   Author: Joshua Dodson
   Version: 1.0
   Author URI: http://www.convergeconsulting.org
   */

   // Include the ga-functions.php helper functions
   include_once('ga-functions.php');

   if(!class_exists('CampaignTracker10'))
   {

      class CampaignTracker10 {

         var $meta_fields = array("gaca10-gaurl","gaca10-gaterm","gaca10-gacontent","gaca10-gadescription");

         // This function will create the custom post type. Thanks to Konstantin Kovshenin's example for additional examples of how to construct custom post types (http://kovshenin.com/2010/03/custom-post-types-in-wordpress-3-0-2089/), which inspired much of this.
         function __construct(){
            // Register custom post types
            register_post_type('campaign', array(
            'label' => _x('Campaigns','campaigns label'), // We're labeling the custom posts as Campaigns and also accounting for gettext appropriately
            'singular_label' => _x('Campaign','campaign singular label'), // Each post will be called a Campaign
            'public' => true, // These will be public
            'show_ui' => true, // Show the UI in admin panel
            '_builtin' => false, // This is a custom post type, not a built in post type
            '_edit_link' => 'post.php?post=%d',
            'capability_type' => 'post',
            'hierarchical' => false,
            'rewrite' => array("slug" => "campaign"), // This is for the permalinks
            'query_var' => "campaign", // This goes to the WP_Query schema
            'supports' => array('title'/* We only need the default title field, but we could use others such as 'author', 'excerpt', 'editor' ,'custom-fields'*/)
            ));

            add_filter("manage_edit-campaign_columns", array(&$this, "edit_columns"));
            add_action("manage_posts_custom_column", array(&$this, "custom_columns"));

            // Register custom taxonomies gasource (for the Campaign Source), gamedium (for the Campaign Medium), and ganame (for Campaign Name)
            // Campaign Source
            register_taxonomy("gasource", array("campaign"), array("hierarchical" => true, "label" => _x( 'Campaign Sources', 'campaign sources taxonomy label' ), "singular_label" => "Campaign Source", "rewrite" => true));
            // Campaign Medium
            register_taxonomy("gamedium", array("campaign"), array("hierarchical" => true, "label" => _x( 'Campaign Mediums', 'campaign mediums taxonomy label' ), "singular_label" => "Campaign Medium", "rewrite" => true));
            // Campaign Name
            register_taxonomy("ganame", array("campaign"), array("hierarchical" => true, "label" => _x( 'Campaign Names', 'campaign names taxonomy label' ), "singular_label" => "Campaign Name", "rewrite" => true));

            add_action("admin_init", array(&$this, "admin_init"));
            add_action("template_redirect", array(&$this, 'template_redirect'));

            add_action("wp_insert_post", array(&$this, "wp_insert_post"), 10, 2);

         }

Let’s give the columns on the admin screen some headings:

   function edit_columns($columns)
   {
      $columns = array(
      'cb' => '<input type="checkbox" />',
      'title' => _x('Campaign Title','campaign title label for edit columns'),
      'gaca10_ganame' => _x('Campaign Name','campaign name label for edit columns'),
      'gaca10_gasources' => _x('Campaign Source','campaign source label for edit columns'),
      'gaca10_gasmedium' => _x('Campaign Medium','campaign medium label for edit columns'),
      );
      return $columns;
   }

Let’s specify which columns we would like to show up on the admin screen for this custom post type. We’ll have columns for campaign source, medium and name, in addition to the post’s title.

   function custom_columns($column)
   {
      global $post;
      switch ($column)
      {
         // The campaign source
         case "gaca10_gasources":
         $gasources = get_the_terms(0, "gasource");
         if ( $gasources && ! is_wp_error( $gasources ) ) :
         $gasources_html = array();
         foreach ($gasources as $gasource)
         array_push($gasources_html, '<a href="' . get_term_link($gasource->slug, "gasource") . '">' . $gasource->name . '</a>');

         echo implode($gasources_html, ", ");
         endif;
         break;

         // The campaign medium
         case "gaca10_gasmedium":
         $gamediums = get_the_terms(0, "gamedium");
         if ( $gamediums && ! is_wp_error( $gamediums ) ) :
         $gamediums_html = array();
         foreach ($gamediums as $gamedium)
         array_push($gamediums_html, '<a href="' . get_term_link($gamedium->slug, "gamedium") . '">' . $gamedium->name . '</a>');

         echo implode($gamediums_html, ", ");
         endif;
         break;

         // The campaign name
         case "gaca10_ganame":
         $ganames = get_the_terms(0, "ganame");
         if ( $ganames && ! is_wp_error( $ganames ) ) :
         $ganames_html = array();
         foreach ($ganames as $ganame)
         array_push($ganames_html, '<a href="' . get_term_link($ganame->slug, "ganame") . '">' . $ganame->name . '</a>');

         echo implode($ganames_html, ", ");
         endif;
         break;
      }
   }

Once our columns are set up appropriately, we should see the following columns (note that this example is with one campaign already added):

Campaigns in columns

The next section enables us to specify which template we would like to use to display this custom post type. We will be using the campaign-template.php template:

   function template_redirect()
   {
      global $wp;

      // If the post type is set and is campaign…
      if (isset($wp->query_vars["post_type"])) {
         if ($wp->query_vars["post_type"] == "campaign")
         {
            // Then use the campaign-template.php file from this plugin directory
            include WP_PLUGIN_DIR.'/campaign-tracker/campaign-template.php';
            die();
         }
      }
   }

If a post is inserted or updated, then loop through the array and update or add the post’s meta data.

   function wp_insert_post($post_id, $post = null)
   {
      if ($post->post_type == "campaign")
      {
         foreach ($this->meta_fields as $key)
         {
            $value = $_POST[$key];
            if (empty($value))
            {
               delete_post_meta($post_id, $key);
               continue;
            }

            if (!is_array($value))
            {
               if (!update_post_meta($post_id, $key, $value))
               {
                  add_post_meta($post_id, $key, $value);
               }
            }
            else
            {
               delete_post_meta($post_id, $key);

               foreach ($value as $entry){
                  add_post_meta($post_id, $key, $entry);
               }
            }
         }
      }
   }

With the following function, we can add custom meta boxes for the admin screen where we edit the campaign:

   function admin_init()
   {
      // Add custom meta boxes for the edit campaign screen
      add_meta_box("gaca10-meta", "Campaign Information", array(&$this, "meta_options"), "campaign", "normal", "core");
   }

The following function is for the admin post meta contents. This lets us create the form in which we specify some of the variables for our trackable URL (except for the taxonomies). It also provides a read-only field that shows the shortened URL after the URL variables have been saved.

   function meta_options()
   {
      global $post;
      $custom = get_post_custom($post->ID);
      if($custom["gaca10-gaurl"][0]){
         $gaurl = $custom["gaca10-gaurl"][0];
      }
      else{ $gaurl = ''; }
      if($custom["gaca10-gaterm"][0]) {
         $gaterm = $custom["gaca10-gaterm"][0];
      }
      else { $gaterm = ''; }
      if ($custom["gaca10-gacontent"][0]) {
         $gacontent = $custom["gaca10-gacontent"][0];
      }
      else { $gacontent = ''; }
      if ($custom["gaca10-gadescription"][0]) {
         $gadescription = $custom["gaca10-gadescription"][0];
      }
      else { $gadescription = ''; }

      $url = trackable_url();
      if ($custom["campaign_tinyurl"][0]) {
         if($gaurl == '') { $shortenedurl = ''; }
         else{ $shortenedurl = create_tiny_url($url); }
      }

      ?>
      <label><?php _ex('Website URL:','website url label'); ?></label><input name="gaca10-gaurl" value="<?php echo $gaurl; ?>" /><br />
      <em><?php _ex('(e.g., http://www.google.com)','website url example'); ?></em><br /><br />

      <label><?php _ex('Campaign Term:','campaign term label'); ?></label><input name="gaca10-gaterm" value="<?php echo $gaterm; ?>" /><br />
      <em><?php _ex('(identify the paid keywords)','campaign term information'); ?></em><br /><br />
      <label><?php _ex('Campaign Content:','campaign content label'); ?></label><input name="gaca10-gacontent" value="<?php echo $gacontent; ?>" /><br />
      <em><?php _ex('(use to differentiate ads)','campaign content information'); ?></em><br /><br />

      <label><?php _ex('Campaign Description:','campaign description label'); ?></label><input name="gaca10-gadescription" value="<?php echo $gadescription; ?>" /><br />
      <em><?php _ex('(use to remind yourself about this specific link)','campaign description information'); ?></em><br /><br />

      <label><?php _ex('Shortened URL:','shortened URL label'); ?></label><input name="gaca10-gashortened-url" value="<?php echo $shortenedurl; ?>" readonly="readonly" /><br />

      <?php
   }
}

}

Here is how the “Add/Edit Campaign� screen will appear:

Add new post

If CampaignTracker10 exists, then we initiate the plugin:

   if(class_exists('CampaignTracker10')){

      // Initiate the plugin
      add_action("init", "CampaignTracker10Init");

      function CampaignTracker10Init() {
         global $gaca10;
         $gaca10 = new CampaignTracker10();

      }
   }

Combine these functions into the campaign-tracker.php file.

The following taxonomy examples should also be on the “Add/Edit Campaign� screen after everything has been added. Here is the “Campaign Names� taxonomy:

Campaign Names

Here is the “Campaign Mediums� taxonomy:

Campaign Mediums

Here is the “Campaign Sources� taxonomy:

Campaign Sources

Similar to how traditional post categories are set up, you can create new categories or select previous categories.

A note on usage: When you begin to use the system, try to select only one category each from name, source and medium. One category per taxonomy type will prove to be most useful in your actual analysis in Google Analytics. So, as a general rule: one name, one source and one medium per URL.

The Helpful Display Functions

Each of the functions in this section is part of the ga-functions.php file. The functions have been separated from the other functions in order to keep the display functions together.

Our file will begin with the formatted_utm_taxonomy_terms function, which will display a URL-friendly version of the taxonomy terms:

   <?php
   /* Some Helpful Display Functions */

   function formatted_utm_taxonomy_terms($the_term) {
      global $post;
      $post_terms = get_the_terms( $post->ID, $the_term );
      if ( $post_terms && ! is_wp_error( $post_terms ) ) :
      $encoded_terms = array();
      foreach ($post_terms as $term ) {
         if(!$encoded_terms[] = $term->slug){
            $encoded_terms[] = urlencode($term->name);
         }
      }
      $return_terms = implode('+',$encoded_terms);
      return $return_terms;
      endif;
   }

The trackable_url function generates the trackable URL from the fields on the admin screen as well as the taxonomies. This appends the appropriate tracking criteria to the URL so that Google Analytics can use the variables and provide information based on these specific variables. To do this, we will use the add_query_arg WordPress function.

   function trackable_url() {
      global $post;
      $custom = get_post_custom($post->ID);

      // the url
      if ($custom["gaca10-gaurl"][0]) {
         $gaurl = $custom["gaca10-gaurl"][0];
      }
      else { $gaurl = ''; }

      // the term(s)
      if ($gaterm = $custom["gaca10-gaterm"][0]) {
         $gaterm = $custom["gaca10-gaterm"][0];
         $gaterm = urlencode($gaterm);
      }
      else { $gaterm = ''; }

      // the content(s)
      if ($custom["gaca10-gacontent"][0]) {
         $gacontent = $custom["gaca10-gacontent"][0];
         $gacontent = urlencode($gacontent);
      }
      else { $gacontent = ''; }
      $arr_params = array ( 'utm_campaign' => formatted_utm_taxonomy_terms('ganame'), 'utm_source' => formatted_utm_taxonomy_terms('gasource'), 'utm_medium' => formatted_utm_taxonomy_terms('gamedium'), 'utm_term' => $gaterm, 'utm_content' => $gacontent);
      return add_query_arg( $arr_params, $gaurl );

   }

The following functions take the campaign-trackable URL and shortens it with TinyURL. This method uses wp_remote_get to generate the shortened URL. It then saves the shortened URL to the post’s meta data when a post is saved. The trackable_url_tiny function enables us to retrieve the shortened URL in the template.

   // Save the shortened trackable URL to the post meta
   function save_shortened_meta($post_ID) {
      $url = trackable_url();
      $shortened_url = create_tiny_url($url);
      update_post_meta($post_ID, "campaign_tinyurl", $shortened_url);
      return $post_ID;
   }

   // Add an action to save it when the post is saved.
   add_action('save_post', 'save_shortened_meta');

   // Retrieve the shortened URL from post meta
   function trackable_url_tiny($url = null, $post_ID) {
      global $post;
      $custom_fields = get_post_custom($post->ID);
      $campaign_tinyurl = $custom_fields['campaign_tinyurl'][0];
      return $campaign_tinyurl;

      return $post_ID;
   }

   // Create shortened trackable URL through the wp_remote_get function
   function create_tiny_url($strURL) {
      $tinyurl = wp_remote_get( 'http://tinyurl.com/api-create.php?url='.$strURL );
      if( is_wp_error( $response ) ) {
         return 'Something went wrong!';
      } else {
         return $tinyurl['body'];

      }
   }

The trackable_url_report function is what provides the human-readable version of the variables. These are broken out by each section. The landing page, campaign name, source, medium, terms and content are all separated and displayed individually if they exist.

   function trackable_url_report() {
      global $post;
      $custom = get_post_custom($post->ID);

      // get the url
      if ($custom["gaca10-gaurl"][0]) {
         $gaurl = $custom["gaca10-gaurl"][0];
      }
      else { $gaurl = ''; }
      // get the term(s)
      if ($gaterm = $custom["gaca10-gaterm"][0]) {
         $gaterm = $custom["gaca10-gaterm"][0];
      }
      else { $gaterm = ''; }

      // get the content(s)
      if ($custom["gaca10-gacontent"][0]) {
         $gacontent = $custom["gaca10-gacontent"][0];
      }
      else { $gacontent = ''; }

      // The Landing page
      $url_info ='';
      $url_info.= "<strong>". _x( 'Landing Page:','landing page label') . "</strong> ";
      $url_info.= $gaurl;
      $url_info.= "<br />";

      // The campaign name
      $url_info.= "<strong>". _x( 'Campaign:','campaign label') . "</strong> ";
      $url_info.= formatted_utm_taxonomy_terms('ganame');
      $url_info.= "<br />";

      // The Source
      $url_info.= "<strong>". _x( 'Source:','source label') . "</strong> ";
      $url_info.= formatted_utm_taxonomy_terms('gasource');
      $url_info.= "<br />";

      // The medium
      $url_info.= "<strong>". _x( 'Medium:','medium label') . "</strong> ";
      $url_info.= formatted_utm_taxonomy_terms('gamedium');
      $url_info.= "<br />";

      // The term
      $url_info.= "<strong>". _x( 'Term:','term label') . "</strong> ";
      $url_info.= $gaterm;
      $url_info.= "<br />";

      // The content
      $url_info.= "<strong>". _x( 'Content:','content label') . "</strong> ";
      $url_info.= $gacontent;
      $url_info.= "<br />";

      return $url_info;
   }

The display_description function displays the description of the URL. We’ve broken this part out here in order to keep all of the pieces that are specific to the URL together. This is also the last function in the ga-functions.php file.

   function display_description(){
      global $post;
      $custom = get_post_custom($post->ID);
      $description = $custom["gaca10-gadescription"][0];
      return $description;
   }

   ?>

Combine these functions into the ga-functions.php file, and then we can move onto creating the template file.

The Template File

The final file that we will use to generate the view of the trackable URL is campaign-template.php. You will remember from the campaign-tracker.php file that we have a call in the template_redirect() function to redirect users to this template when viewing the custom post type of campaigns.

For display purposes, we will use the single.php file from the current default WordPress theme, TwentyEleven. You can, of course, use another theme and different styles.

First, we include the ga-functions.php file so that we can use some of our display functions. The campaign template also uses the Google Charts API to generate the QR code.

The following code will do all of the heavy lifting to display our campaign-trackable URL, the information about the URL, the shortened URL and the QR code. It will also allow us to edit the post if we need to change a variable. Simply drop this code into the loop.

   <h1 class="entry-title"><?php the_title() ?></h1><br />

   <?php
   echo "<strong>". _x( 'Description:','description label') . "</strong> ";
   echo display_description();
   echo "<br />";
   echo trackable_url_report();
   echo "<br />";
   echo "<strong>". _x('Trackable URL:','trackable URL label') . "</strong> ";
   echo "<a href=".trackable_url()." target='_blank'>".trackable_url()."</a><br />";

   echo "<strong>" . _x('Shortened Trackable URL:','shortened trackable URL label') . "</strong> ";
   echo "<a href=".trackable_url_tiny()." target='_blank'>".trackable_url_tiny()."</a><br />";
   ?>

   <br />
   <img src="https://chart.googleapis.com/chart?chs=150x150&amp;cht=qr&amp;chl=<?php trackable_url_tiny(); ?>" /><br />
   <?php edit_post_link( __( 'Edit', 'twentyeleven' ), '<span class="edit-link">', '</span>' ); ?>

When we combine the code, the campaign template will be as follows:

   <?php
   /**
   * The Template for displaying all single posts.
   *
   * @package WordPress
   * @subpackage Twenty_Eleven
   * @since Twenty Eleven 1.0
   */

   // Include the ga-functions.php file so that we can easily display the results
   include_once('ga-functions.php');

   get_header(); ?>

   <div id="primary">
   <div id="content" role="main">

   <?php while ( have_posts() ) : the_post(); ?>

   <nav id="nav-single">
   <h3 class="assistive-text"><?php _e( 'Post navigation', 'twentyeleven' ); ?></h3>
   <span class="nav-previous"><?php previous_post_link( '%link', __( '<span class="meta-nav">&larr;</span> Previous', 'twentyeleven' ) ); ?></span>
   <span class="nav-next"><?php next_post_link( '%link', __( 'Next <span class="meta-nav">&rarr;</span>', 'twentyeleven' ) ); ?></span>
   </nav><!-- #nav-single -->

   <h1 class="entry-title"><?php the_title() ?></h1><br />

   <?php
   echo "<strong>". _x( 'Description:','description label') . "</strong> ";
   echo display_description();
   echo "<br />";
   echo trackable_url_report();
   echo "<br />";
   echo "<strong>". _x('Trackable URL:','trackable URL label') . "</strong> ";
   echo "<a href=".trackable_url()." target='_blank'>".trackable_url()."</a><br />";

   echo "<strong>" . _x('Shortened Trackable URL:','shortened trackable URL label') . "</strong> ";
   echo "<a href=".trackable_url_tiny()." target='_blank'>".trackable_url_tiny()."</a><br />";
   ?>

   <br />
   <img src="https://chart.googleapis.com/chart?chs=150x150&amp;cht=qr&amp;chl=<?php trackable_url_tiny(); ?>" /><br />
   <?php edit_post_link( __( 'Edit', 'twentyeleven' ), '<span class="edit-link">', '</span>' ); ?>

   <?php comments_template( '', true ); ?>

   <?php endwhile; // end of the loop. ?>

   </div><!-- #content -->
   </div><!-- #primary -->

   <?php get_footer(); ?>

When the template is set up and a campaign has been added, then it should display the following page:

Display information

In Conclusion

By using WordPress custom post types in the method described, it is possible to organize marketing campaigns with the relevant Google Analytics campaign-tracking URL, shortened URL and QR code. This makes organizing marketing campaigns much simpler and more effective.

Custom post types make it very easy to set up a system by which to organize content. And we can get creative in how we use custom post types. They can be very useful when organizing content outside of the normal structure of WordPress and other content management systems (i.e. posts, pages, etc.).

Other possible uses of custom post types include the following:

  • Manage client contacts,
  • Create an employee directory,
  • Keep an inventory of items,
  • Organize other data.

Resources

You may be interested in the following resources and articles:

(al)


© Joshua Dodson for Smashing Magazine, 2012.


Using max-width on images can make them disappear in IE8

I recently ran into a problem that was really hard to figure out. I was working on a responsive design where I used img {max-width:100%;} to make sure that images would be downsized rather than overflow in narrower viewports.

It worked great everywhere… until I went to check in IE8. The site’s logo was gone! None of the usual IE bug fixes cured the problem, and it took me quite a while to realise that max-width was part of the problem.

Read full post

Posted in , .

Copyright © Roger Johansson



Freebie: St. Valentine’s Day Icon Set (10 PNG/PSD Icons)


  

Every now and then, we release useful freebies for all of our highly valued readers. Today, it is our pleasure to present to you Cuberto‘s fantastic St. Valentine’s icon set  —  exclusively designed for Smashing Magazine and its loyal readers. The icons presented are available in transparent PNGs as well as Photoshop PSDs (128×128 px) and are perfect for any projects you have coming up for St. Valentine’s Day. Enjoy!

short preview

Download the Set for free!

This icon set is completely free to use for commercial or personal applications without any restrictions. Please link to this article if you want to spread the word.


Initial sketches of Cuberto’s St. Valentine’s icon set.


Quick preview of the icons in the set.

Behind the Design

As always, here are some insights from the designers:

“Our goal was not only to create nice icons but also a functional set that can be used in navigation elements as well as gifts throughout social networks on the upcoming sweet Valentine’s day. Please link to this article if you want to spread the word.”
 —  Peace and Love

Thanks Cuberto, we sincerely appreciate your time and your intentions!

(il)


© Smashing Editorial Team for Smashing Magazine, 2012.


Ten Things To Think About When Designing Your iPad App


  

Like most well-designed things, the magic of an iPad app comes from a union of usefulness, usability and meaning. Games aside, the app must be useful by solving a problem that people actually have through the right set of functionality at the right time. It must be easy to use and, just as importantly, easy to get started using, without a lot of pesky setup and learning steps. And it must hold meaning for the user through visual beauty, an emotional connection, personal insights, etc. In this article, we won’t outline the entire design process for creating an iPad app, but we will explore 10 of the key things to think about when designing your app (and planning the design process).

We’ve excluded tips that have already been mentioned in every single iPad design article ever written (such as, “Invite users to touch by presenting real-world metaphors in a skeuomorphic interface� —look it up!). Instead, we’ll focus on what to really think about when doing design work. By reviewing these considerations in the context of your own application, you can assess whether you’re making good decisions about your design.

Take A Goal-Oriented Approach To Simplify Functionality.

Good iPad apps are about simplicity and doing a few things well. This means you have to be selective about the functionality you include and not throw in the kitchen sink. Consider following a goal-oriented approach to figure out what functionality you need. List all of the high-level goals a user might have when using your app (better yet, watch users doing things that you hope your app will help with in order to get a full picture of what the user’s goals are — but that’s an article for another time). What would someone be trying to get done? Then, brainstorm all of the functionality that someone might want in order to accomplish that task. Look at that big list, and start pruning, with an eye for the minimum that is needed to help the user succeed. And then select a few magical, delightful features to complete the package.

For example, Epicurious does an excellent job of giving the multi-tasking cook exactly what they need. When viewing a recipe in landscape format, users can easily scan ingredients on the left while keeping track of the next instruction on the right, with a bright placeholder that can be dragged with the finger to the current spot. Reviews and additional tips for the recipe are easily accessible via tabs, but the main screen is kept clean and uncluttered, with just the basics.


Epicurious provides a clean interface for recipes, with an orange marker to keep your place.

By contrast, the Whole Foods app starts off being helpful by letting you add recipe ingredients to a shopping list. Unfortunately, it neglects to combine repeated ingredients, so items are listed multiple times. In the screenshot below, bananas appear three times, once for each recipe that requires them, instead of being combined into one entry.


Whole Foods should enhance its app by merging duplicate list items.

Also, don’t provide a button for every control the user might need to accomplish their goal. Think about what the user can infer about the UI through gesture. For example, Apple’s Notes app doesn’t have an “editing� mode; instead, you simply touch the screen to bring up the keyboard, and it auto-saves when you’re done. Basic editing controls such as cut, copy and paste also appear only in response to gestures as needed (and undo is accomplished by shaking).

Apple Notes
The Notes app limits on-screen buttons and presents controls only if it detects they are needed.

Leverage What You Know To Create A Fully Personalized Experience.

No one wants to spend a lot of time setting up a $1.99 app. Leverage as much of what the iPad and other websites know about your users as possible (with their permission, of course). Could you use the user’s location, calendar, Twitter feed or contacts list to make the app smarter and more personalized?

Zite is a fabulous RSS reader for iPad that doesn’t wait for you to add sources, but rather connects to your Google Reader, Twitter or Delicious account and then presents articles based on what it has learned about your interests. I connected it with Delicious (where I store all of my bookmarks), and in five seconds it created a personalized magazine for me to explore new and interesting content! And just like Pandora, the more you use it, the more relevant and personalized the content becomes. So far, even though some argue that Flipboard’s UI is more elegant, engaging with Zite is easier because it’s all set up.


Zite sets things up immediately by connecting to an existing account.

Zite Top Stories
Zite created my own personal magazine by learning about my interests through my Delicious account.

Think About The Place Of Use.

Assume that your user will be out and about when using your app — in a restaurant, in the car, in the kitchen, on a sofa, etc. How does that change the list of goals you’ve put together? For a user browsing recipes, are their needs different on the sofa than in the kitchen, or in a restaurant?

Open Table’s Web app for reserving tables displays a list of restaurants as the default view for search results (i.e. without a map). On the iPad, the default view is a large map with a list of restaurants on the right, along with an option to search your vicinity. This accommodates the common use case of someone trying to find a place to eat when they are out and about.


When you’re out and about with the iPad, Open Table shows you what is near.

Awesome Note opens with a set of default categories that reflect the various places that people might take notes on an iPad.


Awesome Note complements traditional categories like “My idea� and “To-do list� with out-and-about categories like “Travel diary� and “Shopping.�

GroceryIQ is a shopping list that organizes items by aisle to speed up shopping. It also allows filtering by store, which is handy.

Grocery IQ
GroceryIQ offers functionality to make your shopping trip more efficient.

Consider Multi-User And Multi-Device Cases.

Assume that multiple members of a family will be sharing an iPad or viewing the device at once. Unlike a personal computer, the iPad is not necessarily a personal device but could be treated more like a coffee-table book or magazine that multiple residents share. In addition to allowing users to switch accounts, indicating who is currently logged in is also important. An added benefit of accounts is that they facilitate syncing between devices (for example, an iPad and a smartphone).

Flipboard is a great example of shared use through multiple accounts. When you sign in, your name is displayed on the home page.

Flipboard
Flipboard makes clear that it knows who you are.


Like Flipboard, FedEx displays the name of the logged-in user (although the app’s heavy grayscale appearance is odd).

eBay, on the other hand, supports accounts but provides no indication of who is signed in until you touch the “My eBay� button in the corner.


eBay doesn’t make clear who is logged in until you touch “My eBay� in the corner.

Don’t Do Crazy Navigation Unless It’s A Game Or One-Hit Wonder.

Crazy, spinny, eye-catching interactions are fine for one-hit wonders and games. But stick with standard navigation for frequently used apps, such as news readers. If you do want to do something innovative, make sure it supports the task at hand and is extremely usable.

Martha Stewart Living, which is built on the well-designed Adobe Digital Publishing Suite, uses horizontal and vertical scrolling in a novel way by reserving horizontal scrolling for navigating between articles and vertical scrolling for navigating pages of an article. This is paired with a clever pane that visually shows how scrolling works, plus an overview of the current issue for even quicker navigation. With all that and a clickable table of contents, the whole experience is quite lovely.


Martha Stewart Living’s overview pane shows the clever horizontal and vertical scrolling scheme for content created with the Adobe Digital Publishing Suite.

The best thing you could do is actually use an iPad constantly for all kinds of things, and see what works for you. You’ll quickly discover inconsistencies and annoyances all over the app world, and you’ll figure out where to be consistent and where to branch out.

Here are three different methods that news readers follow to enable users to exit articles:

Huffington Post exit
Huffington Post: top right.

NY Times exit
New York Times: bottom left.

Zite exit
Zite: top left.

People tend to rest their thumb near the top left when holding an iPad, so putting the button there is easiest because then people wouldn’t have to change their grip. Also, Zite enables you to click anywhere on the screen outside of the article to close it, which makes for a nice flexible gesture. Similarly, the New York Times enables you to pinch an article to close it and return to the home page, which is even better, especially because the controls disappear once an article has been open for a few seconds — although a one-finger gesture closer to the top left would have worked better, because the two-finger gesture would probably require the user to change their grip.

Be mindful of how you yourself use features, and notice when something is usable and when you have to move your hand awkwardly or do something that disrupts your flow. Look around to find apps that do what you’re trying to do, assess their usability, and decide whether being consistent or doing something different would make more sense. iPad apps are still a new frontier, so now is not the time to buckle down and set conventions — but we should assess whether a new idea really adds something useful or is just novel for the sake of novelty.

Provide A Home Page.

People are used to home pages that orient them to what’s available and that give them a base of operations. Without one, discovering and browsing content can be disorienting and frustrating. Take the NASA news app, which has no home page. Upon launching the app, users are dropped directly into a news article. To view other articles, they would use the carousel arrows on the left and right, or press the tiny list icon in the bottom-left corner of the screen. The list view allows users to browse content in a small scrolling pop-over window that has only enough room for thumbnails and short headlines. The navigation is generally unwieldy and disorienting.


NASA does not provide a home page, but rather drops you into an article with vague pop-over navigation.

Pulse, on the other hand, is a great news app that uses a home page to quickly orient users and to introduce the navigation scheme, which is consistent throughout the app. From the home page, users can easily browse content, having plenty of space to view the large thumbnails and article descriptions to see what interests them. Drilling down into an article will collapse the navigation to the side so that you don’t lose context.


Pulse presents a horizontal scrolling list of articles on the home page.


Opening an article will collapse the navigation to a side panel in landscape view.


In portrait view, Pulse displays the navigation for one content source at the bottom, with easy access to the next page.

Beware Of Awkward Pop-Overs.

iPad offers the nifty interaction of a pop-over to help users retrieve content and navigation in context. But the interaction can also make for a jerky flow, cramming a lot of information into a tiny peephole. Given the limited width and height of a pop-over, avoid stuffing too much in it. Awesome Note tries to cram the interaction for editing a list of folders into a small pop-over, presumably to maintain context. Instead, we get a confusing interaction, with tabs duplicated on the screen and not enough room to get things done.

Awesome Note pop-over
Awesome Note has a somewhat confusing pop-over that duplicates the information on the screen in a cramped space.

NASA’s complex navigation, which we saw in the preceding point, is a similar example of a bad pop-over.

Consider when opening a new page would make more sense than opening a pop-over. Unless context is critical, don’t be afraid to take users to a full-screen view to give the content some room to breathe.

Or consider using split views in clever ways:


Houzz has secondary navigation for each category in a convenient split view.


Martha Stewart Living displays the table of contents for an issue as a full-length pop-over, opening up space for images and descriptive headlines.


Flipboard favors a slide-out panel to give the navigation enough room to do its job.

Avoid Gratuitous Splash Screens.

Remember when the Web had splash screen, and then everyone got annoyed and left? They are even more annoying on the iPad because you’re usually trying to access content while someone is waiting for either you or the iPad. If you need a splash screen because something has to load, display it for the minimum amount of time possible. Better yet, display useful content while the rest of the app loads to give users a head start on the interaction.

Zite piques your interest by loading the first few photos on the home page while the rest of the app loads. When the app is ready, those initial photos animate into place, making for a delightful little welcome interaction.


Zite draws you in on the splash screen, with thumbnails of articles that will be ready once the full app loads.

Use Gestures In Clever Ways, But Don’t Overdo It.

Cool, useful gestures are a mainstay of iPad use. But the line between effective gestures and gesture overload is fine. For example, don’t provide a swipeable carousel and then also allow a generic swipe gesture on the same screen, because this would put competing swipe gestures at odds with each other.

And if a gesture is not obvious, give users a hint.


Zite indicates more content with a cute little “swipe� text at the bottom.

Discovr, a music-discovery application, integrates information about gesture controls right into the UI. The red circle in the screenshot below says “Tap me,� leading to information on how to expand nodes.


Discovr educates users with a red dot explaining the gesture options for the current screen.


Once basic information has been provided, another red node appears saying “Tap and hold me,� informing users how to access more content with a new gesture. With this information baked into the app experience itself, users learn about powerful features of the UI without having to be psychic.

Make Clear What’s Touchable, And Make It BIG.

Many apps suffer from what Jakob Nielsen calls “read-tap asymmetry,� whereby the font may be legible in size, but the tappable areas are so small that users are prone to missing the targets or are unsure whether the areas are even tappable. In the advertisement below, from the Martha Stewart Living app, the arrowed questions in the middle of the screen are tappable, but you wouldn’t know it because they have no affordance. If you’re going to go through the trouble of making more content available, then make it clear where to tap, and make the tappable area nice and big.


It’s not obvious where you would tap in this ad to get more information.


It turns out that tapping the light-gray boxes in the middle shows more information.

The image areas at the top of the Cool Hunting application are actually swipeable galleries, but we get no hint of it. What if there was some kind of affordance, such as dimensionality or a peek at another image to indicate there was more to the right?


Cool Hunting does not indicate that swiping the top image would reveal more images, which makes this functionality hard to discover.

In iOS itself, double-tapping the home key and then swiping left in the multitasking bar reveals a bunch of controls for sound and music, yet this functionality is pretty well hidden. Why not provide some affordance of what is available?


Double-tapping home and then swiping left on an iPad reveals hidden functionality.

What Else?

These are just 10 of the many things to consider when designing your iPad app, but it’s a good place to start. We’d love to hear your top considerations and examples in the comments. We especially lack a strong repository on the Web of examples of good and bad iPad app design. Please share examples of the different ways that apps treat the same functionality (such as exiting articles), and explain why certain solutions are better than others. Have you discovered other techniques through your own design work that you think everyone should put on their list of do’s and don’ts? Let us know.

Further Reading

(Cover image: Johan Larsson)

(al)


© Julie Stanford for Smashing Magazine, 2012.


Desktop Wallpaper Calendar: February 2012


  

We always try our best to challenge your artistic abilities and produce some interesting, beautiful and creative artwork. And as designers we usually turn to different sources of inspiration. As a matter of fact, we’ve discovered the best one — desktop wallpapers that are a little more distinctive than the usual crowd. This creativity mission has been going on for over two years now, and we are very thankful to all designers who have contributed and are still diligently contributing each month.

We continue to nourish you with a monthly spoon of inspiration. This post features free desktop wallpapers created by artists across the globe for January 2012. Both versions with a calendar and without a calendar can be downloaded for free. It’s time to freshen up your wallpaper!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • You can feature your work in our magazine by taking part in our Desktop Wallpaper Calendar series. We are regularly looking for creative designers and artists to be featured on Smashing Magazine. Are you one of them?

Colored Edge

"For February, the month of spring, love and 29 days." Designed by Rahul.s from India.

Smashing Wallpaper - february 12

Hungry Owl

"February, just one more cold month.. :)." Designed by Katerina Bobkova from Ukraine.

Smashing Wallpaper - february 12

Hot Drinks

"Which drink will you choose to make you feel better during the cold season?" Designed by Agathe Altwegg from France.

Smashing Wallpaper - february 12

Bold

Designed by Elisabetta Borseti from Italy.

Smashing Wallpaper - february 12

February Prison Break

"We suggest – do not mess with February." Designed by Marek GuziÑ�ski From Rio Creativo from Poland.

Smashing Wallpaper - february 12

All You Need Is Love

"Love is all you need." Designed by Kaspars Dedzis from Latvia.

Smashing Wallpaper - february 12

February Splashes

Designed by Roland Szabу from Hungary.

Smashing Wallpaper - february 12

Penguin Hockey

"No coward plays hockey!" Designed by Cheloveche.ru from Russia.

Smashing Wallpaper - february 12

Mr. & Ms. Nice

Designed by Diana Morgado from Portugal.

Smashing Wallpaper - february 12

Jealous Much?

"Calendar for February 2012." Designed by Annabelle Bay from USA.

Smashing Wallpaper - february 12

Heartbroken

"Illustrated wallpaper for february on the theme of heartbreak.1920 x 1200." Designed by Danae Botha from South Africa.

Smashing Wallpaper - february 12

The Shortest Month

Designed by Forsaken from France.

Smashing Wallpaper - february 12

Kids And Dragon

"My drawings are mostly black-and-white and the year of the Black Dragon inspired me to start drawing another picture. Let the Dragon this year be friendly and playful ;)." Designed by Jelena Tљekulajeva from Estonia.

Smashing Wallpaper - february 12

Heart On A String

"For hopeless romantics that let others play with their heart." Designed by Jacob Giesler from USA.

Smashing Wallpaper - february 12

A Shadow’s Chance

"A nod at Groundhog Day! The artwork provided with a calendar has a winter color, because the groundhog sees his shadow which means six more weeks of winter. And the other (Green) has no calendar and no shadow which denotes anearly spring." Designed by Joseph Brooks from United States.

Smashing Wallpaper - february 12

Be Mine

"A cutsie calendar theme." Designed by Sandi | Pop Up Factory.com from Toronto, ON, Canada.

Smashing Wallpaper - february 12

It’s The Love Signal

"Let’s beam our love to the universe!" Designed by Lew Su-ann from Brunei Darussalam.

Smashing Wallpaper - february 12

Winter Church

Designed by Pietje Precies from The Netherlands.

Smashing Wallpaper - february 12

Lock Your Love

"February is the month of couples and love, so if you do have that one special person in your life! Then this would be the prefect month to show how much you love her or him :)." Designed by Rihards Gromuls from Latvia.

Smashing Wallpaper - february 12

Cyclops Encounter

"I am a big fan of the Odyssey. Cyclopses are awesome." Designed by Glorm from Canada.

Smashing Wallpaper - february 12

Gloomy Light

"Sometimes we ever feel’s like useless, moody, gloomy, that’s so sadly. Maybe it just like an old gloomy paper effect on my calendar template. But, we can change it with give it colors, this year our life will be not far from heaviness like our years before, just bright it up and make a colors in your moody days!" Designed by Dwi Prastika from Indonesia.

Smashing Wallpaper - february 12

Chillout

"Once upon a time, in a land far, far away, where you will not be online…" Designed by Chilid Interactive Agency from Poland.

Smashing Wallpaper - february 12

All You Need Is Love

"The Beatles said it best! Love is all you need." Designed by Allison Brown from Canada.

Smashing Wallpaper - february 12

Fight For You

"This valentine we should fight for the ones we love." Designed by Tonie Tannous from Lebanon.

Smashing Wallpaper - february 12

Ice Melted

"Ice melted is coming back soon." Designed by Yank from France.

Smashing Wallpaper - february 12

Load Time

"What Scott Adams means about load time." Designed by Fredrik Jensen from Norway.

Smashing Wallpaper - february 12

Love Is In The Air

Designed by Andreas Sofantzis from Greece.

Smashing Wallpaper - february 12

Join In Next Month!

Please note that we respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience throughout their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us, but rather designed from scratch by the artists themselves.

A big thank you to all designers for their participation. Join in next month!

What’s Your Favourite?

What’s your favorite theme or wallpaper for this month? Please let us know in the comment section below! We are looking forward to your submissions next month!

(il) (vf)


© Smashing Editorial Team for Smashing Magazine, 2012.


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress