Jan 20 2019
Jan 20

For this month’s South Carolina Drupal User Group I gave a talk about creating Batch Services in Drupal 8. As a quick side note we are trying to include video conference access to all our meetings so please feel free to join us even if you cannot come in person.

[embedded content]

Since Drupal 8 was first released I have been frustrated by the fact that Drupal 8 batch jobs were basically untouched from previous versions. There is nothing strictly wrong with that approach, but it has never felt right to me particularly when doing things in a batch job that I might also want to do in another context – that really should be a service and I should write those core jobs first. After several frustrating experiences trying to find a solution I like, I finally created a module that provides an abstract class that can be used to create a service that handles this problem just more elegantly. The project also includes an example module to provide a sample service.

Some of the text in the slides got cut off by the Zoom video window, so I uploaded them to SlideShare as well:

Quick Batch Overview

If you are new to Drupal batches there are lots of articles around that go into details of traditional implementations, so this will be a super quick overview.

To define a batch you generate an array in a particular format – typically as part of a form submit process – and pass that array to batch_set(). The array defines some basic messages, a list of operations, a function to call when the batch is finished, and optionally a few other details. The minimal array would be something like:

  <?php  // Setup final batch array.
    $batch = [
      'title'    => 'Page title',
      'init_message' => 'Openning message',
      'operations'  => [],
      'finished' => '\some\class\namespace\and\name::finishedBatch',

The interesting part should be in that operations array, which is a list of tasks to be run, but getting all your functions setup and the batch array generated can often be its own project.

Each operation is a function that implements callback_batch_operation(), and the data to feed that function. The callbacks are just functions that have a final parameter that is an array reference typically called $context. The function can either perform all the needed work on the provided parameters, or perform part of that work and update the $context['sandbox']['finished'] value to be a number between 0 and 1. Once finished reaches 1 (or isn’t set at the end of the function) batch declares that task complete and moves on to the next one in the queue. Once all tasks are complete it calls the function provided as the finished value of the array that defined the batch.

The finish function implements callback_batch_finish() which means it accepts three parameters: $success, $results, and $operations: $success is true when all tasks completed without error; $results is an array of data you can feed into the $context array during processing; $operations is your operations list again.

Those functions are all expected to be static methods on classes or, more commonly, a function defined in a procedural code block imported from a separate file (which can be provided in the batch array).

My replacement batch service

It’s those blocks of procedural code and classes of nothing but static methods that bug me so much. Admittedly the batch system is convenient and works well enough to handle major tasks for lots of modules. But in Drupal 8 we have a whole suite of services and plugins that are designed to be run in specific contexts that batch does not provide by default. While we can access the Drupal service container and get the objects we need the batch code always feels clunky and out of place within a well structured module or project. What’s more I have often created batches that benefit from having the key tasks be functions of a service not just specific to the batch process.

So after several attempts to force batches and services to play nice together I finally created this module to force a marriage. Even though there are places which required a bit of compromise, but I think I have most of that contained in the abstract class so I don’t have to worry about it on a regular basis. That makes my final code with complex logic and processing far cleaner and easier to maintain.

The Batch Service Interface module provides an interface an an abstract class that implements parts of it: abstract class AbstractBatchService implements BatchServiceInterface. The developer extending that class only needs to define a service that handles generating a list of operations that call local methods of the service and the finish batch function (also as a local method). Nearly everything else is handled by the parent class.

The implementation I provided in the example submodule ends up four simple methods. Even in more complex jobs all the real work could be contained in a method that is isolated from the oddities of batch processing.


namespace Drupal\batch_example;
use Drupal\node\Entity\Node;
use Drupal\batch_service_interface\AbstractBatchService;

 * Class ExampleBatchService logs the name of nodes with id provided on form.
class ExampleBatchService extends AbstractBatchService {

   * Must be set in child classes to be the service name so the service can
   * bootstrap itself.
   * @var string
  protected static $serviceName = 'batch_example.example_batch';

   * Data from the form as needed.
  public function generateBatchJob($data) {
    $ops = [];
    for ($i = 0; $i < $data['message_count']; $i++ ) {
      $ops[] = [
        'logMessage' => ['MessageIndex' => $i + 1],

    return $this->prepBatchArray($this->t('Logging Messages'), $this->t('Starting Batch Processing'), $ops);

  public function logMessage($data, &amp;$context) {


    if (!isset($context['results']['message_count'])) {
      $context['results']['message_count'] = 0;


  public function doFinishBatch($success, $results, $operations) {
    drupal_set_message($this->t('Logged %count quotes', ['%count' => $results['message_count']]));

  public function getRandomMessage() {
    $messages = [
      // list of messages to select from

    return $messages[array_rand($messages)];



There is the oddity that you have to tell the service its own name so it can bootstrap itself. If there is a way around that I’d love to know it. But really one have one line of code that’s a bit strange, everything else is now fairly clear call and response.

One of the nice upsides to this solution is you could write tests for the service that look and feel just like any other services tests. The methods could all be called once, and you are not trying to run tests against a procedural code block or a class that is nothing but static methods.

I would love to hear ideas about ways I could make this solution stronger. So please drop me a comment or send me a patch.

Related core efforts

There is an effort to try to do similar things in core, but they look like they have some distance left to travel. Obviously once that work is complete it is likely to be better than what I have created, but in the meantime my service allows for a new level of abstraction without waiting for core’s updates to be complete.

Feb 01 2018
Feb 01
February 1st, 2018

Paragraphs is a powerful Drupal module that makes gives editors more flexibility in how they design and layout the content of their pages. However, they are special in that they make no sense without a host entity. If we talk about Paragraphs, it goes without saying that they are to be attached to other entities.
In Drupal 8, individual migrations are built around an entity type. That means we implement a single migration for each entity type. Sometimes we draw relationships between the element being imported and an already imported one of a different type, but we never handle the migration of both simultaneously.
Migrating Paragraphs needs to be done in at least two steps: 1) migrating entities of type Paragraph, and 2) migrating entities referencing imported Paragraph entities.

Migration of Paragraph entities

You can migrate Paragraph entities in a way very similar to the way of migrating every other entity type into Drupal 8. However, a very important caveat is making sure to use the right destination plugin, provided by the Entity Reference Revisions module:

destination: plugin: ‘entity_reference_revisions:paragraph’ default_bundle: paragraph_type destination:plugin:entity_reference_revisions:paragraphdefault_bundle:paragraph_type

This is critical because you can be tempted to use something more common like entity:paragraph which would make sense given that Paragraphs are entities. However, you didn’t configure your Paragraph reference field as a conventional Entity Reference one, but as an Entity reference revisions field, so you need to use an appropriate plugin.

An example of the core of a migration of Paragraph entities:

source: plugin: url data_fetcher_plugin: http data_parser_plugin: json urls: 'feed.url/endpoint' ids: id: type: integer item_selector: '/elements' fields: - name: id label: Id selector: /element_id - name: content label: Content selector: /element_content process: field_paragraph_type_content/value: content destination: plugin: 'entity_reference_revisions:paragraph' default_bundle: paragraph_type migration_dependencies: { } plugin:urldata_fetcher_plugin:httpdata_parser_plugin:jsonurls:'feed.url/endpoint'    type:integeritem_selector:'/elements'    name:id    label:Id    selector:/element_id    name:content    label:Content    selector:/element_contentfield_paragraph_type_content/value:contentdestination:plugin:'entity_reference_revisions:paragraph'default_bundle:paragraph_typemigration_dependencies:{  }

To give some context, this assumes the feed being consumed has a root level with an elements array filled with content arrays with properties like element_id and element_content, and we want to convert those content arrays into Paragraphs of type paragraph_type in Drupal, with the field_paragraph_type_content field storing the text that came from the element_content property.

Migration of the host entity type

Having imported the Paragraph entities already, we then need to import the host entities, attaching the appropriate Paragraphs to each one’s field_paragraph_type_content field. Typically this is accomplished by using the migration_lookup process plugin (formerly migration).

Every time an entity is imported, a row is created in the mapping table for that migration, with both the ID the entity has in the external source and the internal one it got after being imported. This way the migration keeps a correlation between both states of the data, for updating and other purposes.

The migration_lookup plugin takes an ID from an external source and tries to find an internal entity whose ID is linked to the external one in the mapping table, returning its ID in that case. After that, the entity reference field will be populated with that ID, effectively establishing a link between the entities in the Drupal side.

In the example below, the migration_lookup returns entity IDs and creates references to other Drupal entities through the field_event_schools field:

field_event_schools: plugin: iterator source: event_school process: target_id: plugin: migration_lookup migration: schools source: school_id field_event_schools:  plugin:iterator  source:event_school  process:    target_id:      plugin:migration_lookup      migration:schools      source:school_id

However, while references to nodes or terms basically consist of the ID of the referenced entity, when using the entity_reference_revisions destination plugin (as we did to import the Paragraph entities), two IDs are stored per entity. One is the entity ID and the other is the entity revision ID. That means the return of the migration_lookup processor is not an integer, but an array of them.

process: field_paragraph_type_content: plugin: iterator source: elements process: temporary_ids: plugin: migration_lookup migration: paragraphs_migration source: element_id target_id: plugin: extract source: '@temporary_ids' index: - 0 target_revision_id: plugin: extract source: '@temporary_ids' index: - 1 field_paragraph_type_content:  plugin:iterator  source:elements  process:    temporary_ids:      plugin:migration_lookup      migration:paragraphs_migration      source:element_id    target_id:      plugin:extract      source:'@temporary_ids'      index:        -0    target_revision_id:      plugin:extract      source:'@temporary_ids'      index:        -1

What we do then is, instead of just returning an array (it wouldn’t work obviously), use the extract process plugin with it to get the integer IDs needed to create an effective reference.


In summary, it’s important to remember that migrating Paragraphs is a two-step process at minimum. First, you must migrate entities of type Paragraph. Then you must migrate entities referencing those imported Paragraph entities.

More on Drupal 8

Top 5 Reasons to Migrate Your Site to Drupal 8

Creating your Emulsify 2.0 Starter Kit with Drush

Web Chef Joel Travieso
Joel Travieso

Joel focuses on the backend and architecture of web projects seeking to constantly improve by considering the latest developments of the art.

Web Chef Dev Experts

Blog posts about backend engineering, frontend code work, programming tricks and tips, systems architecture, apps, APIs, microservices, and the technical side of Four Kitchens.

Read more Development
Nov 19 2015
Nov 19

Need an array of user roles in your Drupal 8 site? Say goodbye to user_roles(), say hello to user_role_names().

This function will return an associative array with the role id as the key and the role name as the value.

 * Retrieves the names of roles matching specified conditions.
 * @link https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_role_names/8
function user_role_names($membersonly = FALSE, $permission = NULL) {
  return array_map(function($item) {
    return $item->label();
  }, user_roles($membersonly, $permission));

For more information, see https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_role_names/8.2.x.

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Nov 18 2015
Nov 18

Looking for how to create new module permissions in Drupal 8? Look no further, $module.permissions.yml to the rescue!

In Drupal 8 permissions are now defined in $module.permissions.yml file instead of using hook_permission().

Drupal 8 Static Permissions

Create a new file in the root of your module folder and name it my_module.permissions.yml.

# In my_module.permissions.yml file.
access all views:
  title: 'My module settings'
  description: 'A custom permission for your module settings page.'
  restrict access: TRUE

Drupal 8 Dynamic Permissions

In Drupal 8, you can support dynamic permissions by referencing a function that will dynamically define those permissions. This callback defines the permissions for core’s filter module.

# In filter.permissions.yml
  - Drupal\filter\FilterPermissions::permissions
// in FilterPermissions.php

class FilterPermissions {
  public function permissions() {
    $permissions = [];
    // Generate permissions for each text format. Warn the administrator that any
    // of them are potentially unsafe.
    /** @var \Drupal\filter\FilterFormatInterface[] $formats */
    $formats = $this->entityManager->getStorage('filter_format')->loadByProperties(['status' => TRUE]);
    uasort($formats, 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
    foreach ($formats as $format) {
      if ($permission = $format->getPermissionName()) {
        $permissions[$permission] = [
          'title' => $this->t('Use the <a href="https://benmarshall.me/drupal-8-module-permissions//@url">@label</a> text format', ['@url' => $format->url(), '@label' => $format->label()]),
          'description' => String::placeholder($this->t('Warning: This permission may have security implications depending on how the text format is configured.')),
    return $permissions;

For more information, see https://www.drupal.org/node/2311427.

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

May 20 2015
May 20

Boost the performance of your Drupal 7 website, improve usability and help with SEO by making content load via AJAX in just a few steps.

Drupal AJAX is a cinch to implement—as it should be since core is loaded with it. In just a few of steps I’ll show you how to use jQuery and Drupal’s hook_menu() function to quickly build a AJAX function to return anything from HTML to a JSON array.

Simple Drupal AJAX JSON Implementation

 * Implementation of hook_menu().
 * @see https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_menu/7
function moduleName_menu() {

  // Setup a URL to retrieve the JSON array.
  $items['node/%/moduleName/pageviews'] = array(
    'page callback'     =&gt; 'moduleName_get_pageviews',
    'page arguments'    =&gt; array(3),
    'type'              =&gt; MENU_CALLBACK,
    'access arguments'  =&gt; array('access content'),
    'delivery callback' =&gt; 'moduleName_ajax'

  return $items;

 * Returns the number of pageviews for a node ID.
function moduleName_get_pageviews($nid) {

  // Some fancy function that returns pageviews.
  return fancyPageviews($nid);

 * Renders a JSON array.
function moduleName_ajax($pageviews) {

  // Tell the browser to expect JSON data.
  // @see https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_add_http_header/7
  drupal_add_http_header('Content-Type', 'application/json');

  // Output the JSON result
  // @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_json_output/7
  print drupal_json_output(array('pageviews', $pageviews));

  // Perform end-of-request tasks.
  // @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_page_footer/7

With the above code (after clearing cache), visit yoursite.com/node/55/moduleName/pageviews to return a JSON array with the number of pageviews for node ID 55. More information on the hooks and functions used can be found below:

You can then use this URL and jQuery.getJSON() to return the data via AJAX.

;( function( $ ) {
  &quot;use strict&quot;;

  // When document is ready...
  $( function() {

    // Get the JSON result.
    $.getJSON( &quot;node/55/moduleName/pageviews&quot;, function( data ) {

      // Add the number of pageviews to the page.
      $( &quot;#pageviews&quot; ).text( data.pageviews );

})( jQuery );

Or if you need to pass data to the AJAX script:

;( function( $ ) {
  &quot;use strict&quot;;

  // When ready...
  // @see http://www.benmarshall.me/drupal-behaviors/
  Drupal.behaviors.myModule = {

    // Arguments to pass to the AJAX script.
    vars arguments = { status: 'awesome' };

    // Send the arguments &amp; return the JSON data.
    $.getJSON( &quot;node/55/moduleName/pageviews&quot;, arguments ).done( function( data ) {

      // Add the number of pageviews to the page.
      $( &quot;#pageviews&quot; ).text( data.pageviews );

})( jQuery );

For more information on $.getJSON(), see http://api.jquery.com/jquery.getjson/.

You’ll also notice it’s using something called Drupal.behaviors. This is essentially a document ready for all content, including new content that get’s added to the page after load. For instance, if a modal is added to the page via AJAX and a function that’s already been initialized needs to run on the modal, normally you’d have to force event delegation. For a quick introduction to Drupal behaviors, see http://www.benmarshall.me/drupal-behaviors/.

A Closer Look

Like with everything in Drupal, there’s a number of ways to implement AJAX, but which is best? Let’s dive a little deeper into Drupal AJAX and take a look at how, why and when you can use this powerful feature.

AJAX outside the Form API is new in Drupal 7. It allows back and front-end developers the ability to leverage high performance and solid JSON and HTML responses. You can use this feature to update blocks, nodes, pages and any other element with better performance on the client and server-side vs. loading AHAH page fragments.

Drupal AJAX with jQuery

jQuery provides a few different AJAX commands, depending on your exact requirements. Here is the simplest Ajax call you can make with jQuery:

$( &quot;#someDiv&quot; ).load( url );

What this is saying is “Find the div with the id of ‘someDiv’ and load the html that you find at the location ‘url’ into this div”.

The jQuery utility functions below provide for the extra flexibility you need when dealing with data coming back from the server that needs to be parsed.

// https://api.jquery.com/jquery.get/
$.get( url, parameters, callback );

// http://api.jquery.com/jquery.post/
$.post( url, parameters, callback );

// http://api.jquery.com/jquery.ajax/
$.ajax( options, settings );

// http://api.jquery.com/jquery.getjson/
$.getJSON( url, data, success );

// http://api.jquery.com/load/
$.load( url, data, complete )

The only difference between $.get and $.post is the HTTP request method used to send your parameters (an array passed as the second argument) to the server. Very often in Drupal, you won’t need to send any parameters because the url you will be calling will be a menu callback you have set up as, for example, ‘ajax/get/node_details’ taking one argument, ‘nid’ and so you would simply make the call to ‘ajax/get/node_details/123’ and not need to send your nid parameter as a parameter in the second argument.

Additional Resources:

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Sep 24 2014
Sep 24
This article was originally published by Drupal Watchdog in the winter 2014 edition by Fabian Franz.

The Salesforce Suite of Drupal modules is an easy way to connect Drupal to Salesforce, a Customer Relationship Management system used by retailers and non-profits alike, which allows non-technical staff to create extensive reports — reports that would be difficult to create using Drupal alone.

Although entities can be synchronized to Salesforce objects — and custom mappings created — there is lots more that can be done with Salesforce. Let’s take a look.

Getting Started

For openers, you’ll need:

To get the Developer Edition, create a developer account at https://developer.salesforce.com/signup.

Once you’re in Salesforce, you’ll quickly notice that the site seems overwhelming. A complete overview is way beyond the scope of this article; the most important objects for our purposes are Campaigns, Leads, Contacts, and Cases.

There are many other extensions for Salesforce, extensions that provide new object types. Also, existing object types can be extended in much the same way as in Drupal.

As a best practice, always work in a sandbox environment when not working with a dev instance. It will help ensure that you can create a proper development -> testing -> production workflow.

To create a sandbox (Enterprise, Performance, Unlimited, and Database.com), go to Setup » Sandboxes » Create new Sandbox.

As the final step in this first part of the process, create an application to connect Drupal to Salesforce by going to Setup » Create » Apps and clicking on New application under Connected App. Enter the basic information (e.g. “Drupal Integration”) and activate oAuth. Enter a callback URL to your local instance. If your local development Drupal site resides at http://localhost/salesforce-test/, then your callback URL is http://localhost/salesforce-test/salesforce/oauth_callback. Select api and offline_access as scopes.

Be sure to keep your consumer key and consumer secret handy, and you’re ready to move on.

Next Steps

Download the ‘salesforce-7.x-3.x’ module and enable the salesforce_mapping and salesforce_push modules. In your Drupal site, go to Configuration » Salesforce » Authorize and enter your consumer key and secret.

If you are using a sandbox, you need to enter, under the advanced settings, https://test.salesforce.com/ as the Salesforce endpoint. After logging in, you will be prompted for the permissions specified earlier; after clicking ‘Allow’, you’ll be back at Drupal with the message “Salesforce OAUTH2 authorization successful.” At the bottom of the screen will be a list of resources.

Before mapping the user object, create field_first_name and field_last_name fields within Drupal for the user entity at Configuration » People » Account Settings » Manage Fields.

You’re now able to map the User account to a contact by going to Structure » Salesforce » Salesforce Mappings and adding a Salesforce module called “User Mapping”.

Fill out the fields as seen in the image below, and check the three action triggers (entity create / update / delete). Save, and edit your own user account at People » Edit. Add the first name and last name, and you’ll see that the user account has been synchronized with a Salesforce record (see below).

A Ticket System for Authorized Users

A typical use case is to collect data in Drupal, and then process the data in Salesforce. But for this article, we will create a quick ticket system for authorized uses that will create cases within Salesforce, using the Entityform module, which allows creating forms that can be used for collecting data — similar to Webform, but using Drupal fields.

Download and enable the Entityform module and go to Structure » Entityform Types » Add Entityform Type. Enter Ticket as the name, and select authenticated user as the role. Save the form type and add a message-long text field to it.

Next, map the entityform submission entity with the ticket bundle to a Salesforce case object like the user account. Map the field_message field to the Case description; map the user who creates the case; select Related Entities » User; and map that to Contact ID (see below).

Save the mapping and go to the submit/ticket URL (available from the Structure » Entityform Types screen), enter a message, submit it, and — voila! — your ticket has been created as a case within Salesforce.

Tip: If you copy the Salesforce ID from the message, you can go directly to https://emea.salesforce.com/ID to see the newly created record. (The emea prefix is for the developer edition.)


While Entityform is quite pwerful, form variations are not easily workable because only one bundle can be mapped to one object type. But with the help of the Webform and Salesforce Webform Map modules, in combination with Entityform, it is possible to create a Salesforce mapping per object-type once, and potentially re-use it across hundreds of different web forms. In this scenario, one webform is represented by a campaign in Salesforce, and recursive object creation is enabled using different Salesforce mappings.


Salesforce and Drupal are a powerful combination. The Salesforce module allows you to map complex Drupal structures to Salesforce, and by using Entityform, simple data entry forms can easily be created.

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

May 07 2014
May 07

A feature I regularly use in WordPress development are shortcodes. I needed the same functionality in Drupal. Like most things I’ve found with Drupal, it’s not as easy or clear on how to go about it. No need to fret though, I’ll walk you through how to get ahead of the learning curve and easily create custom tokens.

Drupal’s documentation — or lack of — and a lot of posts I found on how to create tokens had conflicting information. This was mainly due to portions of the Token module getting moved into the core beginning with D7. Though, it doesn’t due much good for typical users if there’s no interface or UI for defining custom tokens.

In the examples below, I’ll show you how to easily create custom tokens within a module.

Creating Custom Tokens in Drupal 7

To create custom tokens in D7, we’re going to use two hooks:

  • hook_token_info() – This is where you’ll create the token and define what they are.
  • hook_tokens() – This is where the magic happens, you’ll tell Drupal what to replace your tokens with.

Below, we’re going to create a custom token that holds the user’s session status (Logged In, Logged Out). You could use this token in conjunction with GA’s custom dimensions to gather more detailed analytics.

Step 1: Create & define the custom token.

In your module, add the following code:

The code above will return an associative array with your custom tokens data:

  • Name: The translated human-readable short name of the token.
  • Description: A translated longer description of the token.

It’s important to note the structure of the array: $info['tokens']['user']['session-status']. Where user is the token type, and session-status is the machine-friendly name.

If you have the Devel module installed, you can use dpm(token_get_info()) to view all available tokens and types.

Step 2: Replace the token.

In your module, after the code above, add the following:

That’s it! The session status token should now be available and appear in the list of tokens wherever tokens are available.

Helpful Drupal Token Modules

Here’s some helpful modules that will make working with tokens in Drupal easier:

  • Token – Provides a UI to view currently available tokens.
  • Token Filter – A very simple module to make token values available as an input filter.
  • Custom Tokens – Gives users the ability to create custom tokens for specific replacements.
  • Token Insert – Allows you to insert tokens into a textarea.

More Information on Drupal Tokens

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Dec 12 2013
Dec 12

I cringe every time I hear someone mention ShareThis. When optimizing a site, it becomes a nightmare to speed up; a paranoids worst fear with all the third-party calls it makes — and a blackhole for sercuity experts tracking down the seemingly ever-changing external scripts it loads.

ShareThis Third-Party Resources

In the process of implementing a CSP, I was shocked to find the total number of resources ShareThis calls. At the time of writing this, I counted a total of 39 domains and subdomains it the ShareThis plugin was calling:

  1. http://w.sharethis.com (JavaScript, Image)
  2. http://wd-edge.sharethis.com (JavaScript)
  3. http://wd.sharethis.com (JavaScript)
  4. http://w.sharethis.com (CSS)
  5. http://l.sharethis.com (Image)
  6. http://adadvisor.net (Image)
  7. http://bcp.crwdcntrl.net (Image)
  8. http://rc.rlcdn.com (JavaScript)
  9. http://d.agkn.com (JavaScript)
  10. http://secure-us.imrworldwide.com (JavaScript)
  11. http://log.dmtry.com (JavaScript)
  12. http://match.adsrvr.org (JavaScript)
  13. http://www.wtp101.com (JavaScript)
  14. http://www.adadvisor.net (Image)
  15. http://p.brilig.com (Image)
  16. http://e.nexac.com (Image)
  17. http://su.addthis.com (Image)
  18. http://rtd.tubemogul.com (Image)
  19. http://d.p-td.com (Image)
  20. http://ds.reson8.com (Image)
  21. http://loadus.exelator.com (Image)
  22. http://dp2.33across.com (Image)
  23. http://p.nexac.com (Image)
  24. http://p.raasnet.com (Image)
  25. http://p.rfihub.com (Image)
  26. http://i.w55c.net (Image)
  27. http://loadm.exelator.com (Image)
  28. http://a.triggit.com (Image)
  29. http://sync.mathtag.com (Image)
  30. http://r.casalemedia.com (Image)
  31. http://dpm.demdex.net (Image)
  32. http://idsync.rlcdn.com (Image)
  33. http://load.s3.amazonaws.com (Image)
  34. http://d.xp1.ru4.com (Image)
  35. http://segments.adap.tv (Image)
  36. http://dm.de.mookie1.com (Image)
  37. http://ib.adnxs.com (Image)
  38. http://tags.bluekai.com (Image)
  39. http://sync.tidaltv.com (Image)

Nuts, huh?! Not a big surprise anymore why ShareThis was causing my slow page load times. From what I found, the majority of the calls are for ad and user habit tracking pixels. No wonder their a free service, their probably getting paid big bucks from companies to track what you’re doing. Though, I understand they need to connect to the various social network APIs to grab numbers, I don’t think they need to add tracking pixels for advertisements and user habits.

An example is adadvisor.net and crwdcntrl.net. Their domains used by Targus Info and Lotame which is an advertising company that is part of a network of sites, cookies, and other technologies used to track you, what you do and what you click on, as you go from site to site, surfing the Web. Over time, sites like adadvisor.net and crwdcntrl.net can help make an online profile of you usually including the sites you visit, your searches, purchases, and other behavior. Your profile can then be exchanged and sold between various companies as well as being sold to other advertisers and marketers.

Alternatives to ShareThis

After finding out everything ShareThis is doing, it was time to find some alternatives. Here’s some I’ve found that seem to be less resource intensive—though may still load ad and user habit tracking pixels, not nearly as many as ShareThis:

WordPress Plugins

If you prefer a more plug-and-play options, here’s some pretty good WordPress plugins and Drupal modules for social sharing.

1. Flare

Flare is a simple yet eye-catching social sharing bar that gets you followed and lets your content get shared via posts, pages, and media types.


2. Social Count Plus

Display the counting data of Twitter, Facebook, YouTube, Instagram, Steam Community, SoundCloud posts and comments.

Social Count Plus

3. Dig Dig

Your all in one share buttons plugin. Add a floating bar with share buttons to your blog. Just like Mashable!

Dig Dig

4. AddThis

AddThis Share Buttons help drive traffic to your site by helping visitors share, bookmark and email your content to over 330 services.


5. Shareaholic

Adds an attractive social bookmarking menu and related content widget to your posts, pages, index, or any combination of the three.


Drupal Modules

1. Social media

The social media module helps integrate your website with social media sites such as Twitter, Facebook and Google+. It provides an centralized way of managing social media profile information and plug-in widgets such as follow and share buttons.

Social Media

2. Easy Social

Centered in a single place, you don’t need to worry in including external javascript libraries, and enabling several social modules.

Easy Social

3. AddToAny

This module helpers your readers and subscribers share, email and bookmark your articles and pages using the popular services such as Facebook, Twitter, Pinterest and over 100 more.


4. AddThis

This is the #1 bookmarking and sharing button on the net. Simple and easy to use button that’s used by 14 million websites worldwide and reaching 1.3 billion people worldwide per month.


5. Service links

Service Links facilitates the adding of social networks links or javascript buttons within the content with a special focus on developers and themers interested to extend their number or customize their displaying. Built on Drupal for Drupal doesn’t include commercial advertising or spying hidden code and doesn’t require third part libraries.

Service links

Like this:

Like Loading...

Author: Ben Marshall

Red Bull Addict, Self-Proclaimed Grill Master, Entrepreneur, Workaholic, Front End Engineer, SEO/SM Strategist, Web Developer, Blogger

Feb 18 2013
Feb 18

It's a simple problem, but a serious one. You've put your content editors in front of Drupal for the first time, and they can understand the node form without any problems. They understand taxonomy terms, grok menus and node references… but they get nervous when it's time to save their work. "Will... will this be published as soon as I click 'save?'" Normally, there's no good way to make the distinction between saving and publishing a piece of content explicit. Site builders can set a content type to be unpublished by default, then give editors the broad "administer nodes" permission, but that's clumsy solution that forces editors to dig for what should be a simple action: publishing or unpublishing a post. That's where the Publish Button module comes in.

Screenshot of settings screen

With the module installed, every content type gets a simple new checkbox: "Use publish/unpublish button." Once it's selected, users with appropriate permissions get a new, Publish, on the node edit form. It unambiguously flips the node's "Published" flag and saves it. If the node is already published, the button reads (predictably) "Unpublish." Site builders can set up fine-grained permissions around who can and can't publish and unpublish content. Setting posts to be unpublished by default, then enabling this module, can give the Drupal content creation workflow an almost WordPress-esque simplicity.

Screenshot of the resulting change to the node form

Because Publish Button is so simple, there's not much to say about how it works. You set up the permissions, activate it for the appropriate content types, and you're ready to go. It won't solve all of your content workflow problems -- it makes no provisions for scheduled publishing or detailed review of revisions, for example -- but it's a clean, quick solution to the uncertainty that comes from Drupal's one-size-fits-all "Save" button.

Feb 11 2013
Feb 11

Comparing Drupal themes is tough: the screenshots they provide are often based on heavily tweaked sites with plenty of slider blocks, tweaked media attachments, and other just-so content. Figuring out the "basics" -- how a given theme styles core HTML elements and recurring Drupal interface patterns -- can be tough! Fortunately, the Style Guide module can help.

Screenshot of styleguide overview

The module was written by a group of experienced Drupal developers, site builders, and themers -- its sole purpose is to provide a single page that contains easily viewable examples of HTML and Drupal design elements. Form fields? Check. Password strength checkers? Yes! Themed Drupal navigation menus? Breadcrumbs? Tabbed input groups? Large chunks of text with inline images? Yes, yes, yes, and also yes. Just enable a theme, browse to the /admin/appearance/styleguide page on your site, and you can quickly see how it handles all of the basics. If you have multiple themes enabled (for example, a primary theme and a backend administrative theme), the module provides a tab for each one. Clicking one quickly switches the active them, and thus the elements you're previewing.

Screenshot of styleguide details

Obviously, a module like this can't show you everything that a theme is capable of. It does provide a easy way to see how it handles the essentials -- typography, form elements, navigational menus, and so on. If you're building your own theme, Style Guide can also serve as a handy checklist of elements to account for.

Feb 04 2013
Feb 04

It's a question we all ask ourselves: What would I do if my site or server was compromised? Security professionals have loads of checklists to follow, and experienced server administrators drill for those moments. As we saw when Twitter.com was recently compromised by hackers, "Reset everyone's passwords, right away!" is almost always one of the important steps. If you run a Drupal site, that particular step can be frustrating. Resetting user passwords one by one is incredibly time consuming, and there's no way to do it for everyone in one fell swoop. At least, there wasn't until the release of the Mass Password Reset module…

Screenshot of administration screen

This recently-released module gives administrators a simple, straightforward admin page where they can reset every user's password with a single click. Notification emails can optionally be sent out to each user, just as if they'd requested the password reset themselves. (If you're using the module as part of the response to an actual security incident, it's probably a good idea to modify the standard password reset email before you click the "reset" button -- explaining why they've been reset is important, and unfortunately the module doesn't let you override it right from its bulk reset screen.) You can also choose to reset the root administrator's password (User 1 on the Drupal site), though the option is disabled by default.

There are a few situations in which you'd want to issue a mass password reset in calmer times. Just before launch, for example, you might want to ensure that a large batch of users migrated from another system all select new, secure passwords. For the most part, though, Mass Password Reset is a good tool to keep in your back pocket for a time when you need it. Hopefully you won't, but it's great to have when you do.

Jan 28 2013
Jan 28

It's a word that can strike fear into the heart of the bravest site builder: Breadcrumbs. Manage them well, and you'll give visitors a helpful visual indicator of where they're at in your site. Miss a detail, and the weird inconsistencies will be more confusing than no breadcrumbs at all. The challenges stem from Drupal's "flat hierarchy" -- by default, almost all pages (including every node you create) live just beneath the home page itself in an undifferentiated pool of content. All of the visual cues it sends to visitors (breadcrumb trails, highlighted parent items in the navigation menus, and so on) start with that assumption until you override them. That's where the Menu Position module helps out. It lets you set up simple rules that tell Drupal where each node type should go in the site's hierarchy, then handles all of the frustrating details automatically.

Screenshot of administration screen

The module's operation is simple and straightforward. Site administrators can set up simple rules describing certain pools of content -- nodes of type 'Blog,' articles tagged with 'Star Wars,' and so on -- then assign them to a particular parent menu item. From that point on, the rule will ensure that matching nodes get the proper breadcrumb trail, highlighted menu trails, and so on. Multiple rules can be active at once, positioning different pools of content in their proper home. It's a much more efficient approach than positioning each node underneath a parent item manually, and there's no performance slowdown if your site sports thousands (or hundreds of thousands) of nodes.

Screenshot of resulting change to site

Menu Position was created by John Albin, the author of the popular Menu Blocks module. He's well-versed in the frustrations that come with wrangling menu items and breadcrumbs, and the module is polished and straightforward. The only downside is that items must be children of an actual Drupal menu item. If you'd like article nodes to appear as if they're the children of a complex contextual-filter-driven view, for example, additional modules like Path Breadcrumbs might be necessary. For the vast majority of sites, though, Menu Position module does the job smashingly, and with a minimum of hassle.

Jan 21 2013
Jan 21

In honor of Module Monday's post-holiday return, we're taking a look at a problem that plagues many sites: dead links. If you maintain content that contains links to other sites, it's inevitable that some of them will ultimately go bad. Domains expire, sites go down, articles are unpublished, blogs migrate to a new CMS and change their URL patterns... and eventually you're left with a dusting of broken URLs in your otherwise pristine content. That's where LinkChecker comes in. It's a module for Drupal 6 and 7 that scans your content for busted links, tells you what nodes need fixing, and -- optionally -- tidies up the ones it can fix automatically.

Screenshot of administration screen

LinkChecker runs at cron time on your Drupal site, churning its way through a bite-size number of nodes each time and scanning them for URLs. It pings those URLs, makes sure a working web page is still there, and moves on. If not, it logs the specific HTTP error for later reference and moves on. It's handy, but the devil is always in the details -- and LinkChecker is designed to handle all of them with aplomb. Do you need to white-list certain content types to ensure they aren't scanned? No problem. Need to make sure that dummy URLs like "example.com" don't get checked and generate false positives? It handles that, too. Need to hunt for urls contained in dedicated CCK or FieldAPI Link fields, in addition to text fields and node bodies? No problem. Want to check image links that reside on remote servers, or check URLs that are generated by Drupal input filters even though they don't appear in the "raw" text of the node? LinkChecker allows a site administrator to toggle all of those options and more.

The module can correct kinds of errors automatically (301 redirects, for example) but it's up to the site's administrator to check the report that it generates for news about broken links. There, each node with busted links can be reviewed and edited.

Screenshot of resulting change to site

LinkChecker is a tremendously useful tool, and its smorgasbord of configuration options means that it can deal with lots of oddball edge cases. One missing option that would still be welcome? An easy way to export the "busted links" report to a text file for review. For extremely large sites, dedicated third-party web crawlers with link checking functions may be a more robust solution, but for Drupal admins who need a hand keeping their sites tidy, it's a lifesaver.

Dec 31 2012
Dec 31

Make 2013 safer with a backup plan for your site

Ah, New Years Eve. It's the time for parties, reminiscing, and the old tradition of New Years resolutions. We promise ourselves we'll exercise, read that important book, donate to charity, or -- depending on the number of web sites we're responsible for -- vow that this is the year to set up a backup plan. Few things, after all, are more terrifying than the realization that a server hiccup has wiped out a web site, or a hasty change deployed to the live site has nuked important content. Fortunately, there's a module that can help. Backup and Migrate offers site builders a host of options for manually and automatically backing up their sites' databases -- and integrates with third-party backup services, to boot!

Screenshot of Backup and Migrate settings

Backup and Migrate offers a number of options for preserving your Drupal site's database, but all of them revolve around three important choices. You can choose to backup just a select group of database tables, or the whole kit and kaboodle -- useful for ditching the unwieldy cache and watchdog tables that Drupal can easily recreate. You can choose the destination for your backup -- drop it into a private directory on your server, download it directly to your computer if you're performing a manual backup, or send it to several supported third-party servers. And finally, you can run backups manually or schedule them to occur automatically.

In its simplest form, you can use the module to manually pull down a snapshot of a site's database for safe keeping, or to do local development with the latest and greatest production data. For real safety, though, you can tie it to services like Amazon S3 storage, or the new NodeSquirrel offsite backup service. Set up scheduled daily or weekly backups, tell it how long to keep existing backups around, and rest assured that regular snapshots of your site's critical data will be tucked away for safe keeping when you need them.

When disaster strikes, you can use the Backup and Migrate module to upload one of those database backups, and restore your site to the state it was in when the backup was made.

Screenshot of the Restore Backup screen

It's important to remember that Backup and Migrate won't solve all of your problems. It requires a third-party addon module (Backup and Migrate Files) to archive and restore the site's important file uploads directory, for example. In addition, the easy one-click backup and restore process can tempt developers to forgo safe deployment strategies for new features. Just because it's possible to download a database snapshot, do configuration work on your local computer, then re-upload the snapshot to the live server, doesn't mean it's a good idea.

That said, Backup and Migrate is an excellent tool that's proven its worth on countless sites. Its clean integration with third-party file storage services also means that it's a great transitional path towards a full-fledged backup strategy for business-critical data. If you aren't using it, check it out -- and enjoy the peace of mind that comes with keeping your site's data safe.

Dec 24 2012
Dec 24

Every week, Module Monday offers a quick peek at useful but lesser-known Drupal modules. Every week, that is, save Christmas, when we put on a Santa cap and pick a fun-and-useless novelty module to brighten the holidays. This year, it's the appropriately themed Christmas Snow module! It adds friendly flurries to any Drupal site for the holidays.

Screenshot of Christmas Snow configuration options

Surprisingly, Christmas Snow comes with a tricked-out configuration screen, allowing administrators to choose options like snow speed, wind direction, and the balance between smooth animation and increased system load as a visitor's browser animates all those flakes. The result? A blizzard!

Naturally, Christmas Snow isn't the sort of module you'd want to use year-round. (Even leaving it enabled for the holidays on a high traffic site is, well, a matter of taste.) But if you're looking for a holiday snow effect for your Drupal site, look no farther: this module does it in style. Merry Christmas, Drupallers!

Dec 17 2012
Dec 17

Among Drupal 7's new features was a freshly rewritten Taxonomy module. Starting with that version, Drupal's venerable tool for tagging and categorizing content became a FieldAPI Field, just like Image fields, Node Reference fields, and so on. That's meant much greater flexibility for editing and displaying taxonomy terms on new Drupal sites, but it's also caused a few hiccups. In particular, when taxonomy terms are deleted (say, by an editor determined to keep things tidy), the references to them on existing nodes don't go away. Taxonomy Orphanage module is designed to fix that specific issue.

Screenshot of administration screen

Using the module is simple -- once it's installed an enabled, the Taxonomy administration page gets an extra tab. There, you can can tell the module to hunt down and remove "dangling" references to nonexistent taxonomy terms. You can also turn on automatic scans for dangling taxonomy terms: whenever cron runs for your site, it will march through a configurable number of nodes and remove pointers to nonexistent terms as well. The use case is simple -- resolving a simple issue with Drupal core -- but Taxonomy Orphanage helps keep your site's content neat and tidy with a minium of fuss.

Dec 10 2012
Dec 10

It's a simple problem, but a tricky one: How can you ensure that special words and phrases, like your company's name or certain trademarks, are always linked to an appropriate web site when they're used in the text of an article? The easy answer is Word Link module: it lets you set up a custom glossary of terms that should be turned into links whenever the appear in text.

Screenshot of administration screen

Configuration is straightforward: once the module is turned on, administrators can choose what content types and what fields should receive the link treatment. Then word lists can be set up, each linking to a custom URL inside your site or on another server. Case-sensitive matching can be turned on and off for each word, and special "no-link" pages can be set up where the module won't apply its filtering. The result? Words are turned into links, wrapped in a special CSS tag that makes them easy to style, and you don't have to train your content administrators that "Our Company, Inc." should always link to the main corporate site.

Screenshot of resulting change to site

The design of Word Link -- each linked word and phrase is its own custom record with unique settings -- means that it's best suited to a small but import list of names, key phrases, and so on rather than a massive glossary. The module also features a handy "only link the first n instances to the word" option, but in the current release that feature isn't working correctly. That said, it's a clean and self-contained solution to the problem that won't interfere with the rest of your editing tools!

Nov 26 2012
Nov 26

Media heavy Drupal sites feel the pain of bandwidth costs in a big way. Simply dropping a few large rotator images on your site's home page, for example, can bloat load times and inflate costs for network and CDN usage on high-traffic sites. Drupal 6's ImageCache module (now built into Drupal 7's Image module) can scale images down to the correct size automatically, but JPEG and PNG images still have a lot of space left to give: specialized utilities can crunch them down to save additional space without compromising quality. That's where the ImageAPI Optimize module comes in: it allows you to pipe all uploaded images through those optimizers automatically.

Screenshot of administration screen

Installing ImageAPI Optimize is easy on the Drupal side -- drop the module in place, turn it on, and head to the Image Settings configuration page. Normally, Drupal provides a simple 'quality selector' on that page to control the level of compression for scaled JPEGs. With this module installed, however, site builders can specify the specific compression and optimization utilities that should be used to crunch image files as much as possible.

Most of the supported utilities will need to be installed on your web server before they can be used, but if you don't have server access or just want to try things out, you can point the module to Yahoo's hosted Smush.it service. For designers who hand-tweak every image in Photoshop, or make manual use of "Export to Web" compression features in their image editors, the utilities supported by ImageAPI Optimize may not make a huge difference. But when users or non-designers are allowed to post images as part of Drupal content, ImageAPI Optimize can help ensure that you're saving all the space (and bandwidth) you can.

Nov 19 2012
Nov 19

What's a site worth if you can't ambiguously tell authors how terrible their articles are by rating them on a scale of 1 to 5 chili peppers? How can we segregate against nodes by only allowing the popular nodes to sit at the cool nodes table? Well lucky for us we're going back to high school in this blog post as I introduce you to a few cool Drupal modules that show us how to get organic results for popular content.


 is one of the more basic, but useful rating modules that adds “rating stars” to content. Users rate the node based on the number of stars you made available, then you can view the average rating of the node to see how popular it is. Simple right? Fivestar is based on , is officially supported in Acquia Drupal, integrates with Views, and is easily the quickest way to add ratings to nodes.

Want to extend Fivestar? Check out . Want your own custom Fivestar widgets? Drupal Ace can show you how in their .


 is pretty similar to Fivestar in the voting aspect, but it also allows for thumbs up/down, emotion ratings (funny, mad, angry), etc. It’s like Fivestar and  all in one, plus a bit more. Rate also has some interesting features, such as Rate Expiration, which disallows voting after a set period of time (for that one guy who wants to down vote an article... 3 years after it was posted). Rate doesn’t allow users to cancel their vote, whereas Fivestar does. Some will bicker back and forth about which one is better, but we’ll leave that to the drama nerds and their never ending debate between Star Wars and Star Trek... Which by the way, a Star Destroyer could take on the Enterprise any day. Just ask .

Want to add some visualizations? Mix it up and integrate with the  to show off those sexy bar charts. I can hear the ladies running already.

User Points

If you want to add a bit of narcissism to your site, look no further than . Okay I kid, healthy competition between users might be a better phrase. User Points allows users to gain or lose points by performing different actions on your site. This may be writing a product review or commenting on a node. With this module, the users are fighting for popularity instead of your content. User Points ties into Services, Rules, and Views which makes it even more site builder friendly.

If you’d like to extend User Points, check out this  to add even more functionality.


If this list of modules were your high school homecoming court, then it’s time to meet your King (or Queen). We’ve met the runner-ups, but  steals the show. This module will give you the most organic results for content based on popularity. Radioactivity provides more of a hotness meter. When an entity is getting attention (either by views or actions defined by rules), it will become hotter by an increasing energy that you set, while those that are not receiving attention are cooling down. Pretty cool, huh... er, I mean hot? You get the point.

So why the name Radioactivity? The cool down rates are based on the concept of half life, or the amount of time it takes for the quantity of something to reach half of the original value. Using Radioactivity, you create a decay profile that sets the cool down rate for the entities it is assigned. Want to know the current trending articles on your site? Set the half life to 3 hours and the granularity to 15 minutes (which is the interval of time to update the energy), and watch as the popular articles float to the top while the not-so-hots sink to the bottom in real-time. Have an ecommerce site? Integrate Radioactivity with Commerce using .

Of course there are a number of settings you can use in the module, such as using memcache for storing energy values, so it’d be nice if you had some direction. Though on the project page there’s a few links for tutorials or documentation, I think that Teemu Merikoski of Wunderkraut has an  for Radioactivity.

Know of any interesting modules that help showcase popular content on your site? Let us know in the comments below.

Nov 15 2012
Nov 15

While visiting BADCamp in Berkeley, CA last week, I sat in on several discussions about productizing Drupal. Jeff Walpole, CEO of Phase II opened the discussion with a presentation on various business and product models the Drupal community has embraced.

Jeff’s experience in growing a successful services company has been that of hard work, long hours and hiring top Drupal talent to fulfill the requests of his clients. His team has created several Drupal distributions that have awarded Phase II business in the government space, yet the distributions themselves have been expensive and taxing to develop and maintain, and have been difficult to quantify based on sales.

One long-term business model would be a shift to productize Drupal in a way that is sustainable, scalable and maintainable. Creating a diverse and robust ecosystem of complementary products and services that compliment the Drupal platform would benefit the community and could add recurring revenue to a business. While this model looks good on paper there are several challenges that need to be overcome.

The first challenge that arises is licensing and selling. To dispel the myth of GPL licensing, we can in fact sell Drupal core, Drupal modules, Drupal distributions, etc. The question then becomes, how can we sell something that is freely distributed? The answer to that question is complex and open for debate.

Another question asked was, even if we do sell Drupal modules and/or distributions, how do we keep others who have purchased our product from giving it away to others for free? The answer is that we cannot…unless we tie it to proprietary APIs or services.

APIs, plug-ins and 3rd party services that support Drupal seem to be the way many forward thinking businesses are approaching the product challenge. By creating these valuable APIs and/or products we can create value to the community and design a product model that broadens our revenue stream.

So what great products can we create that will both be hugely beneficial to the Drupal community and provide monetary value to the business that owns, promotes and supports it? Whoever figures that out will be a true rockstar in the Drupal community.

Nov 12 2012
Nov 12

How to Hide Metadata From Showing on a Published Drupal Page

Drupal's FieldAPI gives site builders a wide variety of ways to attach custom data to content types and other entities. Sometimes, though, you're adding metadata -- stuff that shouldn't be displayed directly when a piece of content is shown, but can affect the content's relationships with other posts, or its overall appearance. The easiest way to do this yourself is to hide the field in question, then sneak extra CSS classes or IDs onto the node itself based on the field's value. A new module, Field Formatter CSS Class, automates that process and makes turning simple fields into extra CSS classes a no-brainer.

Screenshot of administration screen

As one might guess from its name, the module adds a new FieldAPI Formatter type -- "CSS Class." When selected, the field in question doesn't appear in the visible content of the node or entity in question. Instead, the field's value is turned into a CSS class and added to the entity's wrapper div. This is most useful when combined with a List field or a Text field with a small number of allowed values. When combined with some simple CSS rules in a custom theme (or added via a module like CSS Injector), this allows content editors to make easy choices that affect a node's visual appearance without hacking complex markup or embedded CSS rules into the content itself.

Screenshot of resulting change to site

Field Formatter CSS Class is also smart enough to sanitize the CSS classes that it adds -- even if you allow editors to enter custom text in a field, dangerous HTML attributes and CSS tricks will be scrubbed out. If you need a quick and simple way for editors to pass information about a node or other entity to the theme, Field Formatter CSS Class is a solution worth checking out!

Oct 17 2012
Oct 17

After a little over 9 months and with an impressive 1290 sites reporting they use it, Menu Views has undergone a little nip and tuck! Today, I have finally released in hopes to squash the ever so annoying bugs and wonderful feature requests that were made! This module has been an invaluable tool in the mega-menu creation process. It has solved a problem for many people: how to insert a view into the Drupal menu system.

Many Drupal sites I've seen through out the years (those that have complex mega-menus) left me perplexed at how to accomplish this task. I could never really imagine it happening effectively, unless it was rendered using views. After being able to finally see how some of these sites actually accomplished this great feat, I was also a little baffled at the shear complexity of making it happen.

Often times, the theme is the unsuspecting and unfortunate victim. Being hacked, sliced and injected with arbitrary code to succeed in rendering the desired result. Some prefer to do it this way and to them I say "be my guest". However, when a more dynamic approach is needed, it is far better to utilize the awesome power of Drupal. Which begs me to reiterate what the purpose of a CMS is for: letting the system actually manage the content (hmm novel idea).

Menu Overview Form

Eureka! Let Drupal's own menu system and administrative user interface handle this complex problem! When I first released Menu Views (1.x) that is what it solved: inserting a view into the menu. However, it also introduced quite a few other problems that were unforeseen and rather complicated to fix. Namely these involved other contributed modules and the biggest native one: breadcrumbs!

Over the past few months, I really started digging into the complexity that is the menu system in Drupal. Trying to figure out what exactly I could do to help simplify how the replacement of links were intercepted and rendered. After pouring over the core menu module and several contributed modules, I began noticing several commonalities in the best approach: theme_menu_link().

In Menu Views-1.x I was intercepting theme_link() instead. In hindsight, I can't believe how incredibly stupid that was! So essentially, the old method intercepted every link on the site with the off chance it might be a menu link that had Menu Views configuration in the link's options array. Whoa... major performance hit and a big no-no! For this reason alone, that is why I decided to do a full version bump on Menu Views. Part of this decision was to consider existing sites and how they may have already compensated for view were popping up everywhere. An additional deciding factor involved refactoring the entire administrative user interface experience.

Menu Item TypeIn Menu Views (1.x), there seemed to be a lot of confusion around "attaching" a view and optionally hiding the link using <view> in the link path. I thought about this for a while. Ultimately I decided that the best way to solve this would to separate the view form from the link form and give the administrator the option to choose what type of menu item this should be. In this way, menu views can more accurately determine when to intercept the menu item and render either the link or a view.

There are now a couple options to better manage what the breadcrumb link actually outputs as well. Along with rendering a title outside of the view if desired. Both of which can use tokens! No longer are we left with stuff extraneous markup in the view's header. Last but not least, one feat of UI marvel: node add/edit forms can control menu views and you're no longer limited to just the menu overview form!

Menu View Form

Per some user requests, I have also set up a demonstration site so you can firebug to your heart's content: http://menuviews.leveltendesign.com. I push blocks on the left and right to show that it integrates well with Menu Block, Nice Menus and Superfish.

Overall, I think Menu View's new face lift will allow this module to reach a new level of maturity and stability that has been greatly needed. Thank you all for your wonderful suggestions in making this module a reality and truly a joy to code!

Stay tuned for next week: Theming Menu Views in Drupal 7

Aug 28 2012
Aug 28

There are dozens of cool social media icon sets. Many designers want to create a custom set of icons to match their theme. The social media module was built with an icon set manager API.

The social media module for Drupal includes a default icon set called LevelTen Glossy. It also has built in support for a half dozen other free icon sets. Just download them, put them in the correct folder, and presto they are ready to use.

But what if you want to add your own icon set? Here is how to do it.

Adding a custom icon set social media

The socialmedia.icons.inc file contains the API. You can use that code as a starting point. You will want to implement the API in your own custom module such as example.module. The first step is to implement hook_socialmedia_iconset_info();. In your module you will want to add a function like this:

<br /> function example_socialmedia_iconset_info() {<br /> $icons['myicons'] = array(<br /> 'name' =&gt; 'My Icons', // name of your icon set<br /> 'publisher' =&gt; 'Me', // name of publisher<br /> 'publisher url' =&gt; 'http://www.mysite.com', // url to publisher's site<br /> 'styles' =&gt; array( // different variants of icons available<br /> '16x16' =&gt; '16x16',<br /> '32x32' =&gt; '32x32',<br /> '48x48' =&gt; '48x48',<br /> ),<br /> 'path callback' =&gt; 'example_icon_path_myicons, // callback for icon urls<br /> );<br /> return $icons;<br /> }<br />

This works very much like hook_menu();. It just tells the system about a new icon set and provides essential information.

The second element you will need is your path callback function. This needs to match the ‘path callback’ element in hook_socialmedia_iconset_info(). This function is to return the path where the icon can be found.

<br /> function example_icon_path_myicons($platform = 'twitter', $style = NULL) {<br /> $style = isset($style) ? $style : '32x32';<br /> $pt = array(<br /> 'googleplus' =&gt; 'google_plus',<br /> );<br /> $path = drupal_get_path('module', 'libraries') . 'socialmedia/icons/myicons/' . $style . '/' . ((isset($pt[$platform]))? $pt[$platform] : $platform) . '.png';<br /> return $path;<br /> }<br />

When you create your icon set, you will want to follow the standard naming convention which can be found in the socialmedia_icon_platforms() function. If you do have an icon name that does follow the convention, you can use the $pt array to define exceptions. For example, in the above code, the Google+ icon is named google_plus.png, not the standard of googleplus.png. So an exception was created in the $pt array.

Jun 29 2012
Jun 29

Many of you might be familiar with the module Skinr (http://drupal.org/project/skinr). It gained a lot of support back in Drupal 6 by providing an easier, albeit somewhat verbose, way of dynamically configuring how elements on your site are styled.

When I first started using Skinr, it worked as advertised; however, it ultimately left me with a bitter taste in my mouth. I felt like I was constantly trying to navigate an endless maze while blind-folded. There were options upon options and fieldsets within fieldsets. It had almost everything but the kitchen sink in it.

I never really have been one who enjoys feeling like I’m just wasting my time. So I eventually scrapped this module as being a potential long term candidate for managing customizable styling. Apparently I wasn’t the only one who had these concerns either.

Then the 2.x branch was born. I only started using the 2.x branch because it was the only one available for Drupal 7. They had completely scrapped the old interface and did an amazing amount of work to make Skinr easily maintainable. You can view a list of changes here: http://groups.drupal.org/node/53798.

So if any of you are like me, you probably were thinking: “Skinr, in Drupal 7? I don’t want to make this any more confusing than it has to be!” Well fear not! You can learn how to start Skinr-ing in just 7 easy steps!

Let us know if you're using this module and leave us a comment below!

May 22 2012
May 22

We have some really fantastic clients here at LevelTen and have worked very hard with them to explain how web development works. We find though that there are many people that just have no idea what the process is about. Over the last couple of years of working with a fantastic team here at LevelTen, it has occurred to me just how similar building a website is to building a house. Turns out this analogy helps a lot in explaining what we do and how we do it. It also helps set expectations along the way.

If you were to start building a house today, would you start by hiring an interior decorator? Of course not! You also wouldn't ask them to design the structure of your house and yet this is often what happens when building websites. It is important to gather together all the right people necessary to build a website just like when building a house.

General Contractor/Project Manager

First there is the general contractor. For a house, he is the main contact that you, the customer, will have with all of the other people building the house. You may talk to the other people but at the end of the day he is the one responsible for the whole project, and to make sure that everyone has what they need and works together. At LevelTen we call this person the Project Manager.

Next up you would probably go talk to an architect to design the house. What's interesting at this point is that no one is really talking all that much about the color of the paint on the walls and which pictures go where. Generally you are just trying to get an outline of the house, which rooms go where and how big they are. Then there is the engineering of making sure everything is livable and works right. At LevelTen, this is the Information Architect/Wireframers we have. Their main job is to talk to the client, get a good idea of the breadth of the project and then design the whole thing so it will work.

Architect/Information Architect

It is really important when talking to an Information Architect to make sure that you don't leave stuff out. Could you imagine getting near the end of building your new house and then remember that you wanted a media room right in the middle. How much would it cost to squeeze another room there? That happens all the time in the web world. If we don't know what is going on up front then we can't plan for it and it is going to take a lot of effort (read time and money!) later on.


The next person who builds a house is the actual builders. They lay the foundation, raise the walls and make sure everything the plumbing and wiring is done. In typical house construction this usually takes about 40% of the budget to get the foundation laid and the walls framed. This again is very similar to web development. At LevelTen we have a very talented group of developers who use Drupal to build some incredibly feature rich websites very quickly. These are the builders of your website. They are going to be building the content types and views (roughly like rooms) and make sure that all the modules are set up (roughly like plumbing and electrical).

It's at this point that a web shop that really understands Drupal is going to stand out. It takes a while to really learn how to build a Drupal website the right way. We've seen plenty done the wrong way. So finding someone who can do it right the first time is important. Would you hire someone who only has experience building brick buildings to build your wooden framed house? I sure hope not.

Interior Decorator/Graphic Designer

Once the building of your house is done the Interior Decorator takes over. This is the person that picks out the colors, bricks, furniture and finishing touches for the site. So much of this process is dependent on the preferences of the person who will be living in the house that this is a bit of an art to get right. Again we've got a couple of very talented designers here at LevelTen that can make amazing designs for websites. They will pick out the colors and pictures (kinda like furniture!) and make sure everything looks good together.


Of course once the whole design is in place you are going to need The painters and movers to actually get the house looking like the design. This is analogous to our themers. It actually takes quite a bit of work to get all the images, colors and everything set up so that a very dynamic site will always look good. This is one area where I'd say the web world is actually harder than the physical world. Mostly because everything has to be done in such a way that it looks good on hundreds of pages instead of just one room. Luckily we've got a great themer with an eye on detail and a complete understanding of all the different browser quirks.

Occupants/Content Authors

At this point the house and website are more or less done but there is still one thing missing and that is the occupants! In houses people live in them, move around in them and are constantly doing things. With websites that is the role of the Content Authors. In order to have a really great website you need to constantly create and update your content. This is very much like the people that live and breathe in a house. You are going to need some people to live an breathe in your website as well. At LevelTen we typically don't do a lot of the content authoring since that is so specific to the company that it turns out much better when done by someone internal. We do, however, do a lot of training using the newly built website and how to best write for

Security and Maintenance

There is one other group of people that is important for houses and websites but is often overlooked. They are the people who secure and maintain the house. Think of the security monitoring firm and the handyman. Websites need the same monitoring and maintenance. You wouldn't build a house, furnish it and then not look at it again for 3 years would you? Websites are the same way. You need to keep them secure and maintained. LevelTen also offers a support contract that handles this, which allows our expert team to keep your website secure, up to date, and working.

So next time you think about building a website, be sure to not just look for some pretty designs but find a team that has all the skills necessary to take your project through the full process to create a successful website. I can honestly say that our team here at LevelTen is the best team I have ever seen for building websites, and it is an honor and privilege to be working with them.

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Feb 29 2012
Feb 29

Drupal Apps are crazy cool. They make Drupal site building fast and fun for everyone. That’s right, everyone and anyone. Even if you are new to Drupal. They are that simple.

Despite their coolness, apps are new to a lot of people. So we thought we would put together this quick Drupal Apps demo video.

After the demo, go ahead and take apps for a spin. A test drive is the best way to understand what apps can do for you. These instructions will get you started

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Feb 21 2012
Feb 21

There is no doubt that Drupal 7's admin is light years better from a usability perspective. Yet, even with all the enhancements, we find site admins still stumbling to manage their content. Over the last few months we have worked out a set of enhancements that have made our clients lives much easier. So we thought we would share.

Being Drupalistas we share in code form. First we built these enhancements into the Open Enterprise Drupal distribution. This weekend I encapsulated these features into the Enterprise Base module so you can incorporate the enhancements into any Drupal 7 site . (I know it's a bit of an odd name but it serves as the base for all Open Enterprise content apps, thus the name Base).

Problem: Not all content is what it seems

What we have observed with site authors, editors and admins is that they don't think of content as generic nodes. They think of blog posts as blog posts, events as events, videos as videos. Not as content that is typed. When they are on a blog post or a listing of blog posts, they want to easily be able to administer other blog posts or create new ones.

Solutions: Content as types

The solutions we found are actually quite simple but have made a huge impact on how people work with the content types on their site.

1. Content type specific admin

The main way to administer content in Drupal core is the content admin page. This page displays a table of all content on your site presented in a generic way. You can filter by type, but this is tedious, somewhat non-intuitive and still lists content in a generic way. What is needed are content type specific admin pages that are easy to navigate.

Content optimizer modal analysisThe solution: a content type specific content admin view. We have created a general admin view that works like core's content admin with some filter enhancements. This view is overrideable so content type specific fields, filter capabilities, bulk update options, etc can be added. For example the events content type has the event date field in its admin page. The location type has addresses. Image types could have thumbnails.

The next trick is to make it easy to navigate. For starters, we configured sub-tabs under core's content admin for each type. This makes it very simple to switch between types. We also added a "+ add [type]" contextual link as a bonus. But we can still make this easier.

2. Contextual links for type specific admin

Most of the time an editor's desire to jump to the content admin is sparked by reviewing a node or while on a list of nodes. E.g. they are looking at an event or a listing of events and they want to jump and look at an admin view of all events. To do this, they first have to remember that events are actually content. Then they need to click on the content option in the tool bar, and then filter by event type. Now they still don't see the date and times of the events.

Content optimizer modal analysisSo let's make this dirt simple. We already have an event specific content admin, we just have to give them an easier way to get to it. The answer: add a contextual link "+ administer [type]" to node pages and in views that display content of a specific type.

Let's also throw in a "+ add [type]" contextual link while we are at it in case the event reminds them of another, or we are having to enter a series of events.

Getting it

At first when I saw these enhancements, I thought they were rather trivial from a power user perspective. But since I have been using them they are really quite handy. It has also created a contextual shift where site admins used to think of things like events as nodes with special fields. Now they think of events as events. This may sound trivial, but clients are now thinking of some very novel uses for their sites because Drupal does not just manage content, it now manages events, locations, videos and much more.

Try it out for yourselves. There are a few ways you can quickly add this to a site:

  1. Traditional manual install by downloading the Enterprise Base module and dependencies from Drupal.org
  2. One click install via the LevelTen Apps Server. You must install the apps connector modules first.
  3. Start your site with the Open Enterprise Drupal distribution. The apps server connectors are included - along with a lot of other great stuff.

If you went the Apps route (#2 or #3), go ahead and download some content apps like blog, location and events to see how the content admin overrides work.

What do you think? Got any ideas for how to improve the content admin? Let me know.

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Feb 10 2012
Feb 10

The Social Media and Widgets modules have become pretty popular in the months since they launched. The feature request queues have been filling up. Mostly with requests to customize widgets or add new ones.

The modules already support a variety of ways to add new and custom widgets on your own. There are two ways to create your own widgets; coding them in modules using the Widgets and Social Media APIs or adding them via Drupal's UI using the Widget definition admin. While the UI approach has some limitations, it is remarkably flexible and works well as a simple way to add most widgets you might need or to customize those provided by other modules.

It's Alive – Experimenting with Widgets

At their most fundamental level widgets are just snippets of markup code. The Widget module encapsulates these snippets into widget definitions. Definitions store the code templates and any other data related to making the widget work. Once a definition has been created, the widget can be reused and customized in many different ways on the site.

To create a new widget definition simply install the widgets module and go to admin > structure > widgets > definitions and click on the + Add new definition link. If you have a module that provides widget definitions like the Social Media module you can clone those definitions to see how they are built.

Once you have a definition created you have two options from the definition admin page (admin > structure > widgets > definitions). The operations edit link allows you to alter the definition. By clicking on the name of the definition you are taken to a preview. The preview shows you the how the widget will display, the input and rendered version of the code and provides a form containing any widget custom configuration settings. You can change configuration settings and see how the widget reacts. Using the widget edit and preview forms together gives you a lot of control for tweaking your widget definition.

Widget templates

The definition template is the meat of the widget definition. It is where the code snippet is stored. Templates can be as simple as static cut and paste code. For example you can use the below code from Twitter to create a Tweet button. Go ahead and try these code examples out in the widget definition admin to see how they work.

<a href="https://twitter.com/share" class="twitter-share-button">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

While widget definition built using static templates might prove a convenient, simple way to organize your site's code snippets, the real power of widget templates is the ability to add in dynamic elements. Widgets support Drupal core's de-facto system for dynamic data, tokens. You can use tokens to make widgets more adaptive. For example, in our Tweet button we might want to customize the Tweet message by using the data-text attribute. Note, I have left off the JavaScript portion of the code to save space.

<a href="https://twitter.com/share" class="twitter-share-button" data-text="Check out [current-page:title] at [site:name]">Tweet</a>;

When this widget is displayed the tokens will be replaced with dynamic data from your site. In the widget definition preview form you can click the tweet button to see the results.

There are times though where you want to allow admins to easily customize the widget without having to know the code structure. Widget templates support a variables syntax that will auto generate fields in a configure form for admins to easily make changes. Template variables are denoted by using brackets and question marks as follows:


In our Tweet button example, we might want to allow admins to specify a via Twitter handle using the syntax

<a href="https://twitter.com/share" class="twitter-share-button" data-text="Check out [current-page:title] at [site:name]" data-via="[?via=?]">Tweet</a>

The above code introduces a variable configuration "via". By default it is blank. You could set the default to a literal value or a token. When the widgets system encounters a variable it adds a field to the configuration form for that widget. You can see an example of the configuration form on the widget preview form (admin > structure > widgets > definitions > [name of definition]). Site administrators can access this form on a real widget from the widget set editor (admin > structure > widgets > [name of a set])

One issue you might run into with a widget is that you want to implement a variable attribute but when it is blank you want to remove the attribute all together. In the code above, even if you leave the via variable blank, the code would still render as data-via="". If you want to remove the entire attribute when no value is given you can use the following structure:

<a href="https://twitter.com/share" class="twitter-share-button" data-text="Check out [current-page:title] at [site:name]" [?via=data-via="{<none>}"?]>Tweet</a>;

In the above variable structure the entire data-via attribute is contained within the variable markers. The configurable part of the code is contained within curly brackets. If the value of via is set to <none> the entire attribute is removed.

Getting more advanced

The widgets definition UI provides a great deal of flexibility for creating widgets. However there are times where you might want to do more advanced things. For example you might want to customize the configuration form. To do that, you will need to code your widget into a module (hint, use the definition export) and use hook_widgets_element_alter. This is just one example. The widgets module has several APIs to support advanced configuration.

In a future post I will review the APIs. For now, it helps to look at how the Social Media module implements the Widget APIs.

Got a great widget

If you have worked out a great widget definition you think would be helpful for others, go ahead and export it and send it to me. The Widgets or Social Media issues queues on drupal.org are the best place to submit new widgets ideas.

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Jan 27 2012
Jan 27

We are delighted to announce that iO1 has acquired Drupal modules

We would like to thank and recognise John Forsythe who has done a fantastic job that has helped out virtually every Sitebuilder / Drupal developer / Themer over the last few years.

DrupalModules.com has been critical to the growth of Drupal and we plan to make sure that we continue to support the future growth of Drupal. We hope to do you proud in what we do with your baby!

History of Drupalmodules.com

John is a web designer and programmer working out of Ottawa, Canada. He runs a Drupal design service called Blamcast and is a member of the Drupal Association.

Why did John make Drupal modules?

"When I first started using Drupal, I was overwhelmed by the sheer number of modules available. Drupal offers many modules with similar features, and finding the best one for the job is often difficult.

So, In February of 2007, I set out to build a system to help Drupal developers find modules faster and easier. It turned out to be a lot more work than I originally thought, and the project was put aside in favor of other pursuits.

Then one day in October, I saw a survey posted by Dries, showing a strong community desire for exactly what I had been planning. My inspiration was renewed, and since that day, I have been working virtually non-stop to get this project completed.

What you see is the result of over 1,000 hours of development work!"

What happens now?

The site will continue to run as before, although it has been moved onto EC2 with much more power under the hood. iO1 have started upgrading the site to Drupal 7, the first release will most probably be just a refresh with a new look and feel.  We might sneak in the odd feature but the focus is on getting a platform for future development and we felt that moving to Drupal 7 was critical to this.

What about the drupalmodules sponsors?

We recognise and thank the support that the sponsors have given to Drupalmodules over the years, a lot of the major Drupal shops have advertised over the years. However all of these arrangements have ended and we do not see that we will be accepting advertising in the future, for now iO1 is happy to provide all the financial support needed to run this fantastic community service.

If you have something that needs promoting and its important enough to the community then feel free to contact us, we will be happy to promote you/your project, we just will not charge you any money.

What are the future plans?

We don't really know the answer yet!   We don't see Drupal modules as just a review site, we see it as an information hub and toolset for the Drupal community, we see somewhere that is free from the constraints of D.O. that will allow us to continue to lead in the way that John has lead for the last few years.  So everything we do will be done with this in mind.

This is a really exciting day for us all and we are stoked with the possibilities this brings, but there are so many possibilities that we have not finalised what we are going to do and we wanted to talk to the community about what the need / want before making any decisions, obviously we plan to scratch a few personal Itch's like being able to set a version context when browsing / searching!

We would love to hear your ideas in the drupalmodules forum, we have opened a thread Your itch goes here

Jan 13 2012
Jan 13

Have you ever made a Drupal site where the design called for implementing one or more mega-menus? Have you spent countless hours downloading module after module and hacking your theme's template file to get the code to insert at just the right place?

LevelTen Interactive introduces:

Mega menus are typically a collage of multiple types of content: images, links, lists or forms all put into some type of grid or table layout. The beauty behind this module is you can configure an existing view or even create an entirely new view to display exactly what you want. Then just attach that view to an existing menu item.

By design, this module only provides basic HTML structure for inserting a view into the menu system. It does not actually style your [mega-]menu. If no styling exists in your theme or is not provided by a contributed module, the view will appear next to your menu item (which can often be a little confusing at first). It is up to the theme or contributed module to actually style the view to appear inside your menu. If the contributed theme or module implements drop down menus, using CSS or JavaScript, a new child selector (li > .view) must be included. The view can then be styled appropriately from there.

Menu Overview (shows which menu items have attached views):
Screen Shot 2012-01-13 at 8.50.23 AM.png

Menu Item Edit (adds the "Attach view" fieldset for choosing a view):
Screen Shot 2012-01-13 at 8.51.00 AM.png

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Jan 11 2012
Jan 11

January 11th, 2012

1. Display Suite
DS lets you customize the output of nodes and their content fields without having to modify template files. Even clients can drag and drop fields and change how they display and are formatted. If only life were this easy!

Ben – Best thing that happened to Drupal since CCK.
Brandon – More ‘Drupal-way’ than panels.
Trent – With the pulling the node and view layout changes out of the template files, we are able to make changes to sites without having to have your desktop or laptop on hand, making Drupal content layout almost completely editable on a mobile device like an iPad or phone.
John – Powerful and versatile, and very intuitive. It’s easy for a developer to incorporate it into their workflow, and before long it’ll look like the solution to almost any problem.
Shea – Powerful and exportable. Something every developer needs.

Display Suite

2. Views 3
Views is a dynamic tool for building queries that display tables and lists of data. The third version has some amazing new abilities and enhanced user interface features.

Ben – The backbone of any Drupal site. More useful then 50% of core modules.
Brandon – They took what makes Drupal good (views 2), and made it better.
Johannes – One of the most essential contributed modules got a major upgrade!
Shea – You simply do not use Drupal without using views. If this isn’t the most useful module out there I don’t know what is.

3. Context 3
Context 3 lets you control conditions and reactions for different sections of a site like displaying a certain block on all nodes of a certain type or hiding a block when a menu or view is active. It saves developers from writing custom hooks and the interface is straight forward so the clients can use it too.

Johannes – Like Views it’s one of the modules we use on all projects for its awesomeness. Happy to see a major release last year.
Shea – Context brings logic and sense to Drupal. It is what is missing in the default blocks system.

4. Omega
Instead of creating a new theme from scratch or maintaining a custom in-house theme for a new project ImageX Media started using this theme as a base for our client themes.

Ben – Great starting theme with responsive abilities backed in. Makes theming fun even for coders.
Brandon – There is also Plink. The strength of Omega is really Delta, see Delta below.
Johannes – My highlights are that it comes out of the box with a responsive grid layout and it’s HTML 5 compliant. The maintainers put a lot of work into this over 2011.
Trent – The way Omega handles regions has been one of the greatest powers I have come to love about the theme. Being able to add a bunch of regions to the .info file, then using the theme settings to place them in what section of the page you need, then being able to change it on a specific page with Delta, the Omega helper module, is awesome. Omega and Display Suite bring the goals of a CMS to the forefront. Manage the content and layout from the administration back end, while staying exportable. Excellence.
John – Great for getting a responsive design up and running quickly.
Shea – Omega + Delta gives amazing flexibility to developers and administrators through the website UI. The work done to not only provide customizable layouts but responsive themes is impressive.

Omega Theme

5. Delta
Delta allows you, via the Context module to make duplicates of your theme settings for any context on your site. This gives you the ability for alternative layouts as a reaction in Context.

Ben – In combination with Omega a great set of tools to create theme and layout variations.
Brandon – Delta is no longer Omega-only. Extended to all themes and works extremely well together with Context.
Trent – Took a bit to get used to the concept, now I am not looking back. Layouts, grid settings, region placement and more can be set on a per Context basis.
“Shea” – Delta is to Omega as Views is to Drupal

6. Workbench
One of Drupal’s big learning curves is when you teach a content editor to ‘ignore’ all the technical stuff they get forced to see. It can be overwhelming. So Workbench tries to create a tailored interface just for content editors. Then it adds a permissions structure for editing content that matches the organizations structure. And finally Workbench tries to enable a customizable editorial workflow for moderating and publishing content.

Ben – A lot of potential but still not fully ironed out IMHO.
Johannes – It is not a complete solution, but it’s a great start to make the Drupal content editor experience much better than default.
Shea – A starting base for workflows and moderation. There is still much work needed in this module but it is probably the best choice out there for what it does.

7. CCL
The Custom Contextual Links module allows you to add your own links to the contextual drop down widgets of blocks and nodes. Drupal comes by default with contextual links and until now you would have to do some custom coding to customize this. This module gives you a nice UI to make your changes and doesn’t require PHP coding skills.

Ben – I created the CCL module to make it possible to add your own links to the contextual links widgets in Drupal 7
Shea – A somewhat unknown module that provides a simple but extremely useful bit of functionality.

8. Media
Drupal has had a tough time when it comes to managing files and media ‘assets’. Anything from ‘where do you store a file that’s referenced from the database’, ‘how do you control permissions on those files’, ‘what do you do with the file if the node it was attached to gets deleted’ and (not lastly) ‘how come I can’t reference the same file in multiple nodes’. The Media module is the latest attempt at integrating files and media in an easy to use way that makes sense to everyone. In the latest release, Media allows users to attach fields to files as you would to nodes, link to remote assets like YouTube, drag and drop upload, and even integrates with the WYSIWYG module.

Ben – Equal amount of joy and pain.
Brandon – This is awesome, disregard above. Very easy to use, Media library reduces duplicate file uploads.
Shea – I love to hate it. I want everything it has to offer but immediately want to ditch it when it starts throwing up problems. Still in its infancy stage it has the promise to be an amazing addition to Drupal. The problem is that it doesn’t always work.

9. Field Group
Field Group lets you group fields together. Great solution if you want to make horizontal tabs.

Ben – Works great in combination with DS.
Brandon – Should be in core, too key
Trent – Using Field Groups with Display Suite has become the standard for content layout. Being able to setup tabbed content, or just group content sections on a page without having to build a custom block for the styles has made this a must enable for me.
Shea – Useful for organizing fields. Handy but not a necessity.

Field Group

10. Backup and Migrate
A simple module that lets you backup the database and files, stores them on the server, lets you download so you can upload to another site or just keep warm under your pillow. This is a quick and easy way to avoid ruining a site when you want to try something new or just to keep a copy of the important stuff. Never leave home without it!

Johannes – Over the last year, we fell more and more in love with this module and it’s one of the first modules I’ll install for any projects. Besides the features described above it has also has a nice module to integrate with Dropbox.
Shea – Backup and Migrate + Amazon S3 simple storage account rules. Fast, effective, and stable backups that are extremely portable make your site recoverable and speed up the local development to development environment syncing.

Dec 13 2011
Dec 13

Have you ever needed to put Service links or ShareThis into block? How about AddToAny in a node link? Want to have different share buttons per content type? Want a simple way to add the latest widgets from Twitter, Facebook or Google to your site. Want to enable admins to customize widgets without having to dig into the API docs? It's time to start wrangling in all those widgets.

Virtually all the sites we have built over the last several years involve integration with sharing sites and social media through various code widgets, gadgets and plug-ins. The typical process of adding widgets by mixing modules, widget API configuration and custom blocks is tedious at best. To help organize and streamline this process, we recently released the Widgets module.

Defining the problem

Widgets are small snippets of code that enable people to do a variety of things such as share content, visit social media profiles, view updates and so forth. Some widgets are simply copy and paste. Others require dynamic data such as a page title or URL. Many widgets can be customized by changing various parameters in their code.

The main challenges with widgets are:

  • How do we place them on the site?
  • How do we deal with dynamic data?
  • How do we manage custom settings?
  • How do we keep a diverse set of widgets organized?

There are several modules that solve these problems for specific types of widgets in their own way. For example, Service links, AddThis, ShareThis and AddToAny all enable you to add content sharing buttons to your site. There are others that help pull in Twitter and Facebook widgets. There are those that provide links to social media profiles – and the list goes on.

The main issue is that each has their own UI and feature set. Some allow you to place widgets into blocks, some in node links, some embedded into content, but there is no consistent standard. Some allow you to build one set of widgets, some multiple. Each deal with dynamic content in their own way, often through a specialized, single-use token system. Each has different support for caching.

That is not to say that these modules are bad, many are pretty great with their own slick interfaces. However, on today's highly socially-integrated sites, an array of widget types is needed. We need a standardized system for dealing with all these widgets.

The Widgets module

Widgets definition list screenshotThe Widgets module is meant to act as an API to help centralize management of various code snippets. It has an API for modules to provide code snippets via widget definitions. You can also add custom definitions via the admin.

Widgets set form screenshotWidgets definitions can be organized and customized into widget sets. Widget sets are built using an interface similar to core's image style admin. Just create a new widget set then add widget elements from a drop down list. You can sort widgets via drag and drop and modify customizable widgets via configuration forms.

Widgets visibility settingsSets can be displayed in blocks, tokens and node links by content type and display modes.

Widgets definition preview screenshotDrupal's core token system is used as the standard for managing dynamic data. Widget definitions can include standard tokens and special variable tokens which enable admins can configure settings per widget. A simple syntax makes it easy for widget definitions to auto-generate configuration forms from variable tokens.

Widgets set list screenshotTo make things even more plug and play, the API enables modules to define pre-built widget sets. These can be overridden and customized.

Widgets cache settings screenshotFinally, a tunable caching layer is used to assure widget sets load quickly. Caching can be set across all pages, by node authors, by page and by logged in user.

We hope you find the Widgets module as useful as we have for wrangling in the widget herds. Got any improvements, suggestions or comments? Let me know below.

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Dec 12 2011
Dec 12

Healthcare, love it or hate it, it's not going away and in fact the healthcare industry is booming and continues to grow. Almost daily we hear about some revolutionary break through in medicine that will help us to lead longer healthier lives. The web has made sharing knowledge and information easier and easier and the emergence of smart phones allows anyone to access years of historical data at their fingertips. The problem is that traditionally this data has been uploaded through systems that are archaic and quickly becoming obsolete thanks to the rapid emergence of open source tools like Drupal.

Over the past few years, we've seen Drupal's adoption in the arts and entertainment industry, government organizations, online publishing, social communities and now healthcare. At LevelTen we have had the opportunity to implement Drupal for numerous healthcare industry clients like: Caris Life Sciences, Health Market Science, Mission Pharmacal and McKesson to name a few. Just like those in other industries, the medical world is starting to realize the speed at which they can deploy new products and brand focused sites utilizing Drupal's intelligent framework.

The healthcare industry is extremely specialized and often times the information can be confusing or overwhelming to the end users. Utilizing Drupal, a website can be easily modified or changed based upon feedback from patients and site visitors, and ultimately continue to make the site better and more user-friendly over time as a result of that feedback. Plus, some of the more advanced features allow for easily sharing related information and content; in the long run those extra tools will equate to a greater visitor return rate and longer website visit times.

Maybe you're considering Drupal for your medical organization; here are just a couple of great points to consider:

  • Integration - Drupal has a very sophisticated structure and as such can be tied into almost any applications, applications with a solid API are even easier. The benefit of integration is a universal experience for all of your site users and visitors.
  • Customization - Drupal has over 8000 modules (extensions to add functionality) currently available and that list only continues to grow. The benefit speaks for it's self, but the more options available to choose from the faster your site can be deployed, ultimately lowering costs.
  • Easy to Update - Drupal is a CMS and a framework both; the CMS portion when combined with the right modules, makes it easy for non-technical staff to update and manage the website.

I could go on and on, but if you're in the healthcare industry and reading this then Drupal is probably already on your radar; either way I would love to speak with you about some of our past projects and approach to see how we might be able to help you.

Get Drupal help when you need it most! Find hundreds of great tutorials. Track, rate, comment and more. Create Account
Jun 13 2011
Jun 13

There were a ton of great SEO modules for Drupal 6, which made it a go to content management system for those looking to easily optimize their websites for search engines like Google and Bing. Some modules have made the switch from Drupal 6 to Drupal 7 fairly quickly and easily, while others are still on a slow path to getting a Drupal 7 release. In the following article, we take a look at where some of the top Drupal SEO modules are in their development cycle right now for Drupal 7 and find some new modules to help make sure your Drupal 7 website is fully optimized for search engines.

Currently, Nodewords, is the one module that we have found that people are really looking for in Drupal 7, but the new Metatags module that Dave Reid is working on is not quite ready for showtime yet. There has been some progress made by others in the community to come up with a quick fix for the time being. You can find the Meta Tags Quick module, http://drupal.org/project/metatags_quick, by valthebald, currently with a full Drupal 7 release that will give you some quick and dirty meta tags functionality through the new Fields API in Drupal 7. Meta tags don’t seem to hold as much importance for search engine rankings as they used to back in the early days of search engine optimization, but they can help fill in the blanks for more semantic style markup and RDF that shopping and news search engines use.

The list of fully released Drupal 7 SEO modules is somewhat small compared to Drupal 6, but slowly growing with more modules coming out of alpha and beta. Currently there are only 19 full projects listed that have anything to do with SEO for Drupal 7. It also looks like Drupal 7 should have some great search engine optimization support from new module builders as well. We have compiled a list of all the SEO modules for Drupal 7 we could find. We have compiled our list from Drupal.org with their handy new Apache Solr search capability. The list is in order of usage. You should take a look at this list, and take a look at your Drupal 7 installation, and make sure you are running most of these modules if you are trying to take Drupal 7 SEO seriously.

The list of Drupal 7 SEO Modules list, as of 6/11/11

  1. Pathauto - http://drupal.org/project/pathauto - Full release, beta
  2. Page Title - http://drupal.org/project/page_title - Full release, beta
  3. SEO Checklist - http://drupal.org/project/seo_checklist - Full release, beta
  4. Custom Page - http://drupal.org/project/custompage - alpha release
  5. Taxonomy Title - http://drupal.org/project/taxonomy_title - dev release
  6. Revisioning - http://drupal.org/project/revisioning - Full release, beta
  7. SEO Compliance Checker - http://drupal.org/project/seo_checker - Full release
  8. SimpleHTMLdom API - http://drupal.org/project/simplehtmldom - Full release
  9. SEO Watcher - http://drupal.org/project/seowatcher - Full release, beta
  10. Droptor - http://drupal.org/project/droptor - Full release
  11. Extended Path aliases - http://drupal.org/project/path_alias_xt - Full release, beta
  12. Simple Page TItle - http://drupal.org/project/simple_page_title - dev release
  13. Internal Links - http://drupal.org/project/intlinks - Full release
  14. 443 Session - http://drupal.org/project/session443 - dev release
  15. Smart Paging - http://drupal.org/project/smart_paging - Full release
  16. Humans.txt - http://drupal.org/project/humanstxt - Full release
  17. Extended Search Page - http://drupal.org/project/ext_search_page - Full release, beta
  18. Pretty Facets Paths for Search API - http://drupal.org/project/search_api_facets_paths - Full release
  19. Semantic Fields - http://drupal.org/project/semantic_fields - dev release

That doesn’t seem to be the full list of helpful SEO modules though. We did another search on the Drupal.org website for just “search engine” and came up with a few more for our list. If you aren’t satisfied with your search results, always try a few more combinations of ways to say what you are looking for our you might miss out on the best results.

  1. Token - http://drupal.org/project/token - Full release, beta
  2. Google Analytics - http://drupal.org/project/google_analytics - Full release
  3. Link - http://drupal.org/project/link - Full release, alpha
  4. XML sitemap - http://drupal.org/project/xmlsitemap - Full release, beta
  5. Global Redirect - http://drupal.org/project/globalredirect - Full release
  6. Search 404 - http://drupal.org/project/search404 - Full release
  7. Nodequeue - http://drupal.org/project/nodequeue - alpha release
  8. Site Verification  - http://drupal.org/project/site_verify - Full release
  9. Service Links - http://drupal.org/project/service_links - dev release
  10. Similar by Terms - http://drupal.org/project/similarterms - alpha release
  11. Relevant Content - http://drupal.org/project/relevant_content - dev release
  12. Meta Tags Quick - http://drupal.org/project/metatags_quick - Full release
  13. Google Analytics Reports - http://drupal.org/project/google_analytics_reports - dev release
  14. Menu attributes - http://drupal.org/project/menu_attributes - Full release, RC1
  15. Scheduler - http://drupal.org/project/scheduler - Full release

Now we have presented you with 34 Drupal SEO modules that are available in some sort of way for Drupal 7. We have listed each module with their current development status. If you are really in need of one of these modules, you should jump into the module’s issue queue and see if you can help test out some patches or even post some patches yourself.

There are quite a few Drupal 6 SEO modules that haven’t had a proper Drupal 7 release yet. We have compiled a list of these modules based on what SEO modules we found available on Drupal.org through the Apache Solr search results. You will see that some great Drupal SEO modules are still not available for Drupal 7.

  1. SEO Friend - http://drupal.org/project/seo_friend - Waiting for Metatags module
  2. Sub-path URL aliases - http://drupal.org/project/subpath_alias - soon to be subpathauto
  3. Content Analysis - http://drupal.org/project/contentanalysis - no response on D7 port
  4. Content Optimizer - http://drupal.org/project/contentoptimizer - no response on D7 port
  5. Glossify Internal Links - http://drupal.org/project/glossify - port testing
  6. Keyword Research - http://drupal.org/project/kwresearch - no data
  7. Keyword Analysis - http://drupal.org/project/kwanalysis - no response yet
  8. View Alias - http://drupal.org/project/view_alias - not sure
  9. Keywords - http://drupal.org/project/keywords - not sure
  10. Alchemy - http://drupal.org/project/alchemy - wants to port, but not until December
  11. Drupal SEO Tools - http://drupal.org/project/seotools - no answer in issue queue
  12. Readability Analyzer - http://drupal.org/project/readability - waiting for port
  13. Link Intelligence -  http://drupal.org/project/linkintel - not sure
  14. Scribe SEO Analyzer - http://drupal.org/project/scribeseo - not sure
  15. Views 404 - http://drupal.org/project/views404 - patch available, needs testing

So there you also have 15 modules that need to get updated to Drupal 7 yet. If you are looking to see these modules in Drupal 7, try submitting patches, helping out in the issue queues for these modules, or testing dev releases for module maintainers. Every little bit helps!

We have a bit of work to do to make Drupal 7 as search engine friendly in contributed modules, but it’s fair to say that some great work has been done so far by people like Dave Reid, Greggles, and Ben Finklea to get modules out there for Drupal 7 that people really need for Drupal SEO. Aside from that, Drupal 7 includes the RDF module, which adds rich semantic markup to all of Drupal 7’s content. This helps tremendously for search and accessibility. It will be interesting to see what other great search engine optimization modules come out for Drupal 7 and beyond.

Stay tuned as we dive further down the Drupal SEO rabbit hole and show you how to install and configure some of the top Drupal 7 SEO modules you need for your Drupal website. Until then, we hope that this article helps you gain better search engine rankings on your Drupal 7 website through the lists of Drupal 7 SEO modules we have provided you with.

Apr 05 2011
Apr 05

Ever needed to produce functionality in Drupal that multiple modules came really close to providing — but none of them seemed to get it quite right? We recently experienced this issue when needing to create an advanced search page in Drupal 7 for a client. We needed the ability to create pre-filtered result pages from essentially an empty query, displaying everything in a default result that the user could then continue to filter or search within, as needed. This was a strict UI requirement we faced, so we had to rule out what otherwise might have been reasonable alternatives, such as using normal Views with exposed filters. That Solr-like experience was essential.

We knew we needed facets, and we knew that Apache Solr would fit that bill nicely. But we also needed a way to make our own pre-filtered pages as a starting point. Search API would fulfill that need, but to use Search API would require working with entities for the results — and Search API is also facing some refactoring that we wanted to avoid having to compensate greatly for.

Well, if Views alone wouldn't match the interface requirements, what about Views in Apache Solr? Sadly, Views support isn’t in Apache Solr for Drupal 7 yet. So we had to go back to the drawing board and, keeping simplicity in mind, find a way to solve our client's basic requirements.

After having the opportunity to meet with Peter Wolanin, one of the co-maintainers of Apache Solr, it became apparent that we may not even need to port, or integrate into the main Apache Solr project, Apache Solr Views to solve our issue.

Apache Solr PagesApache Solr Pages extends Apache Solr pre-filtered result pages, displaying everything in a default result, with exposed facets.

Applying the logic of creating the simplest solution to fulfill our needs in several hours of late-night development I was able to repurpose another Search API feature, the searchapi_page module, and use it in the context of Apache Solr. This gains us a few distinct advantages:

  • We are able to create the multiple pre-filtered pages we need for our use case.
  • We don’t have to rely on the overhead and complexity of using views to build our Solr query.
  • We’re indirectly able to provide an extension use case in Drupal 7 for Apache Solr module.

The Apache Solr Pages module [corrected URL] is still in need of additional work and a lot of cleanup to remove all of the legacy bits that were carried over from Search API; however, it is presently working for our basic use case. The following features actively need additional help to bring the module to a product-ready release:

  • Apache Solr’s “Current Search” block needs to receive proper integration, with the pre-defined filters being hidden or locked in with disabled fields per the administrator’s choice.
  • This also provides a chance to look into ways to better allow the Current Search block to be extensible by other modules upstream in Apache Solr.
  • View modes that were in Search API’s rendition of pages aren’t supported here; Search API code that allowed this is still in the module but needs refactoring to work.
  • Paging is currently broken due to the difference in how Search API and Solr return results.
  • Need to apply Apache Solr’s “on empty” effect, or allow it to be overridden on a page-by-page basis.

The Drupal 7 branch of Apache Solr Pages is available for download today, and I look forward to seeing more input from the community not just around this module, but around search in the future of Drupal in general.

Nov 19 2010
Nov 19

Most CCK Field modules have a widget where the user adds information upon creating a node which is then saved with the node. For the recent Etherpad module I wrote, I needed an "invisible" widget which saved with each new node some information from the field definition as well as autogenerated information. As I didn't any documentation on how to do this, I thought I'd document it here quickly.

The first thing you do is define your database columns for your field in hook_field_settings.

function etherpad_field_settings($op, $field) {
  switch ($op) {
    case 'database columns':
      return array(
        'etherpad_url' => array('type' => 'varchar', 'length' => 1024, 'not null' => FALSE,),
        'etherpad_text' => array('type' => 'text', 'not null' => TRUE, 'size' => 'big'),
        'attributes' => array('type' => 'text', 'size' => 'medium', 'not null' => FALSE),

Next, you define your widget form inside hook_widget. Some tutorials I saw suggest you define your widget form in hook_elements/hook_process. I did that at first but decided against it as a) I never got it to work and b) it just adds needless complexity. Generally you'll just want to define your widget in hook_widgets.

Two really important things here to get your "invisible" widget to work correctly. First, you must name your form keys the same as you named your database column names in hook_field_settings. This tripped me up for a long time. CCK saves data by magic (you never explicitly save anything from a widget) and this is the key to getting the incantation to take. Second, using the "value" field type was the key to creating an "invisible" field and getting my data saved correctly.


function etherpad_widget(&$form, &$form_state, $field, $items, $delta = 0) {
  $element['etherpad_url'] = array(
    '#type' => 'value',
    '#value' => (isset($items[$delta]['etherpad_url']) && !empty($form['nid']['#value'])) ? $items[$delta]['etherpad_url'] : $field['etherpad_url'] . etherpad_generate_padid($field['etherpad_url']),
  $element['etherpad_text'] = array(
    '#type' => 'value',
    '#value' => (isset($items[$delta]['etherpad_text']) && !empty($form['nid']['#value'])) ? $items[$delta]['etherpad_text'] : "default value for now until we have a function to generate one",
  $element['attributes'] = array(
    '#type' => 'value',
    '#value' => (isset($items[$delta]['attributes']) && !empty($form['nid']['#value'])) ? $items[$delta]['attributes'] : serialize($field['attributes']),
  if (empty($form['#parents'])) {
    $form['#parents'] = array();
  $element['_error_element'] = array(
    '#type' => 'value',
    '#value' => implode('][', array_merge($form['#parents'], array('value'))),

  return $element;

And that's it! Read this and you'll save yourself hours of frustration :)

One other note, the Devel module's "reinstall module" function is very useful as you'll be reinstalling the module often to reset the database w/ your changes. Enable the Devel block to access it.

This documentation doesn't cover most of what you'll need to know to write a CCK module. I relied heavily on the following tutorials.

Nov 12 2010
Nov 12

Hooks is the central mechanism which allows Drupal its extensibility. New functionality can interact with or extend existing functionality using hooks. Use hook, don't hack is a standard way to write code in Drupal.

user_hook() is a hook which is called when an activity is performed on the user. e.g. A user logs in, logs out, clicks on user profile, etc.. 

In Drupal 6, user_hook is a single hook and there are operations accessible through $op for accessing the operation that was performed. The documentation is available here.

But in Drupal 7, this will change. The $op is gone and there are different hooks, depending on what operation is performed. List of available hooks are here.

There might be different repercussions of this:

First the big switch will not be required, making the code simpler from it is in Drupal 6

However, with one hook a dsm could always print which operations are called for a given operation. That will be harder to track now. A developer would need to implement different hook to figure out which ones get called on certain user related activities. It will be interesting to see what coding pattern emerges.

However, the documentation is very good and its intuitive to know which hook should be called, but still sometimes it can be hard to tell without a generic method.

Feb 28 2010
Feb 28

If you have ever hosted a reasonably good site on a shared hosting service then you would definitely have come across the dreaded "exceeded the email limit per hour" warning. If you use Drupal then you don't have to worry about this any more. If you are using Drupal then all you have to do is to install the MailQ module to queue all your mails.

Once the mails are queued, they will be processed later during cron runs where the queue will be emptied in batches of size set by the MailQ module. You can set the batch size based on the frequency of cron runs and the limit on the number of emails per hour allowed by your hosting provider. Normally, shared hosting providers also sets limits on the frequency of cron jobs as well. Whatever be the limits you have the system fully under your control and you do not have to worry about overshooting your email limits if you use the MailQ Module

Post your comments / questions

Jan 25 2010
Jan 25

I was trying to create different tabs (using YUI) to edit a form. I wanted to create a separate tab for each of the field groups. However, in the form_alter method of the form for my module, I could not see the fields in the fieldgroup. On debugging I found my fields in the fieldgroup to be present in the form_alter of other modules. Problem: The CCK fieldgroup module has a weight of 9. If your module has a weight less than 9, then it is called before CCK fieldgroup, hence the problem. Solution: Set your module's weight more than 9. The setting is in the system table, under the column weight. This fixed the problem for me. It took a long time to solve the problem and thanks to some of the other posts mentioned below for writing about this.

Dec 19 2009
Dec 19

There are several modules I have used during building sites. I am not going to get into details of the modules because you should visit the modules. But by far, the most important / useful modules for me have been:

1. Views ; You can think of views as output to your custom query (except you don't write the query). There are several ways to present the views and Calendar is one example. So this is a query builder which can execute queries at run time and present the data however you want.

2. : You can add custom fields to a node or define a new content type based on CCK, This is powerful functionality with no coding. You can order the fields according to your preference. And CCK will become very powerful once is introduced. As of now, Multigroup is in alpha, but I have been using it with no problems. It lets you create a composite or a compound field, consisting of different base CCK fields.

3. : The module renders all administrative menu items below 'administer' in a clean, attractive and purely CSS-based menu at the top of your website. This is a life saver if you are administering a site. Essentially it is a overlay of the entire admin functionality as a ribbon on the top of your web site.

4. : I have to give it to katrib for this module. This is great if you want spreadsheet functionality in your website. We did some pretty advanced things with the module like embedding it within a node as a tab and YUI integration. We also configured a java bridge to be able to upload excel sheets from desktop to the website. Google spread sheet integration is pretty straightforward. This is based on SocialText platform

5. Enables users to create and manage their own groups (like forums). This can bring great social aspects to your website. For some of the sites, we changed the module to represent a company and it was great.

6. : This adds a lot of umph to the site. It is Mainly used to showcase featured content at a prominent place on the frontpage of the site. Demos and tutorials are excellent.

7. : Essential for developers and themers It can generate SQL query summaries, create data for your test site, show the theme information on your site. Don't develop without this module.

8. Pathauto : It automatically generates path aliases for various kinds of content (nodes, categories, users) without requiring the user to manually specify the path alias. Helps get rid of default / ugly paths (node/3 ... )

9. jQuery : jQuery depends on jQuery UI and jQuery update in drupal 6. And here is a good overview of jQuery.This architectural diagram might also be a useful reference. jQuery modules provides all the nice functionality jQuery library.

10. : This module provides several useful extensions to the login system of drupal. What I found really useful was to allow email based logins, email confirmation during registration and auto logout. Happy drupaling :)


About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web