May 29 2016
May 29

On a previous post I explained how we are using BigPipe in Drupal 7 (Cheap Pipe (sort of BigPipe) in Drupal 7). Besides all the known benefits of big pipe, there is a less known side effect that might help you fight spam.

Those out there fighting for conversion optimization know that captcha based form protection is a conversion killer (even with the new NoCaptcha from Google). That's why you should always be looking for ways to protect your web application from bots without real users noticing or their workflows being affected.

Even non-intrusive method such as Honeypot or Hidden Captcha are becoming less effective as bots get more sofisticated.

For us, what has been working very well historically against SPAM is using real e-mail verification when capturing cold leads.This basically consists in trying to deliver a fake message to the e-mail address submited to the form. Addresses used by SPAM bots usually do not exist or have been throttled by the e-mail provider. Of course, e-mail verification is the last stand after being able to go through a set of non intrusive form protection techinques (such as honeypot and/or hidden captcha).

A recent change in one of our customer's applications resulted in an increased number of fake leads being sent to Sendy that were able to pass e-mail verification as they were using valid and not throttled e-mail addresses. If you don't know what Sendy is, it's a self-hosted "simple Mailchimp" that can bring massive savings to e-mail based marketing.

So we decided to  force BigPipe on the block that renders the new lead capturing form, and SPAM submissions stopped inmediately. This makes some sense. Content that is rendered using BigPipe is loaded into the DOM through AJAX. I guess that - for performance reasons - most bots probably don't use a full emulated browser and rely on parsing/scanning the HTML response from the server to perform automatic form submissions. What used to be a plain rendered form, is now this to the eyes of the bot:

May 28 2016
May 28

The Drupal community is very special because of its culture of adapting to change, determination and passion, but also its fun and friendship. It is a combination that is hard to come by, even in the Open Source world. Our culture enabled us to work through really long, but ground-breaking release cycles, which also prompted us to celebrate the release of Drupal 8 with 240 parties around the world.

Throughout Drupal's 15 years history, that culture has served us really well. As the larger industry around us continues to change -- see my DrupalCon New Orleans keynote for recent examples -- we have been able to evolve Drupal accordingly. Drupal has not only survived massive changes in our industry; it has also helped drive them. Very few open source projects are 15 years old and continue to gain momentum.

Drupal 8 is creating new kinds of opportunities for Drupal. For example, who could have imagined that Lufthansa would be using Drupal 8 to build its next-generation in-flight entertainment system? Drupal 8 changes the kind of end-user experiences people can build, how we think about Drupal, and what kind of people we'll attract to our community. I firmly believe that these changes are positive for Drupal, increase Drupal's impact on the world, and grow the opportunity for our commercial ecosystem.

To seize the big opportunity ahead of us and to adjust to the changing environment, it was the Drupal Association's turn to adapt and carefully realign the Drupal Association's strategic focus.

The last couple of years the Drupal Association invested heavily in to support the development and the release of Drupal 8. Now Drupal 8 is released, the Drupal Association's Board of Directors made the strategic decision to shift some focus from the "contribution journey" to the "evaluator's adoption journey" -- without compromising our ability to build and maintain the Drupal software. The Drupal Association will reduce its efforts on's collaboration tools and expand its efforts to grow Drupal's adoption and to build a larger ecosystem of technology partners.

We believe this is not only the right strategic focus at this point in Drupal 8's lifecycle, but also a necessary decision. While the Drupal Association's revenues continued to grow at a healthy pace, we invested heavily, and exhausted our available reserves supporting the Drupal 8 release. As a result, we have to right-size the organization, balance our income with our expenses, and focus on rebuilding our reserves.

In a blog post today, we provide more details on why we made these decisions and how we will continue to build a healthy long-term organization. The changes we made today help ensure that Drupal will gain momentum for decades to come. We could not make this community what it is without the participation of each and every one of you. Thanks for your support!

May 27 2016
May 27

Serving Drupal’s opportunity

The release of Drupal 8 creates many opportunities for organizations worldwide to build something amazing for complex web solutions, mobile, SaaS, the Internet of Things, and so much more. The Drupal Association is excited to work with the community to create these opportunities.

In our mission to support the Drupal Project, the Association unites our global open source community to build and promote Drupal. We do this primarily by using our two main resources:, the center of our community’s interactions, with 2 million unique visitors a month; and DrupalCon, which hosts over 6,000 attendees a year and provides the critical in-person acceleration of ideas.

Both foster the contribution journey that makes amazing software, and the evaluator’s adoption journey that encourages people to use Drupal across industries to create amazing things. As I mentioned in my recent blog post, achieving our mission helps the community thrive into the future and realize their Drupal dream.

With the release of Drupal 8, we have an opportunity to reflect on how the Association leverages these assets to work for Drupal’s current and future opportunities. Working with our board of directors, we determined that the Association needs to:

  • Re-assess the Project’s needs, and find new ways to support and meet those needs
  • Address a structural issue, to be a more sustainable organization

To do this, the Drupal Association board and I made hard choices. Having invested heavily in supporting the Drupal 8 release and exhausting available reserves, we recognize that the Association now must right-size the organization and balance our income with our expenses. The biggest impact is the elimination of seven positions, reducing our staff size from 24 to 17 employees. Also as part of this reduction, we have reorganized staff to better address the Project’s needs now that Drupal 8 is released.

While we do have our eye on a bright future for the Project through these changes, we’re also painfully aware that we’re not just eliminating positions. We’re saying goodbye to seven people who are important to us—whose contributions we value more than we can describe. We’re impacting the lives of people we care about—people who’ve given a lot to the Project and to others in our community.

Making the Drupal Association sustainable

In early 2014, the Association began investing reserves in building an engineering team for two main reasons: to address critical issues that were slowing down the production of Drupal 8, and to modernize In doing so, we purposefully created a structural deficit, with the hopes that we could grow revenue to meet the cost of this investment before we drew down our reserves.

Because of this investment, we were able to accelerate the release of Drupal 8 through a roadmap of features like semantic versioning, DrupalCI (continuous integration testing for the projects we host), better search and discovery capabilities, numerous issue queue improvements, and issue credits, all of which positively impacted the release of Drupal 8. In addition, the engineering team has addressed years of technical debt and incorporated more modern services in the site that have made it more reliable and faster around the world.

While revenue grew from 2014 to 2015 by 14%, it didn't grow enough. Last year, we acknowledged that we did not meet the revenue goals that would sustain this investment. We addressed it with a retrenchment designed to extend our runway and see if we could increase revenue sufficiently. All told, while we have accomplished both revenue diversification and growth, it wasn’t enough to fully replace the investment. Then in spring 2016, several things happened on the revenue front that created a significant budget gap:

  • Sponsored work: The Association funded Engineering resources by accepting sponsored work to build Composer endpoints for Drupal projects. After that project was completed, we were unable to line up an additional sponsored project to continue underwriting the Engineering team.
  • The Connect Program: This new experimental program designed to connect software companies with service providers for partnership and integration opportunities did not meet its revenue goals.
  • DrupalCon: DrupalCon New Orleans ticket sales did not reflect the increase we were expecting this year, and we have revised our DrupalCon Dublin ticket sales projections accordingly.

Chart: 2010-2016 revenue and expense trend

"CAGR" means compound annual growth rate.
2016 data is projected revenue and expenses.

Addressing this structural deficit required a reduction of both labor and non-labor expense. Labor is our biggest cost, and we can’t create alignment without cutting roles at the Association. Holly Ross, our Executive Director, Josh Mitchell, CTO, and Matthew Tsugawa, CFO, offered to step down and contribute their salaries to the reduction, as they saw that a smaller organization doesn’t require a full leadership team. Additionally, we are losing three staff members from the Engineering team, one from the Events team, and one from the MarComm team. We are working with these staff members to help them through their transition.

Our second biggest expense is rent. We are working to eliminate the physical office in Portland, Oregon—moving staff to a virtual, distributed team—but those efforts will likely not introduce savings until 2017. We already work with distributed staff and community members around the world, so we have the know-how and tools like Slack and Zoom in place to support this change when it happens.

While these staff reductions are painful today, they correct the structural problem, bringing expenses in line with income. We have conservatively reforecasted revenue to reflect any impact this staffing reduction may have. We can see with our forecasts that the layoffs result in the Association being on healthy financial ground in 2017.

What happens next?

Leading up to now, we invested in tooling to help the community release Drupal 8. Now that Drupal 8 has shipped, the Project has new needs, which are:

  • Promote Drupal 8 to grow adoption
  • Sustain so the community can continue to build and release software is our strongest channel for promoting Drupal, given that it’s the heart of the community and organically attracts hundreds of thousands of technical decision makers. It provides the biggest opportunity to guide evaluators through an adoption journey and amplify Drupal’s strength in creating new business opportunities through solutions like “DevOps and Drupal” or “Drupal for Higher Education.” These new services on will help evaluators, create value for our partners, and increase revenue for the Drupal Association.

We can also use to better promote DrupalCon. It’ll help grow ticket sales and attract more community members to that special week of in-person interaction, accelerating their adoption and contribution journeys.

Additionally, we’ll expand our efforts to attract more evaluators to DrupalCon. We can accelerate their adoption journey through peer networking and programming that helps them understand how Drupal is the right solution for their organization. We do this today with our vertical-specific Summits (like the Higher Education Summit) and we can do more through relevant sessions and other special programming. And while the Drupal evaluators are there, we’ll connect them with Drupal agencies who can help them realize their Drupal vision.

One thing about our work won’t change: our commitment to the tools you use to build Drupal every day. Though the Engineering team is smaller after today, they will make sure the tools and services you need to build and release the software are supported. That includes things like the issue queues, testing, security updates, and packaging.

Right now, we’re focused on the team as we go through this transition. Once the transition is complete, we’ll be looking at the Project needs and making sure we align our work accordingly. When we make changes, we’ll be sure to keep the community updated so you know what our primary focus is and how we are working towards our vision of Drupal 8 adoption across many sectors.

In the meantime, I invite you to tell me your thoughts on this new focus and how the Drupal Association can best help you.

May 27 2016
May 27

Any time there are major new versions of software, some of the tooling surrounding the software requires tweaks before everything works like it used to, or as it's documented. Since Drupal 8 and Drush 8 are both relatively young, I expect some growing pains here and there.

One problem I ran into lately was quite a head-scratcher: On Acquia Cloud, I had a cloud hook set up that was supposed to do the following after code deployments:

# Build a Drush alias (e.g. [subscription].[environment]).

# Run database updates.
drush @${drush_alias} updb -y

# Import configuration from code.
drush @${drush_alias} cim vcs

This code (well, with fra -y instead of cim) works fine for some Drupal 7 sites I work on in Acquia Cloud, but it seems that database updates were detected but never run, and configuration changes were detected but never made... it took a little time to see what was happening, but I eventually figured it out.

The tl;dr fix?

# Add --strict=0 to resolve the error Drush was throwing due to alias formatting.
drush @${drush_alias} updb -y --strict=0

# I forgot a -y, so Drush never actually executed the changes!
drush @${drush_alias} cim -y vcs

For the first issue, Acquia cloud generates its own Drush alias files, and in all the aliases, it includes some options like site and env. It seems that Drush < 8 would just ignore extra options like those... but Drush 8.x throws an error and stops execution for the current task because of those extra variables. Using --strict=0 tells Drush to squelch any erros thrown by those extra options. Eventually, I'm guessing Acquia Cloud's Drush aliases will be made to be fully-compatible with Drush 8.x, but this workaround is fine for now.

For the second issue, it was just my boneheadedness... if you're running any command that requires a prompt non-interactively (e.g. through an automated system like cloud hooks), you have to add the 'assume-yes' option, -y, just like I used to with fra -y in Drupal 7!

Before, I would get the following error message on every Cloud deployment:

The following updates are pending:

custom module :
  8001 -   Add customizations.

Do you wish to run all pending updates? (y/n): y
Unknown options: --site, --env.  See `drush help                         [error]
updatedb-batch-process` for available options. To suppress this
error, add the option --strict=0.
Unknown options: --site, --env.  See `drush help cache-rebuild` for      [error]
available options. To suppress this error, add the option --strict=0.
Finished performing updates.                                                [ok]

Even though it says 'Finished performing updates', they didn't actually get run. Now it runs the updates without any issue:

The following updates are pending:

custom module :
  8001 -   Add customizations.

Do you wish to run all pending updates? (y/n): y
Performing custom_update_8001                                                                              [ok]
Cache rebuild complete.                                                                                      [ok]
Finished performing updates.                                                                                 [ok]

May 27 2016
May 27

Over the last few Drupal releases, the Webform module has been the standard for creating robust forms and surveys. While this venerable module has served the community’s needs quite well, major releases of Drupal often afford the opportunity to take a fresh look at how common problems are solved, leveraging new technologies and concepts introduced in the release.

Baked into Core

Since Drupal 4.6, Drupal Core has shipped with a basic contact form module that had limited functionality. Finally, the contact module got some much-needed attention in Drupal 8. Contact forms are now fieldable entities, allowing us to build forms with the same fields we build content types, taxonomies, and other entities with.

Building Out the Form

Forms are created and managed by navigating to Structure->Contact Forms in the Admin menu. From here, choose “Add contact form.”

Drupal 8 Contact Form Admin

This takes us to a form for setting the name of the form, email addresses for submissions to be sent to, and optionally an auto-reply message to the submitter. Once saved, we are taken back to the Contact Forms admin page. 

Add Contact Form

This gives us a basic form with Sender Name and Email, a Subject field, and a basic text area for a Message. To add fields to our new form, we need to select the “Manage Fields” option in the Operations dropdown. From here, we can add any of the field types available on the site.

Add fields

Form Display

To customize how the form is displayed, we want to select the “Manage Form Display” option in the Operations dropdown. This will allow us to change the order of the fields for the form, change configurations for each field, and allow us to disable any fields that are provided by default that we don’t want to use.

Form Display Admin

Manage Display

Similar to Form Display, if we want to change the order and display of fields in the submission emails, using the “Manage Display” option will allow us reorder or hide fields from showing in the submission email.

Display Admin
Submission Storage and Export

Everything we’ve covered so far is great if we want to build out a form and start getting submissions by email. However, if we want to save and view submissions in the site or want to export the submissions in bulk, we need to look to some contributed modules to fill in the gaps.

Contact Storage Module

As its name implies, the Contact Storage module addresses the need for a central location from which content editors can review and manage form submissions on the site. The module also provides Views integration as well as some additional customization options for our forms. The default configuration provides these features for us, so we can install the module and start benefitting from it immediately.

Submission Exports

We now have robust forms and a place to centrally store their submissions, with Views giving us the ability to build out lists of submissions. What we’re still missing at this point is a way to download the submissions in bulk, and it’s fairly common to want such an export in a format like CSV that can be loaded into a spreadsheet application. To achieve that, we can put our Views integration to use, along with Drupal 8’s REST Module, and the CSV Serialization module. 

Once these modules are installed, create a new view of Contact Messages and check the “Create a REST Export” option, providing the path we will navigate to trigger the export. Then hit Save and Edit to continue configuring the view.

Create new View

In the format section of the view configuration page, we see the format is set to “Serializer”. Here, we want to configure the settings for Serializer, and select the “csv” format.

View Format Settings

REST Export Style Options

At this point we have a working view that will export all submissions as a CSV. We can leave the view set to show content as “Entity,” which will export all fields for the submission, or we can switch the display to “Fields,” which will allow us to specify the fields we want in the export, and how they are formatted.

With exports now provided by Views, we can create custom exports for specific forms, or we can utilize Exposed Filters and Contextual Filters to provide an export that works for all forms, allowing users to choose how they want the export filtered.

More Form Solutions in Contrib

If we need to provide robust survey forms now, the approach covered here is currently the most stable and ready to implement. If this solution doesn’t meet your use case, it might be worth taking a look at eForm, the Drupal 8 version of the Entityform module introduced in Drupal 7. There is also still some discussion of a Drupal 8 port of the Webform module, so it’s possible with enough interest we could have a few different solutions for providing front-facing forms to end users.

While building forms will be a bit different in Drupal 8 compared to previous versions, the experience is more in line with what we’ve come to expect from building Content Types and other fieldable entities. This provides the opportunity for more flexibility and functionality when building front-facing forms, and the Views integration provides the opportunity to present and export the submitted form data just the way we need.

May 27 2016
May 27

entity metadata wrapper

How many times have you been in a preprocess function or a custom module trying to get the value, or editing an entity? If you’ve had the pleasure to work with Drupal code before, my guess is plenty!

This is a very common process for things like checking against a custom field value to determine layout, send information to a third party API (i.e. client CRM, or analytics tracking) or, like we do here at TAG, include content changes in a release script.

As flexible and powerful as this process can be, dealing with the endless arrays that Drupal provides is tedious and unreliable. Lets look at this snippet of code for example:

$body = $node->body[LANGUAGE_NONE][0][‘value’];

The obvious problem here with getting the value of a node’s body field is the language handling. If at any point the entity gets translated, the code will have to be updated. I also personally think that it’s not very clean.

Thankfully, entity_metadata_wrapper is here to rescue us. This is a entity_api function, so that module will have to be installed and enabled. In your code you can then do the following:

$node = entity_metadata_wrapper(‘node’, $nid); // The first argument is the entity type. The second is the entity ID or the entity object if it’s already loaded.
$body = $node->body->value(); // The body of the node in a much cleaner and maintainable way.

You can also easily set values like this:

$node->body->value =New body value’;

Or even better, by using the setter method:

$node->body->set(New body value’);

Don’t forget to save by using the new save method:


Dealing with a field with multiple values like a list? No problem! Just try this:

foreach ($node->field_list->getIterator() as $delta => $list_item) {
    $label = $list_item->value();

Dealing with entity references? No problem! The referenced entity is "wrapped" as well, and can be treated the same way. Check out this example with a node reference field:

$referenced_nid = $node->node_reference->raw(); // This returns the id of the referenced entity.
$referenced_node = $node->node_reference->value(); // This returns the referenced entity object.
$referenced_title = $reference_node->title(); // The referenced entity’s title.

Overall, you can see how this way of dealing with Drupal entities is much more elegant and effective. It personally saves me a lot of time and the grief of having to look at endless arrays and dealing with undefined index errors.

There is much more to this that can be found on the documentation page here.

As always, don’t hesitate to correct me or ask questions in the comments section. I look forward to hearing your thoughts on the matter!

May 27 2016
May 27

We made it to the finish line of another busy work week!

Thanks for joining us for Episode 9 of The Mediacurrent Friday 5. This week, Community Lead Damien McKenna discusses 5 Tips for Improving Your Site's SEO with the one and only Mark Casias.

He provides some great pointers on the following topics: Submodules, Configuration, Content types, Vocabularies, Users, Oh My!, The Front Page, and Most Important Meta Tags. Watch the video below to learn more.

[embedded content]

Is there a topic that you'd like to learn more about? Send us your thoughts to [email protected] and stay tuned for Episode 10 in two weeks. Have a great weekend!

Additional Resources
How to Improve your Conversion Path Optimization | Blog Post
Mediacurrent's Crash Course in SEO and Drupal | Webinar
SEO Keyword Strategy | eBook

May 27 2016
May 27

A lot of thanks to the commerce guys for contributing the Drupal commerce module to Drupal community, which took drupal to a different level in the CMS world. Its very exciting, Commerce 2.x which is the Drupal 8 version of drupal commerce. As like any other drupal developer / architect, I am also excited about Commerce 2.x

Thank God, I was one of the fortunate ones to attend the Commerce Guys session on DrupalCon New Orleans 2016, the very first session after the release of ‘8.x-2.0-alpha4’  version of drupal commerce. It was an amazing session, which made a lot of things clearer,a lot of unanswered questions were answered by the Commerce guys themselves. Here we are going to discuss about the take away of the Commerce Guys session on DrupalCon New Orleans 2016.

No more Commerce Kickstart in Drupal 8, Why?

No more Commerce Kickstart in Drupal 8,because Commerce 2.x is developed as loosely coupled by using a lot of PHP 5.4+ libraries like tax [tax library], addressing [addressing library powered by Google’s dataset], intl [internationalization library powered by CLDR data], zone [zone management library]. Using composer we can create a new site as like commerce kick start in Drupal 7. For that we have to use the following command.

$ composer create-project drupalcommerce/project-base mystore --stability dev

 The above command will download Drupal 8 + Commerce 2.x with all dependencies to the ‘mystore’ folder. Before running the above command please make sure you have installed composer globally on  your system.

How to install Commerce 2.x on existing site?

For Installing Commerce 2.x in existing Drupal8.x site,  we need to do the following steps.

Step 1: Add the Drupal packagist repository which allows Composer to find Commerce and the other Drupal modules. For that run the following command, 

$ composer config repositories.drupal composer

Step 2: The following command will help us to download the required libraries and modules (Address, Entity, State Machine, Inline Entity Form, Profile).

$ composer require "drupal/commerce 8.2.x-dev"

Step 3: Enable the modules “commerce_product commerce_checkout commerce_cart commerce_tax” , Use drush or drupal console

Read more about the commerce documentation on:

The above steps help you to install the commerce 2.x on the existing site. Moreover  that in Drupal 8 commerce 2.x  requires lot of contrib modules developed and contributed by commerce guys themselves. The following ones are the famous ones.

  1. Inline Entity Form
  2. Address
  3. Profile
  4. State Machine

What is new in Commerce 2.x?

  1. Currency Management :  Integrated the Unicode CLDR project. So it is easy to use the currency inside and outside the US.                                                                                     
  2. Price Formatting: Price format  varies from country to country and language to Country.  Like German(Austria) Vs German(Germany)                                                                       
  3. Taxes: Imports the tax rates automatically on country basis depending upon the product like B2B, B2C, digital or physical products.                                                                           
  4. Stores: Multiple stores in same Drupal Commerce Instance, hence there will be majorly two types of use cases, first one is where User can create their own stores based on their own products. Which means multiple cart from multiple stores, from the buyer’s perspective. The Second one being this, that the Company has billing location in multiple countries.                                                                                                                                
  5. Products: Instead of nodes we hare having Product entity itself. On the production creation page using inline entity to create individual product variations. And those variations holds the SKUs and sets of attributes.                                                                  
  6. Product Attributes: In Commerce 2.x product attributes are its own entities, So it is easy to edit, delete, create new attribute from. Suppose you want to add the attributes to the product variation type,  you have to edit the respective production variation type and select the checkbox under the ‘Attributes’. So it is easy to use different form of modes to display fields.                                                                                                                           
  7. Order and Line Item Types: This will provide the option to have separate order types for different types of products like physical and digital products, event registration, training payment etc. So it s provide different checkout flow, different workflow, different logic  or different experience to the customers.                                                                                  
  8. Order Editing: Order is in step by step. Right columns provide the IP address  and the geo location of the order.                                                                                                            
  9. Add to Cart Forms: In the add to cart forms,we can have the variation attributes fields and line item fields as well. Now we have full control add to cart forms powered by Form display mode and field widget plugin.                                                                                   
  10. Shopping Carts: If you having multiple shopping carts, the ui will help to see and checkout each of them separately.                                                                                        
  11. Shopping Cart block: Easily customizable shopping cart block.                                           
  12. Checkout Flows: You can define your own custom checkout flows.                                    
  13. Improved Checkout UX:  It provides the option to do checkout as a guest user, or can also be registered as a new user while doing checkout.                                                       
  14. Payments: Under active development, Currently integrating Braintree and Authorize.Net as reference implementations.                   


Early in 2017 or even before Commerce 2.x will be fully functional. Commerce 2.x  with Drupal 8 will make a difference in the ecommerce world.

Image credits:

May 27 2016
May 27

Part 1: Architecture
Part 2: Installation & Configuration
Part 3: Video & Playlist Management
Part 4: Including Videos & Playlists in Drupal content

In this multi-part blog series, we are covering the various aspects of the new Brightcove Video Connect module for Drupal 8. Part 1 consisted of an Architecture summary and discussed the Technical approach used during the development of the module. Part 2 detailed the Installation & Configuration steps required to get the module up and running properly. This third part illustrates the management of Videos & Playlists and discusses some of the changes compared to the Drupal 7 version of the module.

Video listing

Once videos have been “imported” from Brightcove or uploaded through Drupal, a listing becomes available in an intuitive interface (with a similar layout to Brightcove’s own Studio interface) located in a tab right next to Drupal’s main Content tab:

Brigthcove Videos list in admin_content

The new listing pages allow you to manage videos in a streamlined manner - something that wasn’t possible in the previous Drupal 7 versions as the video listings were limited and only accessible through an overlay while Attaching a video to a node.

Video upload and edit

When uploading a new video (or editing an existing one), a major improvement over previous Drupal versions is that the upload/edit screen is no longer presented in an overlay - but in the same layer as the other configuration screens:

Add/Edit Brigthcove Video

As can be seen above, tags now include an autocomplete feature. The Related Link URL now also includes autocomplete, letting you search for Drupal nodes:

Autocomplete related link URL

The video upload section has been improved by allowing a wider variety of audio and video container formats, and both the video and image source files can now be replaced with new files on existing assets:

Video upload section

The Availability section has also been improved with a new calendar dropdown:

Video availability section

Finally, not only can videos be uploaded and edited in an efficient manner, but also deleted (deleting Brightcove videos wasn’t possible in the previous Drupal 7 versions):

Video delete

Playlist listing

A listing similar to the Brightcove Video is also available for Playlists:

Playlist listing

Smart Playlist edit

Tags are also autocompleting in the Smart Playlist edit screen as can be seen below:

Smart Playlist tag autocomplete

Manual Playlist edit

Manual Playlists also feature an autocompleting field - this time for the individual videos to be included in the playlist:

Manual Playlist tag autocomplete

Part 4 of this multi-part blog series will demonstrate how to include Brightcove Videos & Playlists in Drupal content.

May 27 2016
May 27

Without further ado, hierbij wat mij opviel aan Drupal modules de afgelopen maand:

1. Hide submit button

Voorkom duplicate content doordat mensen twee maal op de Save button klikken. Deze module zorgt ervoor dat de Save button niet meer dan één keer aangeklikt kan worden, door hem onbruikbaar te maken na de eerste klik.

Download (Drupal 7)

2. Magnific Popup

Maakt automatisch een mooie, snelle galerij met afbeeldingen aan. Met mogelijkheden om de afbeeldingen uit te vergroten op verschillende manieren.

Hij maakt gebruik van de lichtgewicht jQuery lightbox library Magnific Popup en implementeert een Drupal field waarmee je vervolgens afbeeldingen kunt toevoegen aan content.

Download (Drupal 7 & Drupal 8)

3. Mail Verify

Een betere manier om ingevoerde e-mail adressen te verifiëren. De Drupal 8 core verifieert alleen op basis van format, deze module verifieert op een geheel andere manier: hij probeert daadwerkelijk verbinding te maken met betreffende e-mail server om te checken of het ingevoerde e-mail adres ook daadwerkelijk bestaat.

Gebruik deze module niet als primaire bescherming tegen spam, anders loop je kans dat je server wordt ge-greylist. Zet dus voor web formulieren (bv contact, sign-up) bijvoorbeeld Mollom en Honeypot in als primaire spam protectie.

Download (Drupal 8)

4. Search exclude nid

Het kan nodig zijn om bepaalde nodes uit te sluiten van de zoekresultaten in Drupal, simpelweg omdat deze niet relevant zijn.

Download (Drupal 7 & Drupal 8 dev)

5. Facebook Comments Block

Biedt de mogelijkheid om Facebook reacties te laten plaatsen op pagina’s in je Drupal website. Hier zijn meerdere modules voor beschikbaar, maar deze maakt het je gemakkelijk door zijn eenvoudige configuratie. Deze Drupal 8 module gebruikt tevens het systeempad (node/xx) en niet de url alias, waardoor de reacties blijven staan; ook als je de url alias wijzigt.

Download (Drupal 7 & Drupal 8)

Gerelateerde module: wijzig je de url alias van een Drupal pagina? Zorg dat je de Redirect module geïnstalleerd hebt, zodat die automatisch een 301 -permanent redirect aanmaakt. Op deze manier houd je de SEO van betreffende Drupal pagina in tact.

6. Require Login

Zorg ervoor dat jouw complete Drupal website afgeschermd wordt: alle bezoekers moeten inloggen voordat zij content te zien krijgen. Handig voor een Drupal social intranet, of voor het afschermen van testomgevingen.

Download (Drupal 7 & Drupal 8)

7. Dynamic Entity Reference

Een Drupal module waarmee je een entity reference field kan aanmaken waarmee je kunt refereren naar meerdere entity types in plaats van slechts één.

Download (Drupal 7 alpha & Drupal 8 rc4)

8. Field Hidden

Biedt de mogelijkheid om een ‘hidden’ veld toe te voegen: < input type="hidden" / >. Bezoekers zien dit veld niet, waardoor je het kunt gebruiker om verborgen informatie in formulieren mee te geven. Meestal is dit systeeminformatie.

Download (Drupal 7 & Drupal 8)

9. Double field

Soortgelijk aan de Field collection module, maar dan lichtgewicht: splits je veld op in twee delen. Een voorbeeld waarom dit handig kan zijn:

Download (Drupal 7 & Drupal 8 rc1)

10. Classy paragraphs

Soms wil je een optioneel een extra class toevoegen aan een specifieke paragraaf in een stuk Drupal content, zodat het de juiste styling krijgt. Maar je wilt je content managers niet vermoeien met het schrijven van HTML.

Deze module biedt de oplossing: hij genereert een extra knop in de tekst-editor, waarmee Drupal een extra HTML class toevoegt op gekozen paragraaf.

Selecteer zelf de styles die je beschikbaar wilt hebben.

Deze module is afhankelijk van de Paragraphs module.

Download (Drupal 7 beta1 & Drupal 8 alpha1)

11. Supercookie

Binnen de Drupal core is het lastig om álle unieke gebruiker te tracken, voornamelijk als zij allemaal uit één gebouw (en dus één IP) je Drupal website bezoeken. Dit komt door de manier waarop de Drupal core omgaat met sessions en cookies.

Deze module implementeert een andere manier voor Drupal om met cookies om te gaan, waardoor wél alle unieke gebruikers van je Drupal website te tracken zijn.

Voornamelijk voor marketing doeleinden kan deze informatie handig zijn.

Download (Drupal 7 & Drupal 8)

12. Serial field

Voeg een veld toe waarin de numerieke waarde automatisch oploopt, los van Drupal’s ‘node id’ autonummering. Dit kan handig zijn voor bijvoorbeeld factuurnummers. Dit veld kan gedeeld worden tussen verschillende content types; de waarden zullen uniek blijven, dwars door die content types heen.

Download (Drupal 7)

Wrap up

Alrighty, that's it voor nu. Volgende maand weer een aflevering van 'coole Drupal modules', so stay tuned!

May 27 2016
May 27

Easy Drupal Development with Drush ScriptingWhether you work on one Drupal site or multiple, it is often necessary for your local dev environment to be slightly different from your site's server.  Perhaps you need to disable Secure Pages because you don't want to set up SSL on your local environment, or there are modules specific to your website's server config.  If you work on multiple sites in a sporadic fashion its possible you need to synchronize your local database with the dev server between tasks, that way you aren't missing any updated configurations.

Sure, you can pull this off manually by grabbing the database, reloading your local, and updating your Drupal site's config; but why not add a little automation to help out?

Using a Shell Script with Drush

Recently I was setting up a local environment and had the opportunity to use a script created by Colan Schwartz. If you are running Linux or OSX then you can easily use this script and modify it to your own needs.  If you haven't done much shell scripting, or you use an alternative OS such as Windows, you may want to get a quick overview from

Now that you're an expert on shell scripting you should check out Colan's very well documented script on gitlab. You may need to update the command path variables

# Set command paths.

Also, the default USER_WEB settings may be incorrect for you setup and your web server user is not one of: php-fpm, nginx, apache, or www-data.

The MODULES_DISABLE variable controls what modules are disabled on your local environment, and you can modify MODULES_ACQUIA and MODULES_ADVAGG with your own variables and module lists.  

If you'd like to test out the script make sure you have a backup of your code and databases.  Once you get the base settings adjusted for your setup, updating the settings for subsequent sites will be quite easy.  Running the script executes the following commands:

  1. Saves a cache-cleared dump of the destination database (DB) as a backup.
  2. Overwrites the destination DB with the source's.
  3. Updates the DB schema.
  4. Imports the latest configuration saved in code.
  5. Disables modules that shouldn't be enabled during development.
  6. Enables modules that are helpful for development.
  7. Clears all caches.
  8. Overwrites the destination's files directory with the source's.
  9. Runs cron.

I hope this helps your development workflow, if you were able to adjust the script for your specific setup please share your results.  Happy scripting!

Some additional items:

If all you need to do is rebuild your local dev environment then check out this cool project which turns the process into a simple drush command: Drush Rebuild.

Here are a few other scripts that you might find useful or inspirational:

May 26 2016
May 26

By Steve Burge 26 May 2016

How to Build a Drupal 7 Jobs Site

This new class, "How to Use the Bootstrap Framework", teaches you how to use the world's most popular design framework in the world.

Bootstrap is an HTML, CSS and Javascript framework that allows you to create clean-looking websites.

Bootstrap provides pre-built code that solves many of the tricky elements, such as responsiveness, that slow down web projects.

This class is the perfect introduction for anyone who wants to start using Bootstrap.

These videos will show you how to use Bootstrap's grid system, and responsive features. You'll also learn how to customize forms, menus, buttons and text.

Start a free trial!

Intro video for the Bootstrap Class

How to take the Bootstrap Class

If you're already an OSTraining member, you can click here to take the Bootstra Class.

Start a free trial!

About the author

Steve is the founder of OSTraining. Originally from the UK, he now lives in Sarasota in the USA. He was a teacher for many years before starting OSTraining. Steve wrote the best-selling Drupal and Joomla books.

May 26 2016
May 26

At the end of 2012, Larry Garfield wrote a blog post entitled “Getting Off the Island in 2013,” in which he speculated that, in order to stay relevant, Drupal needed to adapt and become more open. My interpretation of the post was that although Drupal has always been open source, in many ways its community had been closed off, sometimes ignoring the larger web development community. Garfield’s post was poignant, even prophetic—that was four years ago. Today, Drupal 8 is gaining steam: it has incorporated many components of the Symfony framework and discussion about including a new, more robust, Javascript framework in core is a hot topic. Drupal is reinventing itself, and in doing so it’s securing its position as the go-to CMS.

That’s why when I saw the new Horizons track in the Drupalcon NOLA program this year, I was stoked. The creation of the interdisciplinary Horizons track represents a shift in the Drupal community towards supporting and adopting and learning from technologies that are changing the way we build websites. It’s a way for the community to “get off the island” and see what’s going on in other areas of our industry.

One of my favorite sessions in the Horizons track was “Amazing User Experiences with Drupal and Ember,” in which Ed Faulkner showed how the power of Ember.js with Drupal makes seemingly complex features very approachable. His live demos showed how with Ember.js a few lines of Javascript could create a user experience that feels like the future. Likewise, in “Elm - Frontend with Guarantees,” Amitai Burstein explained how the Elm language brings the benefits and predictability of functional programming to front-end development. If it compiles, it just works!

The best part of these sessions was that the presenters resisted the temptation to dogmatically bash Drupal, avoiding terms that have become low-grade insults like “monolithic” and “tightly coupled.” Instead, they showed that other frameworks, tools, and techniques can pick up the slack when Drupal falls short—Ember, React, Angular, Elm, and even GraphQL can have a place in the Drupal ecosystem.

Having worked with Drupal since 2010, I’ve had the opportunity to see it grow and evolve over the years. From my humble beginnings integrating with SOAP services (remember those?), to implementing complex SPAs (Single Page Applications) with Backbone.js and RESTful webservices with Node.js, my work with Drupal has always happened at the “messy edges,” as the DrupalCon program put it so aptly. But I’ve come to find that the most exciting work happens in the “messy edges”—When you begin pushing a piece of software to its limits, you know you’re building something exciting; it’s part of what makes web development interesting.

So, I have high hopes for the Drupal project. The Drupal community is self reflective enough to see the flaws in the project and brave enough to reinvent itself—we’ve seen that with Drupal 8. Is there work to be done? Yes. But based on the sessions I saw and the discussions I heard at DrupalCon, I believe this community has what it takes to not only survive, but thrive.

May 26 2016
May 26
I sat down with Ally Gonthier the first time I visited Acquia's then-new downtown Boston headquarters in mid-2015. At the time, she was preparing to leave her job as Support Coordinator at Acquia to enter Acquia's Drupal/tech bootcamp, known as Acquia U. When I returned to Boston in the spring of 2016, I took the chance to talk with her again about her experiences at Acquia U and what had become of her in the meantime. Below is a transcript of our before and after conversations.
May 26 2016
May 26

Drupal 8.1.0 was released on April 20th. (Read the full release notes.) There are a few exciting things about this release. At the top, this is the first time Drupal has done a scheduled feature release using the new semantic versioning and pre-set release schedule. Instead of 8.1, we have 8.1.0, and we got the release out on schedule! (Learn more about the Drupal 8 release schedule and semantic versioning.) This feature release added some CKEditor WYSIWYG enhancements, added some APIs, an improved help page, and two new experimental modules: Migrate Drupal UI and BigPipe.

One of the big advantages to these 6-month feature releases is that we can add new things to Drupal core over time instead of having to wait for the next big version. This means Drupal core will change more over its life than previous versions. One of the downsides of this is that documentation and learning materials may get out of date more quickly. We’re excited about the possibilities of Drupal 8 releases and we’re dedicated to having the most up-to-date and accurate tutorials you can find. To keep on top of things, we are reviewing all of the Drupal 8 releases to see where our tutorials need to be updated, and we’re making sure we stay involved in the core issues and processes so we are aware of big changes that may be coming. This is the most exciting release cycle Drupal has ever had, and we’re loving the energy and the challenge of keeping up with it toe-to-toe. So without further ado, here is a brief summary of the big changes in 8.1.0 and a look ahead at some things that might be coming down the road.


The Drupal 8 BigPipe module provides an advanced implementation of Facebook's BigPipe page rendering strategy, leading to greatly improved perceived performance for pages with dynamic, personalized, or un-cacheable content. This is a huge win for Drupal 8, and will make your sites load super fast. You can see the difference it makes in a short demo video on the BigPipe documentation page. The work on this has been happening for over a year and while it didn’t get into the initial 8.0.0 release, it’s very exciting to see this in Drupal core now. For an in-depth look at BigPipe in Drupal, watch the DrupalCon New Orleans BigPipe session video.


The other big feature in Drupal 8.1.0 is improvements to the migration system, which is how we handle upgrades now. There is now a user interface for running migrations, which was a sorely missing feature. (Though, do keep in mind that more migration improvements need to be made.) There has been a lot of work in this space and we’ve been working on upgrade/migration tutorials for a few months. Part of our delay was the tricky space that the migration in core was in, which made it difficult to ensure we had the most accurate tutorials for coming versions of Drupal core. With the 8.1.0 release knocking we decided to push things along by funding Mike Ryan (creator of Migrate module) to make migrations more solid for 8.1.0, and dedicating some of our own Will Hetherington’s time to assist in the effort.

Specifically, we had Mike spend his time making sure the final core migrate issues for 8.1.0 got guided in, and working to get the Migrate Tools and Migrate Plus contributed modules working well with the new release. This is particularly important since not having these two projects functional would severely limit the usefulness of the Migrate work in core.

Aside from the actual code work that Mike cranked out, we also go 2 great blog posts; one by Mike, Migration update for Drupal 8.1, and the other by Will, Custom Drupal-to-Drupal Migrations with Migrate Tools.

You can also see the fruits of our labor on the Migrate front with the first of several parts for our new Drupal 8 Migration Guide, led by Will.

Drupal 8.2.0

We had our first successful feature release, and 8.2.0 is scheduled for October 2016. It remains to be seen what lands in that release, but we are keeping an eye on important developments. Of course, there is also still room for more improvements to Migrate and so we plan to keep working in the migration space over the coming months. One of the new, interesting things to watch is a project to simplify the theme and render system by using a component library. It's still very much in the planning phase, so we have no idea if it can even possibly make it in to the next version yet. (Here is the main issue on if you want to follow along.) We’re particularly interested here at Drupalize.Me because we have an extensive Theming Guide published and this would definitely be something where we’d need to update our previously published tutorials. Rest assured we’re keeping our finger on the pulse.

May 26 2016
May 26

By Steve Burge 26 May 2016

How to Build a Drupal 7 Jobs Site

This week, we're happy to add a new and much-requested class to the OSTraining library, How to Use the Twig Template Engine.

Twig is a very powerful template engine for PHP. Twig is safe, fast, easy-to-learn and is used by many different platforms. Drupal 8 uses Twig by default, plus we've also come across wonderful examples of Twig being used in WordPress and Joomla.

In this class, you'll learn how to use Twig for your projects.

In the first half of the class, you'll see how to install and configure Twig. You'll then explore Twig's syntax, including filters, comments, math operators and more.

In the second half of the class, you use if/else statements, includes statements and extensions to create powerful and flexible layouts.

Start a free trial!

Intro Video for the Twig Class

How to take the Twig Class

If you're already an OSTraining member, you can click here to take the Twig Class.

Start a free trial!

About the author

Steve is the founder of OSTraining. Originally from the UK, he now lives in Sarasota in the USA. He was a teacher for many years before starting OSTraining. Steve wrote the best-selling Drupal and Joomla books.

May 26 2016
May 26

How to Register an Event Subscriber in Drupal 8Events in Drupal 8 allow for different components of the system to interact and communicate with each other. One system component dispatches the event at an appropriate time; many events are dispatched by Drupal core and the Symfony framework in every request. Other system components can register as event subscribers; when an event is dispatched, a method is called on each registered subscriber, allowing each one to react.

Most of the hooks from previous versions of Drupal were removed in Drupal 8 in favor of Events. Example: hook_init() or hook_boot() which now can be done by registering an event subscriber.

I will use the following structure for the example module:

  - src/
    - EventSubscriber/
      - MyEventSubscriber.php

Standard file for the module:

name: Register an Event Subscriber
type: module
description: 'Example: How to Register an Event Subscriber in Drupal 8'
core: 8.x
package: Other

Define a service tagged with 'event_subscriber' in the

    class: '\Drupal\my_event_subscriber\EventSubscriber\MyEventSubscriber'
      - { name: 'event_subscriber' }

src/EventSubscriber/MyEventSubscriber.php contains a class that implements \Symfony\Component\EventDispatcher\EventSubscriberInterface

 * @file
 * Contains \Drupal\my_event_subscriber\EventSubscriber\MyEventSubscriber.

namespace Drupal\my_event_subscriber\EventSubscriber;

use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

 * Event Subscriber MyEventSubscriber.
class MyEventSubscriber implements EventSubscriberInterface {

   * Code that should be triggered on event specified 
  public function onRespond(FilterResponseEvent $event) {
    // The RESPONSE event occurs once a response was created for replying to a request.
    // For example you could override or add extra HTTP headers in here
    $response = $event->getResponse();
    $response->headers->set('X-Custom-Header', 'MyValue');

   * [email protected]}
  public static function getSubscribedEvents() {
    // For this example I am using KernelEvents constants (see below a full list).
    $events[KernelEvents::RESPONSE][] = ['onRespond'];
    return $events;


Here is a list of KernelEvents constants:

KernelEvents::CONTROLLER; // The CONTROLLER event occurs once a controller was found for handling a request.
KernelEvents::EXCEPTION; // The EXCEPTION event occurs when an uncaught exception appears.
KernelEvents::FINISH_REQUEST; //The FINISH_REQUEST event occurs when a response was generated for a request.
KernelEvents::REQUEST; // The REQUEST event occurs at the very beginning of request dispatching.
KernelEvents::RESPONSE; // The RESPONSE event occurs once a response was created for replying to a request.
KernelEvents::TERMINATE; // The TERMINATE event occurs once a response was sent.
KernelEvents::VIEW; // The VIEW event occurs when the return value of a controller is not a Response instance.

There are more events available. More event constants.

How to dispatch an event

$dispatcher = \Drupal::service('event_dispatcher');
$dispatcher->dispatch($Event_Name, $Optional_Event_Object);

Useful links

May 26 2016
May 26
When you spin up sites for a living, velocity is important. The developers at Acquia understand this, which is why we’re always looking for ways to make website development simpler and easier. Because that equals faster.Many of our customers are already using these tools and practices. But we’d like to spread the word further.We know you’re facing really challenging situations. We’ve got tools that will help you get past them, without taking up an entire afternoon. We can speed you up, and speed up your team.
May 26 2016
May 26

Most people think that using the drush command-line tool is only something hardcore developers do, but it turns out it's also super-helpful for site builders and theme developers too! In my experience, using drush will speed up from 3 to 10 times usual Drupal Admin tasks, compared with visiting the Drupal admin pages in the browser. 

In this article, I'll list the Drush commands I use everyday in my Drupal theme development and site-building process. If you have more of them on your pocket, I will appreciate you comment them as I would love to add them to the list.

As a requirement for executing all of the following commands, you must first ensure to have Drush installed for your Drupal development environment. Fortunately, Acquia Dev Desktop and, Drupal VM, and standard dev environments all come with drush pre-installed.

Without further ado, let's dive into my favourite commands, with both D7 and D8 versions where appropriate.

Clear the Caches

Whether you are loading new template files, adding new libraries or editing your main theme .info file's structure, you will always need a fast Cache clear.

Drupal 7

# run cache-clear on all caches
$ drush cc all

Drupal 8

# run cache-rebuild
$ drush cr

In my personal experience, you may need to clear Drupal Caches between 5 - 15 times a day.

Download and enable any contrib module

With more than 13.000+ Drupal 7 & 8 contrib modules at, that odds are that you're not using one of them are pretty slim! Fortunately, drush makes installing modules from can be done really fast thanks to Drush using the following commands:

Drupal 7 & 8

# Download a module
$ drush dl pathauto

# Enable the module
$ drush en pathauto

Because smart themers are also lazy, they'll be happy to hear that you can do both the download and enabling in a single command:

$ drush en pathauto -y

Keep in mind, every drush command accepts a "-y" argument to skip all yes/no confirmations.

Import & Export Database Backups

The fastest way to backup all your site data is doing a database dump. As a good practice, always clear the caches first, to keep the size of the database "dump file" to a minimum. Depending on the site structure and data, this diference can result in up to a 70% reduction on the SQL dump file size.

Drupal 7 & 8

# Export the DB to a backup file
$ drush cc
$ drush sql-dump > dump.sql

# Delete all data in your database (MAKE SURE YOU TRUST YOUR BACKUP!)
$ drush sql-drop

# Import the DB from a backup file
$ drush sql-cli < dump.sql

Import & Export Site Configuration to Code

Until a site goes live, we do our best to develop without a database dump (Gasp!). When building a new dev or staging environment, we start from an empty databse, and migrate in all our sample content. Then we use either Features module (in Drupal 7) or Configuration Management (in Drupal 8) to import ALL site configuration (content types, fields, views, variables, and everything else) from the code. Here's how drush plays a role:

Drupal 7, using Features module

# Assuming you use Features site wide for Content Types, Contexts, Views...
# Revert all enabled features by overriding current DB config with the features code
$ drush features-revert-all

# Update all feature modules code based on your current DB config
$ drush features-update-all

Drupal 8, using Configuration Management

# Export the configuration to the "config/site" sample folder
$ drush config-export --destination=config/site

# Import the configuration from the "config/site" sample folder
$ drush config-import --source=config/site

Downloading and Enabling the Drupal Theme

As with a module, you could manually visit, downloading the theme, extract it to to the appropiate folder, then visit "Admin > Appearance" to set it. But after you see how easy it is with drush, you'll never do it any other way.

Drupal 7

# Download a theme/module
$ drush dl bootstrap

# Enable the theme/module
$ drush en bootstrap

# List all Installed Themes
$ drush pm-list --type=theme

# Set the theme to be the "default one" or the "admin one"
$ drush vset theme_default bootstrap
$ drush vset admin_theme seven

Drupal 8

# Download a theme/module
$ drush dl bootstrap

# Enable the theme/module
$ drush en bootstrap

# List all Installed Themes
$ drush pm-list --type=theme

# Set the theme to be the "default one" or the "admin one"
$ drush config-set system.theme default bootstrap
$ drush config-set system.theme admin bootstrap

Update Drupal Core + Contrib Modules

Always keeping core and contrib modules up-to-date is the most tedious admin task I know. Turns out that drush has a single command that does everything for you! As a bonus, there's a second command that does a full site archive (code, database, and files) that you can restore from if anything goes wrong!

Drupal 7 & 8

# Export the DB, code, and site into a timestamped and zipped tar archive 
$ drush archive-dump

# Run the entire update process
$ drush up

Generate Sample Content

As described by Blair Wadman in his blog post How to create dummy Drupal content with Drush and Devel, we can create a bunch of dummy nodes to test our Views, Display Modes and see the actual layout in action.

Drupal 7 & 8

# Download and Enable Devel module
$ drush en devel -y

# Enable Devel Generate Sub-module
$ drush en devel_generate -y

# Generate 50 random nodes, with up to 10 comments each
$ drush generate-content 50 10

Other Drush Capabilities...

As mentioned before, these are kind of the most popular Drush commands I use every day, but there's so much more to explore in the following resources:

Gratuitious terrible jokes

Finally, I learned that my colleage Alex Dergachev once did an intro Drush talk at a Drupalcamp Montreal 2010, where he organized his slides around sinister-sounding "Soviet drussia" jokes. We're including these here for posterity.

In Soviet Drussia...

  • Dog watches you
  • Cron executes you
  • Variable gets you
  • PHP evaluates you
  • Core hacks you
  • Module uninstalls you
  • Caches clear you
  • Content manages you
  • Terrible joke ruins you

Let us know if he missed any stinkers.

May 26 2016
May 26

Drupal 7 and below came with an optional module you can use in your input formats - the "PHP Filter". This allows you to put PHP code into the content of your webpages, and Drupal will process the PHP before rendering the page.

PHP Filter - a Bad Idea ™

Put like that, you're probably wondering why on earth anyone would want to do that. The content of a webpage, in a Content Management System (which is how Drupal is often used) should be just that - the content. Only in a manually coded site would you put the website logic (the server-side PHP) in the same place as your content.

Well, precisely. And there are other reasons why it's a bad idea.

1. Security. Any PHP code in a module can be run through various automated or manual checks to make sure you've written good, secure code. Maybe even your webserver runs tools that scan for possible signs of malware. PHP code in your content is buried deep in the database, where it won't get checked.

2. Debugging. If you find a page of your site is not working as it should, you need to identify where things go wrong. It makes the job a lot more complicated if there's PHP code in page content, as well as in the other places where it ought to be.

PHP Filter - a Commonly Used Feature

In spite of this, it's very common for people to use the input filter. Classically, when someone knows some PHP, but is just beginning to learn Drupal, they find some logic they want in their website that they can't work out how to do it. At least, they can't work out the "Drupal way" to do it. So they go for the obvious work-around - put the logic into the Body of whatever page they're creating.

But, eventually, you learn better ways of doing things, and you learn just why the PHP filter is a bad idea, so you want to disable it on your site. Before disabling the "PHP filter" module, you need to make sure that none of your current website content uses it. How do you go about this?

You need to run some database queries to make sure you've caught them all.

Step 1: Find the input formats that use the PHP filter

The PHP Filter is simply one formatter that you can use in an "Input Format" (like "Filtered HTML" and so on). Most people would only enable the PHP Filter in a single text format that they have created especially for this task, maybe named something like "PHP Code". But don't bet on it. Some sites may have enabled the PHP Filter on other Text Formats as well.

SELECT * FROM `filter` WHERE module = 'php' and status = 1

(Note - if you're using a prefix for your tables, you'd obviously need to prefix the table name 'filter'. If you use prefixes, you'll know what I mean, so I'm only going to point this out once in this post.)

This will show you all the input formats that use the PHP filter. In my case, I only had one, and it was Input Format number '2' (look in the 'format' column of what this query spits out.)

Step 2: Find all nodes that use those input formats

We now need to find all nodes that use this input format.

SELECT * FROM `field_data_body` WHERE body_format = 2

or, if you are checking for multiple input formats:

SELECT * FROM `field_data_body` WHERE body_format IN (2, 5)

This will show you all the nodes in your site that use those input formats.

Look at the 'entity_id' column. That will tell you the node ID of each node.

Step 3: Fix those nodes so that they don't use the PHP Filter

Now you need to go to each of those nodes in turn and fix them. They need to be on a different Text Format, one that doesn't use the PHP Filter at all. To load each node, go to, where nnnn is the node ID you just found in the database.

How to get rid of the PHP from the node will depend on why you originally used the PHP code.

It may be that you aren't even using PHP in some nodes, and you can just change the Text Format to a different one, check it still looks OK, and move on to the next node. Or it may be that your PHP use was so simple you can do without it. Sometimes, you may need a module from Drupal's contrib repository, or even a custom-coded module. That's beyond the scope of this guide.

Step 4: Don't forget blocks

Oh yes.

It's just possible (:cough:) that you might have added a custom block to your site, and put some PHP code in there as well.

SELECT * FROM `block_custom` WHERE format = 2

From the results of that query, you can probably find the block in the Blocks Administration screen of your Drupal site.

But, in case you have a lot of blocks, the 'bid' column gives you the block identifier. You can load this page:[bid]/configure, where [bid] is the block identifier you got from your query.

Step 5: Tidy up

That's it. You can now edit the text formats which had the PHP filter in, to either delete them or disable the PHP filter. Then you can disable the PHP Filter module from your site.

Have I missed anything? Are there other common places where PHP code might lurk in the database? Please plug any gaps in the comments section below.

May 26 2016
May 26

What do you get when you put two Project Managers in one hotel room for a week at DrupalCon? A lot of work, a lot of laughter, and a lot of learning. Don’t worry, we didn’t kill each other… yet.

With our days spent in sessions and nights spent on Bourbon Street or answering client emails (not at the same time), DrupalCon New Orleans was a truly illuminating experience. I came to LevelTen a year ago not even knowing what “Drupal” was -- and in the past year I have truly come to understand the power behind the Drupal platform and the community.

My Three Big Takeaways from DrupalCon 2016:

  1. You are not alone in your frustrations.

  2. You don’t know what you don’t know.

  3. Knowledge is power.

You are not alone in your frustrations.

From a Project Management standpoint, this was incredibly helpful to understand: someone else has been through exactly what you’ve been through -- and they didn’t die, either.

In On Inheriting Someone Else's Mess: Lessons Learned from a Rescue Project, Marcus Iannozzi from Message Agency explored the difficulties of taking on someone else’s project. I particularly related to his concept of “wounded trust”: when a client who has had a bad experience worries, not only that you won’t deliver, but that you are actively trying to take advantage of them. Sound familiar? From an inside sales perspective, I deal with this often.

Perhaps the most illuminating part of this session actually came from the Q&A portion. Someone asked if, knowing what he knows now, Marcus would take on this project again. Without hesitation, he said “No.”

Takeaway: Hindsight is always 20/20.

In Becoming a TPM: Dos and Don'ts of Technical Project Management, Jessi Fischer (Pantheon) and Anne Stefanyk (Kanopi Studios) showed an impressive display of cat GIFs as the basis of a comparison of Technical Project Management to herding cats. They discussed that the key to good TPM is to communicate effectively with a non-technical audience and employ strategies for risk mitigation. Don’t leave your developers out to dry, and take responsibility for the team as a whole.

Takeaway: When you put cats in a presentation, I am 1000% more likely to pay attention.

In How To Grow Support To Become A Cornerstone Of Your Business, John Ouellet and Katy Pool from Kalamuna touched on both good and bad clients, while also discussing how to structure support contracts to function as a lead-in to larger projects. Have a tough client? They suggest either learning how to say no, implementing another team member as the PM, or parting ways with the client.

Takeaway: The dreaded “support” contract can be beneficial for your business if you have the right team and the right framework.

You don’t know what you don’t know [and I didn’t know any of this].

In a BoF covering Event Organization & Sponsorship called “Mo Money, Mo Sponsors,” focusing particularly Drupal and other tech Camps, representatives from Pantheon, Acquia, and FFW seemed to agree on one thing: if you want to get your camp sponsored, you need data. This includes who will be attending your event and their demographics, but also a marketing plan that covers how you will be attracting new people to your camp.

Takeaway: Pantheon doesn’t care if you put their name on a shirt or a poster. Offering face time with potential clients or new hires is one of the most valuable things you can offer.

In Recruiting and Retaining Dedicated Volunteers, Stephanie from Amazee Labs covered how to find, train, and retain a great volunteer staff. She made a great Stone Soup analogy that boiled down to this: individually, people may not have much to give as far as talents, availability, or interest, but if you maximize on their desire for something great, you can create it.

Takeaway: Offload enough responsibility on your volunteers so that you can jump in if something goes wrong without causing something else to break.

Knowledge is power.

In GE Energy Connections & FFW: Delivering Business Results Beyond Clicks, Conversions and Revenue, Brent Bice (Agency) and Holly Bounds (Client) teamed up to offer both agency and client perspectives on moving to Drupal. Holly was gracious enough to speak with me for a few minutes afterwards from a sales point-of-view on how they were convinced to move to Drupal and to work with FFW. She mentioned that one of the big pieces that FFW was able to offer was knowledge: for example, teaching her the difference between a configuration and a customization allowed her to prioritize what they needed and cut costs where configurations were sufficient.

Takeaway: The modern client wants to feel empowered, even if you’re doing all the work. Taking the time to teach them certain things can have a large ROI.

My first year at DrupalCon was one for the books -- and not just because of the Pantheon party, or the beignets, or getting soaked in the rain with my teammates. Connecting with hundreds of like-minded people in person really reinforced the community foundations of Drupal for me, and helped me to better understand both the current state of Drupal shops, and the opportunities that we have to grow and change in the future.

Check out the rest of our DrupalCon[densed] 2106 series! No matter who you are, we've got your perspective covered.

May 26 2016
May 26

Raspberry Pi Dramble Cluster with Mini Raspberry Pi Zero Cluster

Another year, another field trip for the Pi Dramble—my 5-Raspberry-Pi cluster! I presented a session titled Highly available Drupal on a Raspberry Pi Cluster at php[tek] 2016, which just so happens to have moved to my hometown, St. Louis, MO this year!

For this presentation, I remembered to record the audio using a lav mic plugged into my iPhone, as well as iShowU to record what was on my screen. Sadly, I didn't have a secondary camera to capture the Pi Dramble itself, but you can glance at all the other 'Let's build a Pi Cluster' videos if you want to see it in action!

Here's a video recording of the presentation:

[embedded content]

And here are the slides:

If you haven't yet seen the Dramble, check out all the details at

It was a fun and lively session, and I thank the php[tek] organizers for allowing me to share my passion for electronics, Ansible, PHP, and Drupal with another great group of people. I'll be giving another talk tomorrow, on a completely unrelated topic, ProTips for Staying Sane while Working from Home.

May 26 2016
May 26

XHProf is a profiling tool for PHP code – it tracks the amount of time and memory your code spends in each function call, allowing you to spot bottlenecks in the code and identify where it’s worth spending resources on optimization. There are have been a number of PHP profilers over the years, and XDebug has a profiler as well, but XHProf is the first one I’ve successfully managed to configure correctly and interpret the output of.

I had run across a number of blog posts about using XHProf + Drupal, but never actually got it to work sucessfully for a project. Because so much of the documentation online is incomplete or out-of-date, I thought it would be useful to document my process using XHProf to profile a Drupal 8 custom module here. YMMV, but please post your thoughts/experiences in the comments!

How to find documentation

I find the XHProf manual entry super-confusing and circular. Part of the problem is that Facebook’s original documentation for the library has since been removed from the internet and is only accessible via the WayBack Machine.

If there’s only one thing you take away from this blog post, let it be: read and bookmark the WayBack machine view of the original XHProf documentation, which is at

Install XHProf in a VM

If you’re not running DrupalVM, you’ll need to install XHProf manually via PECL. On DrupalVM, XHProf is already installed and you can skip to the next step.

sudo pecl install xhprof-beta

Note that all these commands are for Ubuntu flavors of linux. If you’re on Red Hat / CentOS you’ll want to use the yum equivalents. I had to first install the php5-dev package to get PECL working properly:

sudo apt-get update
sudo apt-get install php5-dev

And, if you want to view nice callgraph trees like the one below you’ll need to install the graphviz package sudo apt-get install graphviz

Image of a sample XHProf callgraph

Configure PHP to run XHProf

You need to tell PHP to enable the xhprof extension via your php.ini files. Usually these are in /etc/php5/apache2/php.ini and /etc/php5/cli/php.ini. Add the following lines to the bottom of each file if they’re not there already. You will also need to create the /var/tmp/xhprof directory if it doesn’t already exist.

; directory used by default implementation of the iXHProfRuns
; interface (namely, the XHProfRuns_Default class) for storing
; XHProf runs.

Lastly, restart Apache so that the PHP config changes take effect.

Set up a path to view the XHProf GUI

The XHProf GUI runs off a set of HTML files in the xhprof_html directory. If you’ve been following the install steps above, you should be able to find that directory at /usr/share/php/xhprof_html. Now you need to set up your virtual host configuration to serve the files in the xhprof_html directory.

I find the easiest way to do this is just to symlink the xhprof_html directory into the existing webroot of whatever site you’re working on locally, for example:

ln -s /usr/share/php/xhprof_html /var/www/my-website-dir/xhprof

If you’re using DrupalVM, a separate vhost configuration will already be set up for XHProf, and the default URL is although it can be changed in your config.yml file.

Hooking XHProf into your module code

Generally, the process of profiling a chunk of code using XHProf goes as follows:

  1. Call xhprof_enable()
  2. Run the code you want profiled
  3. Once the code has finished running, call xhprof_disable(). That function will return the profiler data, which you can either display to the screen (not recommended), or…
  4. Store the profiler data to a file by creating a new XHProfRuns_Default(); object and calling its save_run method.

In the case below, I’m profiling a module that implements a few Drush commands from the command line which I’d like to optimize. So I created _modulename_xhprof_enable() and _modulename_xhprof_disable() functions – the names don’t matter here – and then added a --profile flag to my Drush command options which, when it is set to true, calls my custom enable/disable functions before and after the Drush command runs.

Here’s what those look like in full:

 * Helper function to enable xhprof.
function _mymodule_enable_xhprof() {
  if (function_exists('xhprof_enable')) {
    // Tell XHProf to track both CPU time and memory usage
        // Don't treat these functions as separate function callss
        // in the results.
        'ignored_functions' => array('call_user_func',

 * Helper function to disable xhprof and save logs.
function _mymodule_disable_xhprof() {
  if (function_exists('xhprof_enable')) {
    $xhprof_data = xhprof_disable();

    // Saving the XHProf run
    // using the default implementation of iXHProfRuns.
    include_once "/usr/share/php/xhprof_lib/utils/xhprof_lib.php";
    include_once "/usr/share/php/xhprof_lib/utils/xhprof_runs.php";

    $xhprof_runs = new XHProfRuns_Default();

    // Save the run under a namespace "xhprof_foo".
    // **NOTE**:
    // By default save_run() will automatically generate a unique
    // run id for you. [You can override that behavior by passing
    // a run id (optional arg) to the save_run() method instead.]
    // .
    $run_id = $xhprof_runs->save_run($xhprof_data, 'xhprof_mymodule');

    echo "---------------\nAssuming you have set up the http based UI for \nXHProf at some address, you can view run at \n$run_id&source=xhprof_mymodule\n---------------\n";

The echo command here works fine for a Drush command, but for other tasks you could log the run url using watchdog.

Note: Another way to run XHProf on a Drupal site is using the XHProf module, but I haven’t had great luck with that.

Viewing profiler results

If everything is configured correctly, when you run your module you should get a run ID output either to the screen (via echo, as above, or however you’ve configured this logging). Visit the URL you configured above for xhprof, and you should see a list of all the stored runs. Clicking on a run will bring up the full profiler report.

Sample screenshot of an XHProf profiler report

Now what?

Now you’ve got all this data – how to make sense of it? What to do with it? Stay tuned for more discussion of how to interpret XHProf results and a real-world example of profiling a D8 module, next week!

About the author

Tim Stallmann

Recent posts by Savas

May 20, 2016

The ins and outs of the talks, sessions, parties, and more from Drupalcon New Orleans 2016.

Apr 20, 2016

A peek under the hood at our website’s commenting app, Squabble.

Mar 22, 2016

Savas Labs will host 4 lightning talks at the American Underground @Main for the next TriDUG meetup.

May 25 2016
May 25

The Aaron Winborn Award was created in 2015 after the loss of one of one of the Drupal community’s most prominent members, Aaron Winborn, to Amyotrophic Lateral Sclerosis (also referred to as Lou Gehrig's Disease in the US and Motor Neuron Disease in the UK). Aaron’s commitment to the Drupal project and community made him the epitome of our unofficial motto: "Come for the code, stay for the community". The Community Working Group with the support of the Drupal Association came together to honor Aaron's memory by establishing the Aaron Winborn Award, which annually recognizes an individual who demonstrates personal integrity, kindness, and above-and-beyond commitment to the Drupal community.

Nominations were opened in March, giving community members the opportunity to nominate people they believe deserve the award, which were then voted on by the members of the Community Working Group, along with previous winners of the award.

We are pleased to announce that the 2016 recipient of the Aaron Winborn Award is Gábor Hojtsy. During the closing session of DrupalCon New Orleans, Community Working Group members presented the award to Gábor. The award was accompanied by a free ticket to DrupalCon, which he donated to Bojhan Somers.

Gábor was described in his nomination as an "amazing community connector" who is passionate about empowering others, stepping aside and allowing others the space and support to lead, and celebrating even the small wins that people who work with him achieve. The stellar work and leadership he displayed on the D8 Multilingual Initiative, managing sprints, Drupal events and setting up are just a few of the ways that this tireless Drupal contributor has been making an enormous impact in our community for more than a decade.

We hope you will join us in congratulating Gábor, who has demonstrated personal integrity, kindness, and above-and-beyond commitment to the Drupal community in abundance.

May 25 2016
May 25

[embedded content]

At this month's Sydney Drupal meet up I did a presentation about Search in Drupal 8. In the video, I explain three ways you can create a search page, they are as follows.

1. Core Search

The core Search module which comes with Drupal has some new functionality in Drupal 8. The biggest change is the ability to create custom search pages without using any other module.

2. Views Filter

A common way to build search pages in Drupal 7 was to create a views page and use the "Search Keywords" filter in views. This can still be done in Drupal 8 and best of all Views is now part of core.

3. Search API

The Search API module is used to create powerful search pages and it's highly extensible. It is the module to learn and use for building search pages.

I hope this presentation helps and that you enjoy the video.

Like what you see?

Join our free email list and receive the following:

  1. Discover our best tutorials in a 6 part series
  2. Be notified when free content is published
  3. Receive our monthly newsletter
May 25 2016
May 25

by David Snopek on May 25, 2016 - 11:26am

As you may know, Drupal 6 has reached End-of-Life (EOL) which means the Drupal Security Team is no longer doing Security Advisories or working on security patches for Drupal 6 core or contrib modules - but the Drupal 6 LTS vendors are and we're one of them!

Today, there is a Moderately Critical security release for XML sitemap to fix a Cross-Site Scripting (XSS) vulnerability.

The module doesn't sufficiently filter the URL when it is displayed in the sitemap.

This vulnerability is mitigated if the setting for "Include a stylesheet in the sitemaps for humans." on the module's administration settings page is not enabled (the default is enabled).

Download the patch for XML Sitemap 6.x-2.x (also works with 6.x-2.1, the latest release), 6.x-1.x or 6.x-1.2.

If you have a Drupal 6 site using the XML sitemap, we recommend you update immediately! We have already deployed the patch for all of our Drupal 6 Long-Term Support clients. :-)

If you'd like all your Drupal 6 modules to receive security updates and have the fixes deployed the same day they're released, please check out our D6LTS plans.

Note: if you use the myDropWizard module (totally free!), you'll be alerted to these and any future security updates, and will be able to use drush to install them (even though they won't necessarily have a release on

May 25 2016
May 25
It's my pleasure to introduce Acquia Bolt, a development tool for generating new Drupal projects using a template derived from our Professional Services' best practices.We began building and using Bolt internally over the past year. Our goal was to codify a set of tools and conventions that would allow us to:
May 25 2016
May 25
It's my pleasure to introduce Acquia BLT, a development tool for generating new Drupal projects using a template derived from our Professional Services' best practices.We began building and using BLT internally over the past year. Our goal was to codify a set of tools and conventions that would allow us to:
May 25 2016
May 25

Dropcast: Episode 20 - Kind of a big deal

This episode we hit a land mark of twenty episodes, so instead of picking on Mario the entire time, we talk about our favorite moments at Drupalcon in New Orleans. Of course this is funny since half of us didn't actually attend the 'Con. Other episode titles considered: "Bob and Mario live vicariously through Mark and Ryan"

Episode 20 Audio Download Link


Mediacurrent Blog Mentions:

Topic Drupalcon Moments Mark:

Topic Drupalcon Moments Ryan:

Topic Drupalcon Moments Mario:

Topic Drupalcon Moments Bob:

Pro Project Pick:

Drupal News:

The Final Bell:

May 25 2016
May 25

Other than a quick sample of blocking a specific file extension using the 'nomask' option, the documenttation for Drupal's file_scan_directory() does not help much with how to bock content from certain directories.  The documentation says

The preg_match() regular expression of the files to ignore.'

So it leaves you to believe that any regex should work.   So setting

$options['nomask'] = "#(/deleted/)#"

should block any directory named 'deleted'.  The problem is, it doesn't work that way.   In file_scan_directory() the regex is not run against the full path of the file, it is only run against the directory or filename recursively.  It is not evaluating  'directory1/subsection/deleted/index.html' , where the regex above would definitely come back with a hit and reject the item.  It is first evaluating, 'directory', then 'subsection', then 'deleted'...   It does not get a hit on deleted because it is missing the slashes on each side.

One possibilty would be to remove the slashes from the regex like this:

$options['nomask'] = "#(deleted)#";

But without the slashes, it would not only reject the directory 'deleted', it would reject the directory 'not-deleted'  and the file 'faq-why-my-account-was-deleted.htm' which might have undesired consequences.

The trick to get it to reject only 'deleted' as a directory and its contents is to restrict the regex to only the start and end of the string being evaluated. like this

$options['nomask'] = "#^(deleted)$#";

and if you wanted to block 'deleted' and another directory like '_vti_cnf' it would look like this:

$options['nomask'] = "#^(deleted|_vti_cnf)$#";

May 25 2016
May 25

While I have had the privilege of attending a number of DrupalCons and camps over the years, I cannot remember one with as many sessions and BOFs (birds of a feather) on the topic of security. In addition to the security talk on the program schedule, I had a great time chatting with individuals in the hallways and a few security focused companies in the exhibit hall. 

I wasn't able to attend all of the sessions and BOFs mentioned below, but I want to highlight my favorite takeaways from the ones I worked into my schedule.

Simplifying Security: Protecting your Clients and your Company covered some common security myths that will surprise many technical and non-technical alike. Make sure to catch the video of the session.

Watch the Hacker Hack dives into the mind of a hacker and how it isn't like the movies. Spoiler alert: The end results can be just as dire for your website and associated data. The session was interactive with video examples of the hacker(s) in action. I plan to watch this session on video again as it was full of interesting details.

Data Security in Drupal 8 was a BOF led by Rick Hawkins. Rick talked about a number of security improvements in Drupal 8.

There was also a lively discussion about data encryption techniques and challenges with securely storing encryption and API keys.

Meet with Security Team Members and Ask Security Questions was led by Michael Hess and other members of the Drupal security team. This BOF was a great reminder that there are still so many ways to get involved in the Drupal community. The article How to join the Drupal Security Team has lots of details on getting involved. Even if you don't want to join security team, the last section of the same page, "Improve Drupal's security from outside the team," is pure gold. So many ways to get involved. The BOF attendees asked questions and discussed Drupal security team processes and how the team dealt with Drupageddon and other security incidents.

It is great to see the awareness of security rising in the community as Drupal continues to drive more enterprise websites and applications. I think that all of the Drupal and related hosting infrastructure best practice discussions will help enterprise and non-enterprise install bases. This kind sharing is one of the many things I love about being part of an open source community.

Security-related sessions and BOFs I didn’t attend

In summary

The number of sessions and interest in security at Drupalcon confirmed to me that attendees realize security is no longer a checkbox within a list of requirements. Security should be an ongoing part of any software development process, just as we do with UX, digital strategy, content architecture, etc. I am looking forward to taking what I have learned to continue educating our clients and the Drupal community on the importance of protecting websites and applications. 

Additional Resources
Highlights from Drupalcon New Orleans | Mediacurrent Blog Post  
The Real Value of Drupalcon | Mediacurrent Blog Post    
How to Prepare Your Team for Drupal 8 | Mediacurrent eBook 

May 25 2016
May 25

Your company’s business development team just announced a new Drupal project has been given the green light, and you will be the project manager. What do you need to do to help your development and strategy teams succeed in giving the client the best possible experience and product? You need to ask the right questions.

3 questions to ask regardless of the CMS in play

The project manager of any technical project, leveraging Drupal or some other CMS, should first and foremost ask:

1. Where is the Statement of Work (SOW) and how do I access it?

The SOW should:

  • lay out the scope of the project, including functionality, travel and training expectations;
  • provide you with a start and expected end date;
  • tell you the budget;
  • explain the agreed upon change order process to handle any new requirements that may come up during the project.

PM Tip: Tap into the knowledge of those who came before you!

In addition to the written knowledge in the SOW, don’t forget to speak to the business development team about their interactions with the client. Did the client mention any pain points? Does the anticipated launch date correspond with a business need and is therefore a “must have” instead of a “nice to have?” Any insight into the personalities of the various stakeholders? And remember to talk to your fellow PMs too– have they worked on similar projects or with similar clients?

2. What project management methodology are you using for this project - Agile, Waterfall or something in between?

If you use Agile, your project plan will need to account for the collaborative nature of the project – expect more back and forth discussions and meetings with stakeholders throughout the process. If using Waterfall, you should account for the upfront requirements gathering that needs to take place before the development can begin. Either way, your project plan should fit the needs of both the client and your internal team to get the project done right.

PM Tip: Click here to find out more about Agile.

3. What are the best talent resources you have available to fit the specific needs of this project?

Based on the SOW, who is going to be on your team? You should consider not only the special talents of your available resources but also the preferred working styles of the team members, and how they will mesh with the client and each other. It goes without saying that you should provide a front end developer if the contract includes applying a design, for example, but there are subtler considerations too. Maybe the client has expressed an interest in knowing how things work instead of just seeing the end result of the technology. In this scenario, you’d try to engage a developer who wants to share his or her knowledge and enjoys client interactions.

PM Tip: Nothing beats a real conversation!

Get to know your development and strategy teams by picking up the phone or walking over to have a face to face conversation. Reading a bio or an IM thread is great but nothing beats talking to the person – simple human to human interaction is still the best indication of who the person is behind the talent.

Questions to ask for a Drupal CMS

In addition to the aforementioned considerations, a project manager about to start a Drupal CMS project could benefit from knowing the answers to a few more questions:

1. In what platform is the current site built and which version of Drupal is the most appropriate for the client’s needs?

2. What are the hidden “it happens by magic” moments in this new project – aspects of the project that the client might not recognize as heavy lifts or even considerations for your team and therefore might not directly call it to your attention?

Your Client’s Customers and Other Vendor Relationships

A project manager must establish a foundational understanding of the client’s customers and have a full view of all third-party vendor relationships in the mix. This process sometimes involves decoding client requests:


  • Client says “We have members or donors and want to track their behavior.”

Single Sign on or other API

  • Client says “We have members who want to login once and be able to see everything across the online communities we provide them.”

SOLR Search Functionality

  • Client says “We have members who want to login once and be able to search the content in all uploaded files and conduct mini searches within our publications to find what they need quickly.”


Every client must be satisfied that the security measures behind their new Drupal website are aligned with their unique business needs. Many times, clients take security for granted but it is the project manager's job to make sure a client's trust is earned and proven well-placed:


  • Client says “We need to be secure.”


  • Client says “We need to be secure because we are collecting money.”

High Availability Server

  • Client says “We need to be secure because we are collecting a crazy amount of money from our 1 million transactions a day.”

Event Tracking

  • Client says “We need to be secure because we are collecting a crazy amount of money from our 1 million transactions a day for our multiple concert events each week.”

In the end, the worst thing a project manager can do is ask nothing and just hope the project works itself out. A project team’s success and a client’s great experience is made or broken largely in between the sentences of the contract and outside the negotiation meeting room. Asking questions and truly listening to the answers given can only lead to good things for your project. In the case of communication, you can never have too much of a good thing.

Additional Resources
One Word to Save Your Project |Mediacurrent Blog
How to Budget a Drupal Project |Mediacurrent Blog
17 Tips for Leading Effective Conference Calls |Mediacurrent Blog 

May 25 2016
May 25

Today I will describe a way to handle multiple teams with their own private file folders using the IMCE module.

Let’s pretend that we have to develop a website called which consists of three (or more) different teams. The team structure could look as followed:

Website Groups

Every team should only be allowed to edit their own pages but no page from any other team. Therefore it would also make sense to separate the team’s file folders so that the files can be stored separately to secure its privacy.
Of course, we could simply add three IMCE profiles and define their folder access rights individually there. But what about when working with 10 teams? Or 50? Or even more? Then we definitely would prefer a more flexible solution.
Thankfully, IMCE ships with the ability to define user folders by PHP execution, how awesome! But in order to achieve this, we’ll have to set up teams as taxonomy terms first and reference them from our user entities.

Setting up the “Teams” taxonomy vocabulary

First things first: Let’s create a new taxonomy vocabulary called “Teams”. For every team that we will have on our website, we have to create a new taxonomy term in this vocabulary.
Before adding any teams as taxonomy terms though, we’ll have to add a new field called “FTP Folder” to the taxonomy vocabulary.
This field will specify the name of every team’s root folder. So, naturally it shouldn’t contain any spaces or other wicked special characters and it should be URL readable.
In order not to face any unusual results later, it is recommended to configure this field as required.

Afterwards, we can add our three terms, “Team Alpha”, “Team Beta” and “Team Gamma”.
As value for their FTP Folders, we use “team-alpha”, “team-beta” and so on.

That’s it for the taxonomy part! Now let’s link this information to the team’s users.

Adding a taxonomy term reference field to the user entity

In my case, I didn’t have multiple roles for the teams. I only had one, called “Team member”. Because every team has exactly the same rights as the others, maintaining only one role suited me best.
For really special cases, I could always just create a new role with the special permissions.

So, how do we link users to their teams the easiest? Exactly, by just adding a taxonomy term reference field to the user entity!
Let’s call this field “Team” and reference our previously created taxonomy vocabulary “Teams” with it.

Now, when adding a new user, we can select it’s team belonging and IMCE will be able to grab the needed information from there.
Yes, IMCE will be able to do that but it’s not doing it yet.
Getting the teams ftp folder for the current user is still something we have to code, so let’s proceed to the next step.

Writing a custom function to provide the accessible directories for an user

Now we need to provide IMCE the information that we’ve set up before.
We’ve created users belonging to teams, which hold the FTP root folder name for the teams.
What’s left to do, is to write a function (ideally in a custom module, in my example the module is called “awesome_teams”), that combines all information and returns it to IMCE.
Following function would do that for us:

function awesome_teams_imce($user) { $user_folders = array('cms/teams/all'); $user_wrapper = entity_metadata_wrapper('user', $user); $user_teams = $user_wrapper->field_team->value(); foreach ($user_teams as $user_team) { $user_team_wrapper = entity_metadata_wrapper('taxonomy_term', $user_team); array_push($user_folders, 'cms/teams/' . $user_team_wrapper->field_ftp_folder->value()); } return $user_folders; }














function awesome_teams_imce($user) {

  $user_folders = array('cms/teams/all');

  $user_wrapper = entity_metadata_wrapper('user', $user);

  $user_teams = $user_wrapper->field_team->value();

  foreach ($user_teams as $user_team) {

    $user_team_wrapper = entity_metadata_wrapper('taxonomy_term', $user_team);

    array_push($user_folders, 'cms/teams/' . $user_team_wrapper->field_ftp_folder->value());


  return $user_folders;


The function expects an user object as argument and will return an array of strings containing all the folder names an user is allowed to access.
Our folder structure would look like this:

  • sites/default/files/cms
  • sites/default/files/cms/teams
  • sites/default/files/cms/teams/all
  • sites/default/files/cms/teams/team-alpha
  • sites/default/files/cms/teams/team-beta
  • sites/default/files/cms/teams/team-gamma

Note: The folder “cms/teams/all” is a special folder and every user is allowed to access it.
It will be used to save files which are used globally over multiple or even all teams.

What our code does, is actually looping over all assigned teams for the given user (yes, an user can be in multiple teams!), and adding the teams ftp folder names to the array of accessible folders.

There is no “hook_imce” hook, the “_imce” in the function name does nothing till now. You can also name your function differently. The link from IMCE to our function is something we have to set up in an IMCE profile.
Let’s proceed to the last step then, shall we?

Creating the IMCE profile “Team member”

Now, as the last step, let’s create an IMCE profile called “Team member”. You’re free to define any settings as you like, there’s only one thing that will be special about this profile: The accessible directories path.

Instead of writing something constant as “cms/teams/team-alpha”, we’ll write “php: return awesome_teams_imce($user);” here.
So, the setting should look like this:


Now save the profile and you are done!

As soon as one team member now accesses the IMCE page (either via /imce or by the configured file/image fields), he will only see his team’s directories and the special directory “all” which is meant for exchange.

This wasn’t that difficult, was it?

I hope I was able to give you an insight on how to solve more complicated file permission issues with IMCE.
Don’t forget to give feedback, ask questions and follow our blog if you want to read more about our Drupal experiences at Liip!

May 25 2016
May 25

My role as a principal at LevelTen means that I spend a lot of time overseeing Accounting, Operations, and Marketing. So for my visit to DrupalCon 2016, I wanted to spend as much time as I could talking with other C-level people to see what struggles we have in common and what solutions we've come up with.

Throughout the sessions, summits, and socializing, there were a few key themes that kept coming up over and over from people who run Drupal shops. With that in mind, this post is less of a DrupalCon 2016 takeaway than a preliminary analysis of the economics of Drupal as it evolves in Drupal 8 and beyond.

Offshoring: The U.S. Perspective

As with any business, attention to the bottom line is always a topic of hot discussion among agency principals. One recurring theme seems to be the idea of offshoring of development work (and increasingly other work).

Let’s face it, Drupal has its origins across the pond, so the concept of offshoring has always been in its roots, so to speak. As Drupal grew, healthy collaboration from anywhere in the world became a standard within the community. Geographic boundaries were never a problem when it came to the sharing of information, modules, and other technical hurdles.

What did NOT come as straightforward was the outsourcing of the actual development work (or project management work) to places outside of the country a company was conducting business. Historically, outsourcing seemed to be frowned upon within U.S. agency circles, but now, it seems to be the standard practice for larger agencies, even if only to test the waters. (For the record, I am not a protectionist, but I can appreciate the long term economic implications suggested by those who don’t like this trend.)

Either way, it is a new economic reality for any U.S. agency wishing to compete: some competitors will be leveraging workforces outside the U.S. We can talk about maintaining a competitive advantage all day, but the economics of capitalism will drive companies to seek economic advantages abroad if they exist.

Business Summit: One Size Does Not Fit All

Susan Rust did an excellent job of leading the Business Summit, where many takeaways for agency principals were discussed. There were way too many great conversations to pack into this writing, so I suggest that, if at all possible, you should really attend one of these summits yourself -- maybe at DrupalCon Baltimore?

One issue Susan raised, which I also think needs to be addressed, is the separation of agencies by size in these summits. Considering all the varying sizes of companies working with Drupal, one size does NOT fit all when it comes to operational challenges (or solutions). It is both inspiring and comforting for all to listen to the successes and challenges of all size shops; however, the idea that a 15-person company like LevelTen will employ the same solutions as a 100-person shop and a 2-person shop would be naive. I reiterate Susan’s call to modify the format in some way to accommodate all business summit participants, but sub-segment by agency size.

Drupal Economics: Drupal is Going Upstream

For those developer types, “upstream” has nothing to do with Git. In business parlance, "upstream" has to do with looking at larger industry sectors that, most times, serve other industries downstream. When we say that Drupal is going upstream, we mean that Drupal is evolving to be a good solution for large enterprise-level businesses, as opposed to small or mid-size businesses.

I saw a lot of people during the course of the week get caught up in the question of whether Drupal "can" be for everyone. Of course it can. The real question is "Who is Drupal best suited for at this time?," and an honest assessment is needed to answer it. It seems clear that Drupal is going upstream, becoming a preferred web platform for large enterprises. If you think Drupal is still best suited for small or medium businesses, I would love to hear why.

Now that we have established that Drupal is in fact going “upstream,” I would like to share what that means for the economics of Drupal:

1. Project sizes are getting larger, even as websites are commoditized.

Websites are fast becoming a commodity (if they are not already there, here in 2016). Look no further than ads for free websites with a minimal purchase, or inexpensive SAAS platforms for the masses. With this commoditization comes downward pressure on prices (price per unit of output), even as the industry matures. The successful companies look to larger projects to sustain the increased revenue requirements needed to support growth initiatives in an industry where the price per unit of output is decreasing.

2. Drupal shops are looking for economic advantages (see my point about outsourcing, above).

With increased revenue comes increased expenses and decreased profits as a percentage. Business owners often combat this with lower cost structures to prop up profits, which is generally regarded as a short term fix.

Lowering costs is not a sustainable model for growth unless, that is your competitive advantage (side note: contrary to Michael Porter’s acclaimed Competitive Advantage Theory (which I generally subscribe to), certain industries that exhibit rapid change, and lots of new alternatives or substitutes, will find that being the cost leader is the least desired strategy). Instead, the majority of Drupal shops are looking for other ways to increase their margins, whether that is through outsourcing, moving to a recurring-revenue retainer model, or other ways of restructuring the company.

3. Consolidation in the industry is coming.

Lastly, in an environment this competitive, Drupal companies are increasingly looking to consolidation through mergers and acquisitions of competitors to maintain growth. In this scenario, only a few survive the onslaught -- unless you have a true differentiation in the marketplace, and even then, it will be tempting to sell out to a competitor at some point.

This is not a doomsday prediction for the economics of Drupal, but rather, a reminder of the economic forces of goods and services that have increasing demand, and how companies attempt to capitalize on this need during the growth phase.

As Drupal becomes more powerful and more popular, these tensions are going to arise for more and more people, from solo freelancers to small shops to big players like our friends at FFW. At LevelTen, we plan to keep doing everything we can to keep bringing Drupal solutions to the people that need them.

May 24 2016
May 24

The normal Drupal instructions for applying patches are well used and reliable. However, I find them to be a little verbose, so I came up with a slightly quicker workflow.


The short explanation of what I do is to copy the patch's URL and run this command:

curl [patch URL] | patch -p1

Which would then become something like this:

curl | patch -p1


  1. This workflow assumes the current version of the module/theme/core being patched is up-to-date, possibly a -dev version, and that the patch was also relatively current. It is common for files to substantially change from revision to revision, so a patch written against the latest -dev version of a module may not work with an older release.
  2. I'm not touching the "always use Drush Make" or "Composer is how the cool kids do it nowadays" workflows, this is purely about spending less time mucking around with patch files to test what could be a single line change to one of the simplest, or most complex, pieces of code you've ever seen.

Longer explanation

Step 1: Find the patch to be applied.

Step 2: Copy the patch's URL into the clipboard.

Step 3: In Terminal (or the Command Prompt on Windows), go to the appropriate directory for that project, e.g. sites/all/modules/contrib/metatag.

Step 4: Type the following into the terminal window: curl

Step 5: If it gave any warnings, update the issue with the comment "This patch needs to be rerolled." and change the status to "Needs work".

Step 6: Presuming the change applied ok, use "git status" to see what changed.

Step 7: If any files with a file extension ".install" show as either being changed or added, run the database updates.

Step 8: Clear all of the site's caches: drush cc all

Reason to do this

  • There's no need to keep a copy of a patch file, it can always be downloaded again later from if needed again.
  • Because there are no patch files locally there's no worrying about where the patch file is stored on the computer versus which directory the command prompt is in, or how to make the path to the patch work correctly.
  • "git apply" does not apply the patch at all if it would not apply cleanly, and it often doesn't explain why the patch would not apply, even with the "-v" argument. If the patch didn't apply cleanly then it has to be manually recreated from scratch, which can be problematic and lead to mistakes. Using the "patch" command instead will apply what can be successfully applied, and anything that couldn't be applied correctly will be saved out as a separate ".rej" file, leaving much smaller pieces to be recreated.
  • There will be fewer files floating around the computer; the only patch files on my computer are the ones I actually created.

Over to you

What development processes have you tweaked to your own liking? Let me know in the comments.

Additional Resources
Mediacurrent's Contrib Committee April 2016 Update |Mediacurrent Blog
How to Add Content in an Update Hook |Mediacurrent Blog
Acquia's Dev Desktop: A Drupal Service for Beginners |Mediacurrent Blog

May 24 2016
May 24

As I've said before in my custom views filter handlers tutorial, views is amazing. Today I was writing a custom style plugin. I got the plugin to show up in the list of available formats, but whenever I saved the form, it wouldn't stick.

My Typical Method of Debugging in Drupal

Typically I would throw dpm's to debug, so I started walking through the callstack trying to find where things were going wrong. Then I ran into a line in views that called vpr(). It looked like a print_r debug statement, so I knew this was either being logged or there was a setting somewhere.

A Better Way to Debug Views Plugins

Sure enough it is part of the "Enable views performance statistics" setting to have these messages logged with watchdog. To turn it on go to /admin/structure/views/settings/advanced. Even better, when you turn Devel on, you can have them dpm'ed instead. Now I get exactly the information I need to figure out what I was doing wrong, without having to throw my own dpm's in views or ctools.

Other Views Settings for Debugging

Also, if you are just looking to debug your views query the "Show the SQL query" and "Show performance statistics" options on /admin/structure/views/settings are invaluable.

This post is part of my challenge to never stop learning.
May 24 2016
May 24

How to Secure Drupal HTTP HeadersIn this blog post I will briefly overview some of the very useful HTTP response header parameters that will help to secure any website. HTTP Response headers are name-value pairs of strings sent back from a server with the content you requested. More information can be found on the internet.

I will cover some of the most important security-related HTTP parameters. The original blog post was written by Scott Helme who is the creator of This is a brief overview of his blog post to introduce this technique to our readers.

Most of the header parameters can be set either in your .htaccess file (Apache) or webserver configuration files (preferred).

It is always good to review your response HTTP headers and remove some of them (if the system allows). For instance PHP version or webserver version.

Important: Make sure to QA your website after making the changes to the HTTP headers. Headers such as X-Frame-Options and Access-Control-Allow-Origin may break your site if incorrectly configured.

Also as a result of this blog post I built Drupal 8 module. The module is similar to Security Kit Drupal 7 module.


This response header can be used to configure a user-agent's built in reflective XSS protection. Currently, only Microsoft's Internet Explorer, Google Chrome and Safari (WebKit) support this header.

Set this in Nginx:
add_header X-Xss-Protection "1; mode=block" always;

Set this in Apache:
Header always set X-Xss-Protection "1; mode=block"


The X-Powered-By header gives information on the technology that's supporting the Web Server. This parameter specifies the technology (e.g. PHP etc..) supporting the web application (version details are often in X-Runtime, X-Version, or X-AspNet-Version

To disable this parameter edit your php.ini file. Set expose_php = Off and restart your webserver.


This header parameter prevents Google Chrome and Internet Explorer from trying to mime-sniff the content-type of a response away from the one being declared by the server. It reduces exposure to drive-by downloads and the risks of user uploaded content that, with clever naming, could be treated as a different content-type, like an executable.

Set this in Nginx:
add_header X-Content-Type-Options "nosniff" always;

Set this in Apache:
Header always set X-Content-Type-Options "nosniff"


Clickjacking protection. Valid values include DENY meaning your site can't be framed, SAMEORIGIN which allows you to frame your own site or ALLOW-FROM which lets you specify sites that are permitted to frame your own site.

Set this in Nginx:
add_header X-Frame-Options "SAMEORIGIN" always;

Set this in Apache:
Header always set X-Frame-Options "SAMEORIGIN"


Access-Control-Allow-Origin is apart of the Cross Origin Resource Sharing (CORS) specification. This header is used to determine which sites are allowed to access the resource by defining either a single origin or all sites (denoted by a wildcard value). It should be noted that if the resource has the wildcard value set, then the Access-Control-Allow-Credentials option will not be valid and the user-agent's cookies will not be sent in the request. Valid values are:

  • * - Wildcard value allowing any remote resource to access the content of the resource which returned the Access-Control-Allow-Origin header.
  • - A single serialized origin (http://[host], or https://[host]).

Content Security Policy

This HTTP header parameter allows you to define a whitelist of approved sources of content for your site. By restricting the assets that a browser can load for your site you will have extra level of protection from XSS attacks.

Set this in Nginx:
add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always;

Set this in Apache:
Header always set Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'"

Read more Content Security Policy - An Introduction

HTTP Strict Transport Security

This policy will enforce TLS on your site and all subdomains for a year.

Set this in Nginx:
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains" always;

Set this in Apache:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Read more HSTS - The missing link in Transport Layer Security

Drupal modules

Download Drupal 8 module (github)

Useful links

  1. List of HTTP header fields
  2. Security HTTP Response Headers
  3. Security through HTTP response headers
  4. Hardening your HTTP response headers
  5. Introduction to HTTP Response Headers for Security
  6. Guidelines for Setting Security Headers
May 24 2016
May 24

Phew! It's been a busy few weeks. I recently had the priveledge of presenting a session (Content-Driven UX) at DrupalCon: New Orleans 2016 with my teammate, Bjorn Thompson. The room was packed with collegues and professionals eager to learn about this emerging paradigm. You can find out about the best content sessions from DrupalCon this year (including ours).

Content-driven UX is constantly on my mind. My entire career is focused on practicing and evangalizing this framework. With DrupalCon winding down, I thought I would touch on the subject a bit more in this blog, and provide some additional strategies for creating and delivering powerful, user-friendly content.

1.  A Content-Driven User Experience (UX) 


Content is at the center of everything

What if I told you that by the time you read this, there will be over 1,012,089,457 billion websites on the web? Now, imagine how much content and data is generated every year. In the world of web, the one bonafide thing people consume is content. Some criteria that are at the heart of content-driven experiences are:

  • Message Quality:  Does the content’s “personality” match the target user? Yep content should have personality. One way it comes out is through copy, by voice, tone and style.
  • Front-Loading:  Is the most important content served upfront? The most important content is the conclusion. Your users want that first, not last.
  • Chunking:  Do headings, lists, UI patterns etc effectively organize content it digestible sizes? Users skim and scan digital content.
  • Pathways:  Does the content provide users access to complete goals and tasks? Make sure those goals continually align with the business goals too.
  • Access:  Is the content easily available across multiple devices? Content is meant to be consumed. Tip: find out where target users are and share relevant content there.

Content and design make a strategic whole. This digital superpower forces (or entices us) to address the entire digital ecosystem - from experience to performance. It also help us to ensure two important perspectives are up-front and center: target users and the business itself. What else can it do? A lot.  For one, as practitioners, it allows us to take a deeper look at how content should be written, visualized and delivered in order to drive content consumption or, end user experience. It also empowers digital strategists like myself to ensure on-page content is architected in way that will support the entire ecosystem. There’s a lot of content-driven resources out on the webs -  it’s worth doing some research and including the wisdom into your framework. 

design should support UX content Engagement

I’m frequently asked about the intricacies of visual design and it’s influence on content. It’s a subject I care deeply care about and find myself eager to discuss. Visual design is important. It should support stronger content-consumption (a.k.a. performance) experiences. 

Consider colors, typefaces, logos, emblems, and writing style as the skin that wraps around content. Visual design drives the desire to want to consume content.  Take a moment and think about your home. Imagine several rooms with furniture, electronics, colors, textures, patterns etc. Each room serves a specific purpose - just like web pages within a site. The furniture in each room also serves a specific purpose - beds are made for bedrooms - not kitchens. We spend a lot of time sourcing the right colors and material for our furniture, even digging into the tech specs for the tv we’re upgrading. In the world of web, the furniture, electronics, dishes, clothes - everything in your home - is similar to digital content. 

Design wraps around content. Good design helps draw in users to complete goals or take an action. Choosing the right interfaces and interactions are equally as important. My start in the digital world came from studying (and practicing) Visual Interaction Design (IxD). IxD is a UX design framework that focuses on UI interactions, user journey interactions and pathways. It’s great marriage of science, logic and creativity.


2.  Deploy a Multi-Device Friendly UI

People searching for local businesses will be doing so using various devices. Mobile Internet usage has already overtaken desktop usage, especially when it comes to local searches. After all, if someone is looking for a shop or restaurant in a certain area, they'll probably be away from home already, hence the likelihood they'll be using a smartphone or tablet. 

Fortunately, making your website mobile-friendly is easier than ever before, particularly if you're using a content management system (CMS) such as Drupal or Wordpress.

The easiest way to build a mobile-friendly interface is simply to use a responsive design theme that automatically scales to the size of the screen it is being displayed on. As a local business, you should prioritize mobile users and thoroughly test your website across a wide range of mobile devices. Always make sure your content is easily readable and navigable on the small screen.

3.  Invest in Localized SEO 

Local business websites should absolutely focus (and invest) in locaized search engine optimization (SEO). First, be sure to create a domain name that reflects your industry and, if possible, the geographical area it serves. If your business serves multiple locations, it is wise to have multiple domain names, since you'll be able to optimize each website for individual locations. The content of your website should also be relevant to a local audience and, while paying attention to locally relevant keywords and place names is advisable, you must make sure to prioritize user experience by offering value-adding content that your target audience will find genuinely useful. Localized SEO can drive serious qualified traffic.

If you're interested in more tips on localized SEO, check out SearchEngineLand's article.

4.  Use Persuasive Trust Signals 

Ttrust signals are particularly important for e-commerce websites, and they're also valuable for any business websites. Many of your potential customers will be looking for reviews elsewhere, so there's no harm in quoting some positive feedback on your own website, provided you ask for permission from the author beforehand. For example, if you run a guesthouse that has an excellent rating on Airbnb or TripAdvisor, be sure to mention this on your website with a link to the original source to prove its authenticity. 

If your small business also maintains an e-commerce store, consider deploying your own user-review system. This helps to show your target audience that their opinions matter. Trust seals, which are awarded to some businesses and their websites can also help to increase your conversion rate.

5.  Share a Relatable Company & Team Story 

Every business website, no matter what size, should have an 'About Us' page. This mission-critical page is the perfect stage for sharing your story and building a sense of trust with your target audience. Writing a compelling About Us page isn’t always easy, since it's important to capture your reader's attention with an engaging story that they can relate to. People love stories, and this page is your opportunity to tell the story of your business. Use an honest and friendly tone that captures the essence of your brand, rather than trying to be promotional. Your business might have had the humblest of beginnings, but this is something that you can and should proudly proclaim on your About Us page. You can further amplify your story by adding a high-quality image or two. 

Example About Us Page from The content is their team story and they've added some great interactions to really help bring that story to life. 

6.  Social Media Integration

Any successful business should already have an active social media presence in the form of a Facebook page and Twitter account at the very least. However, integrating social media on your business website is also important, since it helps to promote sharing and feedback and reach out to a wider audience.

One of the simplest ways to integrate social media is to have social sharing buttons for the major social networks on all of the main content pages of your website. These buttons allow your visitors to share pages they like on their own social networking profiles with the click of a button. It is also a good idea to promote your own social media profiles on your website and vice versa. As social media marketing continues to grow, it becomes increasingly important to integrate it with your overall digital marketing strategy.

7.  Keep Your Content Delivery Fresh & Relevant

Static websites tend struggle with achieving higher search engine results (SERPs) in the longer term. People want current information when searching the Web, so it is essential that all of the content on your website is kept up-to-date and relevant at all times. Things like outdated contact information, directions and price information will serve only to distract and annoy your readers. Although blogging and other forms of dynamic delivery content might not be particularly effective for a lot of small businesses, any business website can make good use out of a news and events page. Use this page to post information about things like new products, sales and any other current affairs related to your business and its target audience. 

Remember, a great business website is one that not only attracts new visitors, but holds onto existing ones as well.

8.  Display Contact Information Up-Front

One of the most common reasons for consumers to turn to the Internet before visiting a local business is to find contact information. Rifling through the phone book or phoning an expensive directory enquiry number is a thing of the past for the vast majority of people. Your contact information should be clearly visible throughout your website, preferably permanently located at the bottom of every page. However, it pays to have a dedicated contacts page as well that also provides directions to your venue. 

Another important factor to consider when adding your contact information is to keep it consistent with any other listings you have online, since this is crucial for the sake of exposure in local search results. In other words, your business name, address and phone number must be written down exactly as it appears on your Google Local listing (which you should also have).

Image Courtesty: "A Blueprint of The Perfect Contact Form #Infographic"

9.  Integrated Google or Bing Maps 

In addition to contact information, people also expect to find directions to your venue. Even if you haven't made a point of putting your business on Google Maps or Bing Maps already, it might still be there anyway, in which case you will have to claim and verify your listing to prove that you are the owner of the business. This step is one of the most important for increasing your standing in the search engines, and it also allows potential customers to locate your business without even having to visit your website. Google and Bing both allow you to integrate maps into your website simply by copying and pasting a few lines of code. 

You'll also be able to customize the appearance of your maps without having to get involved in any complicated coding. If you're using a CMS like Drupal or WordPress you can simply copy the code into a text/HTML widget.

10.  Use a Newsletter Subscription Form 

In spite of many people claiming that email is losing its popularity, it continues to be the favorite way for consumers and businesses to keep in touch with one another. In fact, email is actually growing, thanks in part to the increasing ubiquity of mobile Internet and the fact that most people are now more likely to check their emails while on the move. 

Given the importance of email, every small business should maintain an opt-in email marketing strategy, and your website conveniently serves as the number-one platform for collecting subscribers. Always make it quick and easy for your visitors to sign up to your newsletter by adding a subscription box in the sidebar of your website. You can draw more attention to it through the occasional call to action, but make sure not to ask for any more information than necessary.

It's a Wrap!

An excellent business website can't be designed in a day, but it's not as difficult as you might think to get started. Thanks to the rise of user-friendly content management systems, you can get a website up and running in a matter of minutes. Nonetheless, it will take time and creativity as well as a thorough understanding of common design practices and SEO for your website to become truly effective.

Do you have content or a site that seems to have stagnated? Have you revived or increased user engagement with your content? Share your content-first experiences in the comments below or get in touch and ask your questions!

May 24 2016
May 24

Swiss has traditionally been dedicated to the best quality and innovation. Some of the best things in life come from Switzerland. Did anyone mention chocolate?

Photo by Janine, released under CC BY 2.0

Drupal and free software are no exception. Many companies and individuals are dedicated to them on a daily basis. That said, it is no surprise that Drupal's number one comes from Switzerland.

Jerome from MD Systems explains how we achieved that, which are the main advantages of Drupal and why everyone should use it. Very interesting read!

May 24 2016
May 24

Google summer of code 2016 started with a full swing this week. Vijay is one of the students participating in it. He is working on the Media module for Drupal 8.

He wrote an introduction blog post. I'd like to invite you to read it, say hi and follow his work as it progresses through the summer.

Welcome in the Drupal community Vijay!