Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Nov 18 2020
Nov 18

The Authoring Experience Problem

Authoring experience is a huge concern for web teams everywhere. As it should be. The ability for digital publishers to keep up with the rapidly accelerating demands of their users, and the pace of their competitors, largely depends on providing easy-to-use, expressive tools for their teams to create compelling content.

In practice, this means that publishers need the ability to quickly produce rich digital content from a range of possible components: text, images, videos, social media assets, and so on. Authors should be able to mix various elements quickly and effortlessly, with simple controls for managing content flow and layout. Under the hood, content should be structured and predictable. We’ve written about this before: organizations cannot sacrifice structure for flexibility. They need both.

And yet authoring experience has been a major shortcoming of Drupal, often articulated by marketing and editorial leaders as, “Drupal is too complicated for my organization.”

Other platforms from across the entire spectrum of digital publishing systems – from Adobe Experience Manager to Wordpress, Squarespace to WiX – provide rich, intuitive tools for easily creating all kinds of digital content. What Drupal offers in terms of flexibility – powerful APIs, easily customizable structured content, and a huge range of content management features – has come at the expense of the authoring experience.

Layout Paragraphs

A while ago I wrote about Entity Reference with Layout (or ERL), a Drupal 8 module that combines Paragraphs with the Layout API for a more flexible, expressive authoring experience in Drupal. ERL had one concerning drawback: you had to use a special field type for referencing paragraphs. That means ERL wouldn’t “just work” with existing paragraph fields.

Layout Paragraphs, the successor to ERL, fixes that problem. The Layout Paragraphs module combines Drupal Paragraphs with the Layout API and works seamlessly with existing paragraph reference fields.

The Layout Paragraphs module makes it dead simple for authors to build rich pages from a library of available components. It offers drag-and-drop controls for managing content flow and layout, and works seamlessly with existing paragraph reference fields.

Layout Paragraphs features include:

  • Easily configure which content components, or paragraph types, are available to your authors wherever Layout Paragraphs is used.
  • A highly visual, drag-and-drop interface makes it simple to manage content flow and layout.
  • Site admins can easily configure Layout Paragraphs to support nested layouts up to 10 levels deep.
  • A “disabled bin” makes it easy to temporarily remove content elements without deleting them.
  • Layout Paragraphs works seamlessly with existing paragraph reference fields.
  • Authors can easily switch between different layouts without losing nested content.
  • Layout Paragraphs is fully customizable and works with Layout Plugins, Paragraph Behaviors, and other Drupal APIs.

What About Layout Builder?

While there are strong similarities between Layout Paragraphs and Layout Builder, Layout Paragraphs solves a fundamentally different problem than Layout Builder.

Layout Builder, in Drupal core, is a powerful system for managing layouts across an entire website. With Layout Builder, site administrators and content managers can place content from virtually anywhere (including custom blocks) within specific regions of a layout. Layout Builder is extremely powerful, but doesn’t directly solve the problem I mentioned above: “Drupal is too complicated for my organization.”

Layout Paragraphs adds a new interface for effortlessly managing content using Drupal Paragraphs. It is simple, fast, and expressive. Layout Paragraphs is a field widget, and works the same way as other Drupal fields. The Layout Paragraphs module makes it simple for publishers to create and manage rich content from a library of available components: text, images, videos, etc. Layout Paragraphs is completely focused on the authoring experience.

Try It Out

If you want to see Layout Paragraphs in action, simply download the module and give it a try. Setup is fast and easy. From the Layout Paragraphs module page:

  1. Make sure the Paragraphs module is installed.
  2. Download/Require (composer require drupal/layout_paragraphs) and install Layout Paragraphs.
  3. Create a new paragraph type (admin > structure > paragraph types) to use for layout sections. Your new paragraph type can have whatever fields you wish, although no fields are required for the module to work.
  4. Enable the “Layout Paragraphs” paragraph behavior for your layout section paragraph type, and select one or more layouts you wish to make available.
  5. Make sure your new layout section paragraph type is selected under “Reference Type” on the content type’s reference field edit screen by clicking “edit” for the respective field on the “Manage fields” tab.
  6. Choose “Layout Paragraphs” as the field widget type for the desired paragraph reference field under “Manage form display”.
  7. Choose “Layout Paragraphs” as the field formatter for the desired paragraph reference field under “Manage display”.
  8. That’s it. Start creating (or editing) content to see the module in action.

If you’re using Layout Paragraphs in your projects, we’d love to hear about it. Drop a note in the comments section below, or get involved in the issue queue.

Nov 12 2020
Nov 12

Creating absolute menu links in Drupal 8 is pretty simple, but it took a little thought to land on the best solution for my use case. I ran into the requirement while working with a client to deploy their site navigation to a REACT app sitting on a different domain. The menu links we pulled in from their primary website needed to point back to their domain correctly, which of course meant they needed to be absolute.

A quick search turned up a couple of solutions, but none that quite suited my requirements. Here’s what I came up with — it’s fairly concise, leaves the menu link attributes intact, and doesn’t involve the theme layer.

 * Implements hook_preprocess_menu().
function MYTHEME_preprocess_menu(&$variables) {
  // Limit to specific menus for performance.
  $menus = ['main', 'footer'];
  if (isset($variables['menu_name']) && in_array($variables['menu_name'], $menus)) {
 * Recursively make menu items link with absolute.
function MYTHEME_set_menu_items_to_absolute(&$items) {
  foreach ($items as $item) {
    $url = $item['url'];
    if (!$url->isExternal()) {
      $item['url'] = $url->setOption('absolute', TRUE);
    // Recursively loop of sub-menu items.
    if (isset($item['below'])) {

Generating absolute menu links this way means I can pull main navigation onto various apps without any headache and without sacrificing any Drupal theme layer functionality.

You can download the gist here. Make sure you specify which menus you'd like to act on, by machine name, in the first line of the MYTHEME_preprocess_menu() function. The code goes in mytheme.theme — don't forget to replace MYTHEME with your theme name throughout.

Do you have a simpler way? Feel free to share in the comments.

Oct 20 2020
Oct 20

The AddEvent module for Drupal 8 lets you place easy-to-use Add to Calendar buttons on your website that integrate with Apple, Google, Yahoo, Outlook, and Office 365 calendar apps among others. The module also lets your users subscribe to entire calendars managed by AddEvent, adding all of your scheduled events to their calendars and keeping their calendars updated if your event details change.

The module is powered by AddEvent and you’ll need an AddEvent account for it to work properly. Free accounts include one calendar, restricted event-adds, and limited functionality; paid accounts include multiple calendars, higher subscriber limits, and a wide variety of other features. You’ll be able to build Add to Calendar proof-of-concept functionality with the AddEvent free version in just 15-20 minutes — but a professional tier account is necessary for any commercial level use.

First things first: Create an AddEvent account

Head over to AddEvent.com and register for an account. AddEvent is a paid service that offers a variety of features and high volume usage for licensed customers — but they also provide a free Hobby account that will get you started. After creating and verifying your account with the free Hobby plan, navigate to the Account screen by clicking on the user menu in the upper right corner of the screen, then clicking Account. From there, click Domains in the left-hand navigation, then follow instructions to add your domain.

AddEvent Module: domain whitelisting The domain where you will be using an Add to Calendar button needs to be whitelisted with AddEvent.

The Hobby plan only allows the use of one domain — but you’re able (at the time of writing this, anyway) to add a local development environment so that you can test without deploying to a publicly accessible website. When you’re ready to make the switch, you can simply remove your development domain and add in your live domain.

Install the Drupal 8 AddEvent module

Once you’ve registered for the service you’ll need to install the AddEvent module in your Drupal 8 website. You can install a Drupal 8 module in a variety of ways, but the easiest is probably using your terminal, starting from your project’s root directory. First require the module using composer:

composer require drupal/addevent

Then enable the module using drush:

drush en addevent

Now you’re all set to start using the AddEvent module. You can immediately create single-use Add to Calendar buttons using custom blocks, or combine custom blocks with a custom Event node type and the Token module to automatically produce Add to Calendar buttons for all of your events.

Add to Calendar: Static event buttons

Creating a static Add to Calendar button for a single event is super simple. Before we configure a block with our Add to Calendar link, though, we’ll need to fetch our Client ID from AddEvent. To do that, simply navigate to the Account page at AddEvent.com using the menu in the upper right corner of the screen. You should see a Client ID and API Token — just keep this window open or paste the Client ID in a safe place.

AddEvent Module: Client ID You'll need the Client ID to render your Add to Calendar buttons without the AddEvent branding.

Now on your Drupal site navigate to Structure > Block layout (/admin/structure/block) and click on Place block in the region you would like to place your Add to Calendar button. In my case, I’ll demonstrate adding the button to the Content region of a basic page that lives at the URL /my-basic-page.

From the Place a block dialogue that follows, click Place block next to the Add to Calendar item. Fill out the following fields as indicated to get your first example working:

  • Title: Add to Calendar
  • Display title: not checked
  • Button text: Add to Calendar
  • Title: My example event!
  • Description: My example event description!
  • Start: 10/31/2020 8:00 AM (the format is important, the date isn’t)
  • End: 10/31/2020 9:15 AM
  • Client: [Client ID from above]

Under the Customization portion of the form, paste your Client ID in the License field. This will remove the AddEvent branding from your button dialogue.

Finally, in the Visibility section of your block setup, choose Pages and write in the URL of the page you’d like the block on — in my case I’ll use /my-basic-page. Click Save block and navigate to the page you configured your block to appear on.

AddEvent module, an Add to Calendar button. A basic Add to Calendar button will present options for adding to Google, Yahoo, Apple, Office 365, Outlook calendars and more.

That’s it! Click the button and choose a calendar type to add the event to your calendar — it’s that easy. Next we’ll look at dynamically adding buttons to a custom Event node page.

Add to Calendar: Dynamic event buttons

You can create dynamic event buttons by using the Token module with a custom Event content type. Any node type with a properly configured date field will work. Make sure the Token module is installed before proceeding — use whatever Drupal module installation method works best for you. For this example, we’ll create a super simple Event node type. In my example below, I’ve added two custom fields of the Date type: field_event_date_start and field_event_date_end.

AddEvent module: Event content type A custom Event node type with date fields for start date and end date, for use with dynamically created Add to Calendar buttons.

Once your Event content type is set up, you just need to add a new Date format that will work well with the AddEvent module. To do that, navigate to Configuration > Date and time formats (/admin/config/regional/date-time) and click the Add format button. You can see below that I’m calling my format AddEvent and using the format string m/d/y g:i A which will translate to something like 10/30/20 4:45 PM — exactly what we need for our Add to Calendar button.

AddEvent module: date format Define a custom AddEvent compatible date format to get your Event content type working with Add to Calendar buttons.

Now we’ll place a new Add to Calendar block just like in the previous section, only we’ll use tokens for the Event title, description, and the start and end dates. When you open the Configure block interface for your new Add to Calendar block, click the Browse available tokens link in the description area of the Event Information section. The tokens you’re looking for will be in the Node group. Notice that the token options for field_event_date_start and field_event_date_end indicate our custom AddEvent format — tokens will be available for all of your custom date formats. Check out my example below.

AddEvent module: tokens The Token module lets block configuration be dynamic, allowing your Add to Calendar buttons to pull data from Event pages.

Everything else will be the same as it was in the first example in the section above, with the exception of the Visibility settings. For this block, we’ll restrict visibility by Content Type, ensuring that the block only appears on our custom Event node type pages.

AddEvent module: Block visibility Set block visibility to the Event content type to automatically create an Add to Calendar button on Event pages.

Once you’ve clicked Save block you’re all set. Now your Add to Calendar button will appear on every Event page in the region you specified, and it will inherit all of the event details from the specific event page.

Subscribe to an AddEvent calendar

Paid AddEvent accounts can manage multiple calendars of events on the AddEvent dashboard, and they have access to robust features like RSVP, custom fielded calendar events, subscriber reports, analytics, and more. While the Hobby account can demonstrate how Subscribe to Calendar works, the feature isn’t much use with the free-version restrictions in place.

Setting up a Subscribe to Calendar button is super simple. Before setting up the block on your Drupal site, you’ll need the Unique Key for your AddEvent calendar. From your Dashboard on AddEvent.com, click the menu options icon next to your calendar of choice (Hobby accounts only have one calendar) and click Calendar Page. Now copy the Unique Key for use on the block configuration below

AddEvent: Calendar Unique Key The Unique Key of your calendar used with the Subscribe to Calendar block type subscribes your users to entire AddEvent calendars.

On your Drupal site, navigate to Structure > Block layout (/admin/structure/block) and click Place block in the region of your choice. Choose the Subscribe to Calendar block type, then paste your Unique Key from above in the Data-ID field. You may want to place your Client ID in the License field like in previous configurations, to remove the AddEvent branding from the interface.

You can set up the Visibility settings however you wish, for my example I’ll stick with the /my-basic-page URL like before.

AddEvent module: Subscribe to calendar Subscribe to Calendar buttons add all of the events in an AddEvent calendar to your users calendar, and updates them regularly.

You’re all done! Now your users can subscribe to the calendar(s) you maintain on your AddEvent account. As you add and edit events on your AddEvent calendars, your subscribers’ calendars will be automatically updated. Very cool!

NOTE: Different calendar services synchronize at different speeds and some are very slow. Google Calendars, for example, can take up to 24 hours to synchronize changes from calendar subscriptions.

If you have suggestions, comments, or issues related to the AddEvent module, please let me know on the AddEvent module page! And feel free to leave questions or general comments below.

Sep 22 2020
Sep 22

Bay Area Drupal Camp has gone — wait for it — 100% virtual! BADCamp is a community run celebration of open-source software with a keen focus on learning and inclusivity. Every year this event brings Drupal users, developers, marketers, and content specialists together from all over the country for high value talks, summits and trainings.

While you’ll have to forego the trip to beautiful Berkeley, California this year, the good news is that registration is free and the 2020 session lineup is as packed as ever. Mark your calendar for this October 14th - 17th, and get ready to join Aten, the Bay Area Community, and your colleagues and peers from across the country in three major session tracks: Drupal for Beginners, Advanced Drupal, and Marketing & Communications.

Aten is excited to sponsor this year’s Higher Education Summit, and for our team to contribute a few sessions of their own, detailed below. Register for BADCamp 2020 today!

Friday, October 16th

Managing People: The Art & The Science, 1 PM PST

Project Managers are tasked with organizing client schedules, timelines, meetings, internal resources and much, much more. Every one of a PM’s tasks overlap in a central — and often complex — practice: managing people. Join Janice Camacho, Project Manager, as she explores the art of meeting each individual where they’re most comfortable, and the science of why they’re comfortable there. In this session you’ll learn how to get out of your own way and build the healthy, confident project teams that support strong, long-term client relationships.

True Life: I’m an introvert in an extrovert’s world, 2 PM PST

Do you shy away from speaking up in a crowded room? Do you prefer to maintain a carefully guarded bubble of personal space? Does the prospect of addressing an audience make you perspire and/or shake? Introverts exist in the world of Digital Project Management, too. Gasp! And — perhaps contrary to intuition — they bring a unique set of strengths and abilities to the table, much like their extraverted counterparts. Join Kacie Miner, Digital Project Manager, as she shares her experience of being an introvert in the DPM space. In this session you’ll learn:

  • Strengths, abilities, and positive attributes that introverts bring to the table
  • Ways to adapt your personality to the job at hand without changing who you are
  • Strategies that will set you up for success instead of causing you to overthink
  • Tips and tools to know where you lie on the extrovert scale, and knowing how to recover
  • How to develop your own toolkit for being fully prepared when put on the spot

Layout Building in Drupal, 3 PM PST

The Layout Discovery API has dramatically changed the way Drupal 8 websites are designed, built and maintained. Solutions like Layout Builder, Entity Reference with Layout, and Layout Paragraphs have added a new dimension of content presentation on top of traditional content management. With these tools content editors have more control over their online presence than ever before — but this newfound flexibility isn’t without its own challenges. Join James Nettik, Front-end Developer, as he covers the essentials of layout building in Drupal 8. This session will cover:

  • An overview of the tools available today and their pros and cons
  • How to begin working with the new Layout Discovery API
  • Tips to keep the authoring experience as intuitive as possible
  • Solutions to common questions and pitfalls while designing and building

Don’t miss your opportunity to learn the latest in Drupal, network with fellow professionals, and attend in-depth technical and management training. Register for BADCamp 2020 today. We’ll see you there!

Aug 26 2020
Aug 26

Adding SVG icons or button styles into Drupal menus can be difficult — especially if you’re trying to avoid hardcoded, fragile solutions. With the Menu Link Attributes module you can easily add custom HTML5 data attributes to individual menu links, then use a preprocessor to inject your SVG icons and button styles based on those attributes. This solution takes just a couple of minutes and should work on Drupal 8 / Drupal 9 installations.

Menu Link Attributes

Add the Menu Link Attributes module to your project via composer require drupal/menu_link_attributes, then enable the module with drush en menu_link_attributes or through the GUI on the Extend page. Once the module is enabled navigate to Structure > Menus and click the Available attributes tab. Here you’ll add YAML configuration that will describe which attribute options you’d like added to individual menu links.

Menu link attributes config The menu link attributes configurations can be found at Structure > Menus > Available attributes (tab).
    label: Icon
    description: 'Replace the text of the menu link with an icon.'
      facebook: Facebook
      instagram: Instagram
      twitter: Twitter

Paste the above YAML into the configuration textarea and click Save to create a new Icon option for menu links using the custom data-icon attribute. With this option you can add attributes to your link like data-icon=”facebook” — or whatever you define in your config YAML. In our example we’ve defined facebook, instagram and twitter.

Menu link attributes settings Menu link Attributes settings are now available on the edit screen for individual menu links using the configurations set above.

Next you’ll want to assign these data attributes to your Drupal menu items using the GUI. For this example I’ve created three new menu items in the Main navigation (machine name main) menu: Facebook, Instagram, and Twitter.

Sandbox theme homepage A custom Sandbox theme, using Bartik as a base theme, on a fresh Drupal 8.2 install.

Create an SVG Sprite

This solution assumes you’re using a sprite of SVG icons and have included them somewhere in your templates. There are many ways to do this in Drupal, and covering them here would be outside the scope of this post. For simplicity, I’ve added the following sprite at the bottom of my page.html.twig file — you can follow suit to get this example working in your project. Notice that the value of the data-icon attribute in the menu links match the IDs of the symbol elements in the sprite.

  SVG markup in page.html.twig

In my custom Sandbox theme, I've copied page.html.twig from the base theme and pasted the SVG code from above as the last line.

Inject your SVG markup with a preprocessor

In your mytheme.theme file (or sandbox.theme in my case), define the following hook to inject SVG markup in any menu item that has a data-icon attribute. As mentioned above, you’ll need to paste the SVG markup provided at the bottom of your page.html.twig file in order to see any icons actually populate.

 * @file
 * Functions to support theming in the Sandbox theme.
use Drupal\Component\Render\FormattableMarkup;
 * Implements theme_preprocess_menu().
function sandbox_preprocess_menu(&$variables, $hook) {    
  foreach ($variables['items'] as &$item) {
    $attributes = $item['url']->getOption('attributes');     
    if (isset($attributes['data-icon'])) {
      $title = new FormattableMarkup('
      ', [
        '@title' => $item['title'],
        '@icon' => $attributes['data-icon'],
      $item['title'] = $title;

In this example using Sandbox, my custom sub-theme of Bartik, I added an svg { max-width: 25px; } CSS declaration to my theme's base styles so my menu icons aren’t the size of the whole viewport.

Example homepage with SVG icons in Drupal menu links. SVG Icons in their proper place as Drupal menu items! I added a line of CSS (above) in my Sandbox theme to set the icon sizes.

Voila! Now you’ve got SVG icons in your Drupal menu links, and you can easily alter the data-icon link attributes with a point-and-click interface. Check back soon for a separate post on creating SVG sprites for your Drupal templates.

Aug 17 2020
Aug 17

Content migration into a Drupal website using spreadsheet or CSV data can be surprisingly effective — especially (counterintuitively?) with large and complex datasets. I’ve written about data migration in Drupal 8 a couple of times, but new projects keep highlighting the diversity of data sources and content configurations, reminding me over and over again that data migration doesn’t really have a one-size-fits-all solution. In this post we’ll get you from zero (fresh Drupal 8 install) to a basic CSV data migration — including entity references and multiple field values — in about 15 or 20 minutes. You can download the accompanying Aten CSV Migrate example module here, and skip straight to the instructions if you'd like.

Drupal 8 offers a handful of powerful and extensible migration modules in core. These modules lay the foundation for a wide variety of migration methods including several flavors of CSV importers like the point-and-click Entity Importer module for Drupal 8 developed by my colleague Travis Tomka. GUI powered migrations are perfect for minimally to moderately complex content, but can have a hard time crossing the finish line alone for complicated datasets.

When GUIs overwhelm: CSV or Spreadsheet content migrations

Earlier this year I began working with the National Science Foundation’s National Ecological Observatory Network (NEON) to migrate robust ecological data collected from more than eighty terrestrial and aquatic field sites across the United States into a Drupal 8 website. The bulk of the data was destined for a content type with more than 75 unique fields, and the sheer volume and complexity of the data was steering me away from point-and-click interfaces.

Luckily for me, the NEON team are old hands when it comes to spreadsheet manipulation. Their expertise and flexibility were applied to formatting a spreadsheet export of their data specifically configured for an import into Drupal. Then their spreadsheets were exported to CSV, a format simple to consume into a Drupal website with the right modules and configurations. With just a little back and forth, we were well on our way to a successful, complex data migration with minimal custom code.

The basics: Getting spreadsheet or CSV data in Drupal

A quick introduction to configuring a CSV import using the Migrate Source CSV module for Drupal 8 is warranted. Once the basics are clear, a more complex import won’t be so overwhelming. If your data is in spreadsheet format, you’ll want to export it to CSV. The example below assumes a comma delimiter, no encapsulation characters, and no escape characters. For more complex content you’ll define these attributes in the source portion of your migration yaml file. The following steps culminate in a working example CSV data migration module you can download and tinker with. Note that this first example doesn’t discuss the more complex sample below, which is also included in the download.

  1. Ensure that the core Migrate module is enabled
  2. Install and enable Migrate Source CSV, Migrate Tools, and Migrate Plus
  3. Create a new custom module (or just download my working example) which will include an info file, a migrate file, a source file, and an install file following the outline below


type: module
name: Aten CSV Migration
description: 'Aten CSV Migration example. Read more from this data migration from CSV or spreadsheet tutorial.'
package: Migration
core_version_requirement: ^8.7.7 || ^9
  - drupal:migrate
  - migrate_source_csv
  - migrate_plus

Here we simply define the module and its dependencies.


 * Implements hook_uninstall()
function aten_csv_migrate_uninstall() {

This implementation of hook_uninstall() will clean up active configuration for the example CSV data migration when the module is uninstalled.


id: aten_csv_migrate_node
label: Aten CSV Migrate example node
  - Aten Migrate CSV
  plugin: csv
  path: modules/custom/aten_csv_migrate/sources/aten_csv_migrate_items.csv
  ids: [ID]
  title: Title
  body: Description
  field_color: Color
  field_weight: Weight
    plugin: default_value
    default_value: item
  plugin: entity:node

This is the cornerstone of the migration. Using the migrate_plus.migration.my_module.yml namespace lets us hook into the power of the Migrate Plus module. You can see we define our CSV file in path and then map our fields to columns in the CSV file under process including the node type item which we’ll need to create.


100,Ball,A top quality exercise ball.,Red,4
101,Flag,The perfect flag for your collection.,Blue,1
102,Paperweight,A weight for your important papers,Black,2
103,Thermos,Liquids stay warm with this amazing product.,White,2

Some items that we’ll stuff into nodes!

Now that your code is in place, make sure that you have a content type configured to receive the content import. For this example I’m sticking with core field types and a custom node type item that matches my CSV data. Note that the field machine names match those in the process definitions of my migrate_plus.migration.aten_csv_migrate_node.yml file.

Content type Item The content type "Item" contains simple core fields and will receive the CSV data.

And here are the field configurations.

Content type Item field definitions. The "Item" content type contains the core body field, a field_color (short text) field, and a field_weight (integer) field.

Now you’re set to run your import using drush. You’ll want to clear the drupal and drush caches before attempting your import via drush cr and drush cc drush - at which point you’ll see the migrate commands are available to drush via drush list.

Now we run the migration using drush migrate:import aten_csv_migrate_node, and we should see a success message.

Command line drush commands With the module properly installed drush cr, drush cc drush, and drush migrate:import aten_csv_migrate_node should complete the example migration.

That’s it for the basic CSV data migration! You’ll now see the items defined in your CSV have populated as nodes, with all the field data mapped to the appropriate fields.

Four nodes of the content type Item successfully imported The CSV content has been imported into "Item" nodes.

And if we check inside, we'll see our individual fields migrated as we'd hoped.

CSV data imported into the fields previously defined. Our title, description, color, and weight columns have imported. Note that the ID column is simply a unique identifier, and is not imported into a node attribute.

Now that we’ve got the basics down, we can move on to exploring some real-world complexities. Here’s where manipulating the format of the data in the CSV file becomes particularly handy.

A deeper dive: Getting spreadsheet or CSV data in Drupal

Migrating CSV data into a Drupal website is perhaps the most cost effective when A) The source data is inherently complex, and B) It can be easily manipulated, reformatted and re-exported to facilitate an easier migration. In the case of NEON’s content the volume and uniqueness of data fields, their relational aspects (think tags or entity references), and their inherent complexity (like multiple values for the same field) made it a good candidate on the first account. The client team’s capacity to fiddle with formats and re-export their data to spreadsheets made it a good candidate on the second.

For more complex field types we rely on Migrate Plus plugins which will be used to populate the data. For the complex example included in the download to run successfully, you’ll need to configure a new content type complex_item with the appropriate fields. My example uses the Geofield and Address modules which allows the setup of the field_coordinates and field_address fields respectively. The rest of the fields are core.

Complex item content type field configuration The complex_item content type configuration implements core, Address and Geofield fields: field_address (address), body, field_coordinates (geofield), field_link (link), field_multiple_taxonomy_term (entity reference: term), field_single_entity_reference (entity reference: node), field_single_taxonomy_term (entity reference: term).

It’s fields like field_multiple_taxonomy_term that really shine with CSV or spreadsheet imports, in that having the client separate multiple values with a “|” in their export and then implementing the explode plugin quickly solves what could otherwise be a complex problem.

YAML configuration for import into field_multiple_taxonomy_term Code highlight is from migrate_plus.migration.aten_complex_csv_example.yml. All mentioned code is included in the Aten CSV Migrate download included with this post.

Another thing to notice in migrate_plus.migration.aten_complex_csv_example.yml is the difference between the entity_lookup plugin and the entity_generate plugin. The entity_generate plugin will search by title for a matching entity, and create one if it doesn’t exist. The entity_lookup plugin, on the other hand, skips the field if an appropriate existing entity isn’t found.

YAML configuration for import entity_lookup vs entity_generate Code highlight is from migrate_plus.migration.aten_complex_csv_example.yml. All mentioned code is included in the Aten CSV Migrate download included with this post.

The Migrate Plus module ships with an impressive collection of plugins and example code. Once you’ve gotten your feet wet, it’s likely you can find everything you need for complex data migrations from CSV within the various Migrate Plus example submodules.

There are as many ways to migrate data into Drupal as there are unique combinations of source data, client teams, and project requirements. Knowing more about the methods available to you is a great way to broaden your options and choose the right tools for each unique job. What are your go-to migration methods or tricks of the trade? I’d love to hear about them in the comments below.

Aug 07 2020
Aug 07

Get ready for the first ever fully virtual DrupalCamp Colorado, this August 14-16, 2020. This year’s DCCO is packed with more than two dozen sessions covering a wide array of topics from content strategy to accessibility, data migrations, analytics, and much, much more. The event will be broadcast via Zoom & Hopin, offering plenty of opportunity to connect, network, learn & share from the comfort of your own home. If you haven’t already, make sure to register for this free event. We’re super excited for the 2020 lineup and hope to see you there — perhaps in one of the Aten team’s sessions listed below!

Friday August 14th, 2020

Nonprofit & Government Summit, 8:30 AM

Accessibility on the web is important to everyone, but the pressure to meet accessibility standards is perhaps most keenly felt by publicly funded or government organizations. Michaela, Front-End Developer and accessibility expert, will be presenting an introduction to accessibility for the Nonprofit & Government Summit that covers fundamentals, performing audits, and a few tricks of the trade.

Saturday August 15th, 2020

Successful Projects Start With Great RFPS, 10:15 AM

A user-centered approach should take the front seat when it comes to website design and development, but what about developing RFPs for your upcoming digital project? Join Joe Crespo, Director of Accounts at Aten Design Group, as he covers how to write an RFP that communicates clearly with the users at the center of proposal writing and evaluation — your potential vendors. Learn how great RFPs lead to better proposals and more successful projects.

Social Media and Accessibility, 11:15 AM

Social media allows you to establish meaningful, productive dialogue with your end users, potential clients, content consumers or other target audiences. Can your social media speak louder, to a wider audience, and with a bigger focus on inclusion? Join Michaela, Front-End Developer and accessibility expert, as she walks through creating accessible content for major social media platforms — and why it’s important to your organization.

Don’t miss your opportunity to connect with the Aten team, the Drupal community, and the wider sphere of your colleagues in the digital services industry — register for DrupalCamp Colorado 2020 today!

Jul 23 2020
Jul 23

The Entity Extra Field module for Drupal 8 lets site builders attach blocks, views, token driven content, and entity operation links as orderable pseudo-fields to any entity’s edit form or its displays. After installing the module any user with the Administer entity extra field permission can easily configure node attributes like author or publish date as orderable fields — as well as create block fields, views fields, operation link fields (like Edit and View) or a host of other custom entity fields with a simple point and click interface.

Entity Extra Field is essentially an easy-to-use UI for configuring Drupal’s pseudo-field components that are defined and exposed through hook_entity_extra_field_info(). It puts the power and flexibility of pseudo-field elements into the hands of site builders, delivering a wide variety of new field configuration possibilities without dipping into custom code.

A quickstart example: node properties as fields

Here’s a quick example of configuring node properties as fields (or technically, pseudo-fields). Let’s say you’d like your site’s Article content type to display the author at the bottom of the post, instead of the standard display just beneath the title. With the Entity Extra Field module, you’ll be done in two minutes. First make sure you have the Token module installed on your site, then download the Entity Extra Field module via composer using:

composer require drupal/entity_extra_field

You can read about using composer to download modules & dependencies on Drupal.org. With Entity Extra Field installed, you’re ready to get started.

An article node with the author and publication date displayed beneath the article title Right out of the box, an Article node type displays the authoring information just beneath the node title.
  1. Enable both the Entity Extra Field and Entity Extra Field UI modules via drush en entity_extra_field and drush en entity_extra_field_ui or the old-fashioned way on the Extend page at /admin/modules
  2. Navigate to Content types administration at /admin/structure/types and click the Manage fields button next to Article
  3. Click on the new tab, Manage extra fields, to add your pseudo-field
  4. Click the Add extra field button at the top of the page, then fill out the form to define your new "Node author" field:
    • Field Name: Node author
    • Display Type: View
    • Description: The node’s author
    • Field type: Token
    • Field type configuration: Text field
    • Token value: Another great article by [node:author] (note that you can browse through about a billion other useful tokens via Browse available tokens)
  5. Use the Field Type Conditions options at the bottom of the page to enable your new pseudo-field for just the Article content type
  6. Finally, after saving your new "Node author" pseudo-field, head to the Manage Display tab of your Article content type and order your new field — in our case, just below the body

To complete our task, we’ll probably also want to disable Display author and date information in the Display Settings section of the Article content type Edit tab. Voila! Your node author is now a field.

An article node with the node author displayed below the body text using the Entity Extra Field module. After a few quick configuration steps, an Article node displays the custom author pseudo-field just below the body.

You could easily repeat the above steps to establish a new "Post date" field — also orderable just like the new "Node author" field — and place that beneath the title or wherever you please. It’s also worth noting that the Field Type Conditions options (step 5 above) can add a whole layer of flexibility to when and how your pseudo-fields appear.

Entity Extra Field: Taking it to the next level

Creating token fields is just the beginning. With the Entity Extra Field module you can attach any block, view (with contextual arguments), token, formatted textarea with tokens, or — thanks to recent contributions from geek-merlin — entity operation links like Edit and View to any entity type edit form or display. The result isn’t limited to super configurable entity displays — there’s a whole world of possibilities using views with arguments or custom blocks as pseudo-fields.

Example graph data rendered with the help of Entity Extra Field shows uninsured statistics by race / ethnicity. An Entity Extra Field implementation for The Commonwealth Fund's Health System Data Center uses a block pseudo-field to place dynamically rendered React charts on the node page — driven by node field data.

I originally built this module, for example, to display dynamically rendered React charts as a node pseudo-field, where the data represented in the chart is driven by the values of various fields from the node context definition. The result is an easy-to-edit node form where content managers can add or edit the statistical data that drives the charts via normal node fields — and an orderable, configurable pseudo-field on the node display that renders the chart just like a regular field without complex configurations or poking around in code.

What else can you do with the Entity Extra Field module? You decide. And if you come up with anything you’d like to share, please let me know!

Jul 16 2020
Jul 16

The Notification Message module for Drupal 8 lets content editors quickly and easily publish configurable notifications. It can create site-wide notifications, conditional alerts, or other site messages — all using a consolidated UI that doesn’t require editors to stitch together functionality with complex combinations of core and contributed modules.

Have your organization’s hours of operation changed for the holiday? Is a specific product on backorder? Has a service area been affected by a storm system? No matter who needs to read it, what it needs to say, or when it needs to be automatically published and unpublished, Notification Message makes crafting messages to users simple.

The Nashville Public Library website with a prominent notification banner deployed with the Notification Message Drupal 8 module. Nashville Public Library uses the Notification Message module for Drupal 8 to deploy notification messaging specific to distinct audience segments in a bright, clear yellow banner.

I built the Notification Message module to help Nashville Public Library broadcast site-wide or contextual messages to their customers via time-boxed notification banners. Their previous system, built on Drupal 7, used separate content types for each variety of notification, and relied on configurations completed elsewhere in the site (blocks, contexts, scheduled or manual publishing) to function properly. Notification Message provides a clean, natural editorial experience and bakes in a lot of configuration options.


Notification Message un-clutters the content management experience and provides simple but powerful tools for editors. Notifications are:

  • Published and unpublished automatically within a specified date and time range
  • Built using custom entities to maintain separation from the standard content publishing experience
  • Linked in the Content Menu right out of the box to slide naturally into the content admin UI
  • Highly configurable via conditions to show up when, how and to who you want
  • Extensible far beyond basic site-wide banner messages using custom fields, custom templates and custom conditions
  • Complete with granular permissions for both administering custom notification message types and managing notification content

Quickstart Guide

Setting up Notification Message — and your first notification — is simple. First download the Notification Message module using the composer workflow: composer require drupal/notification_message

If you need help with composer, check out using composer to download contributed modules on Drupal.org. Once the Notification Message module is available in your project, you’re ready to get started.

  1. Enable Notification Message via drush en notification_message or directly from the Extend page at /admin/modules
  2. Navigate to the Content page at /admin/content, then to the new navigation item Notification message
  3. Click Add notification message, choose the Global type (for now) and complete the entity edit form, making sure to select the appropriate theme under Notification Conditions / Current Theme, and a date & time range that includes right now under Notification Options / Message Publish
  4. After saving your notification, head to the Block layout page at /admin/structure/block and place the Notification messages block (via the Place block button) in the appropriate region

Mission accomplished! Now you’ll see your global notification in the region you assigned as long as the current date & time are within the date range you indicated in the Message Publish section of the entity edit form. You can create new notification message types from the Notification Message types page at /admin/structure/notification-message-types that can respond to diverse conditions such as Page URL, node attributes and user attributes — or any other conditions defined by your site — and can include custom fields and custom display configurations.

The Human Rights Watch website featuring a takeover lightbox delivered via the Notifications Message module for Drupal 8. Human Rights Watch used a fielded and conditioned implementation of the Notifications Message module earlier in 2020 to deliver rich form content in a Lightbox takeover to drive a donation campaign.

Custom templates for your custom notification types can override or extend the included notification-message.html.twig and notification-messages.html.twig templates for a variety of presentations — from the standard site-wide notification banner to whatever you can imagine.

Jun 10 2020
Jun 10

A few weeks ago I hosted a webinar about integrating React with Drupal as a part of the Aten at Home Webinar Series. Here’s a quick recap of what we covered, and a recording of the session. Thanks to everyone who participated!

Jump to the video.

Background Concepts

React vs Other Javascript Frameworks
While the webinar focuses on React, the concepts apply to other Javascript Libraries or Frameworks as well.

Progressive Decoupled vs Fully Decoupled
This webinar focuses on embedding apps within specific regions of a webpage, rather than building entire websites as stand-alone React apps.
Related reading: When to Consider Decoupled Drupal

JS Component vs Other Methods
There are a number of ways to integrate Javascript with Drupal. This webinar focuses on JS Component, a new developer-focused module for easily embedding Javascript applications within Drupal-rendered pages.

What We Covered

  • For Progressively Decoupled Drupal 8 sites, I recommend using the JS Component module. You can find documentation and examples on the module page.
  • Once the module is installed there is no user interface. You use JS Component by adding a .js_component.yml file to your custom module or theme. You can also use JS Component in a custom module by including a boilerplate .info.yml file and .js_component.yml file to define your individual JS components.
  • The .js_component.yml file leverages the libraries directive and works very similarly to attaching libraries in Drupal. However, JS Component allows you to define/create a single or multiple Javascript components and with those components you define the JS and CSS dependencies.
  • Once you create a JS component you’ll be able to add your React app as a block and manage it the same way you would other Drupal blocks: with Layout Builder, from the Manage blocks page, as a paragraph using the Block Field module, or with code in a twig template file.
  • In the .js_component.yml file you can define the root_id and mount your React/JS app to a unique ID on the page. This means you can add multiple React/JS apps to the same page without worrying how they all will mount to the same ID.
  • Also within the .js_component.yml file you can add custom settings that will be available to the React/JS app via the window settings object. These custom setting values are fields available when adding the block to the page. For example you could add a select field that changes the theme for a React app.

Watch the Recording Online


How can I configure JS Component to load externally hosted JS files?
Since the JS Component module is using the Libraries directive it works the same where you can use external libraries/files. Here’s a link in the Drupal docs that covers this.

How is JS Component different from the Drupal Libraries API?
JS Component uses the libraries directive and adds additional functionality. For example, creating a JS Component exposes your app as a block, making it easier to place your app anywhere on your site using existing Drupal layout tools (Layout Builder, Manage Blocks screen, etc.). Also it gives you the ability to to add custom settings that can be passed down to your app. Finally it also creates a consistent and organized way to add React/JS apps.

Does each component have its own namespace in drupalSettings? that is - if you had 2 blocks they could each have their own react_title for example
Yes, each component is name spaced using their component id.

Is there a postbuild for windows?
I don’t develop using Windows, but I would assume you could use the Linux subsystem and it should work.

What’s the future of the JS Component?
The primary goal for JS Component is to make it incredibly easy to embed Javascript applications within the context of Drupal-rendered pages. As Drupal becomes even more flexible with tools like Layout Builder and support for RESTful applications, look for even more powerful data providers in JS Component to integrate Drupal with your embedded Javascript applications.

Have you experienced any challenges using the JS Component module?
Since the data in the window object is not immediately available to the React/JS app, you need to create a function that waits for the data to be ready before you can rely on using it.


Here’s a link to an example code repo: https://github.com/AtenDesignGroup/js_component_examples

More Questions?

We’d love to address your questions in the comments section below.

Apr 20 2020
Apr 20

More than two years ago I wrote about Drupal’s much-improved upgrade path and what it means for the future. What I wrote then is still true today: after Drupal 8, upgrading to new major versions (Drupal 9, Drupal 10, etc.) will be much, much easier than it was in the past. The difference will be night and day. That’s great news for all the poor folks still suffering PTSD from their last major Drupal migration.

Now Drupal 9 is right around the corner and it’s time to make sure you’re ready. Here’s a quick run-down on how to prepare for Drupal 9.

If you’re running Drupal 8 right now:

Upgrading to Drupal 9 should be as simple as any minor release update (i.e. upgrading from Drupal 8.7 to 8.8). You’ll just need to make sure your codebase is up-to-date with the latest versions and APIs. Here’s a quick and simple checklist to make sure you’re ready for Drupal 9 (this assumes you’re currently on Drupal 8, using a composer-based setup, and have the drush command line utility installed).

  • Keep Drupal core updated to the most recent stable version (as of today that’s Drupal 8.8.8). In most cases, using composer update drupal/core and drush updatedb will do the trick.
  • Likewise, keep contributed modules up to date. Use composer outdated to list available updates, and composer update drupal/[module name] to upgrade modules selectively. Alternatively, you can bulk update everything with composer update. After updating modules, run drush updatedb to perform any necessary database updates.
  • Test your updated website. Automated tests are a huge help, but depending on what exactly was updated and how large your website is, you might also get by with just clicking around and making sure things work.
  • Update your custom code. There are a number of tools available for finding outdated code in your website. Matt Glaman’s “drupal-check” identifies deprecated code in your Drupal 8 codebase. Drupal rector helps automatically update outdated code to the latest, Drupal 9 -compatible alternative.
  • Rinse and repeat. It’s a good idea to keep things updated monthly, and of course whenever there are security-related updates.

If you’re not running Drupal 8 right now:

First, the bad news: just like migrating to Drupal 6 or 7 before, migrating to Drupal 8 is a serious undertaking. Think “software development project” rather than “product upgrade.” Considering the magnitude of the effort, this is a good time to revisit your overarching digital strategy, approach to user experience, and content authoring workflow.

Some good news: With powerful new features, faster-than-ever load-times, and a radically improved upgrade path, Drupal 8 (and Drupal 9) is worth the effort. Even better: as long as you keep your website up-to-date, migrating to the latest version of Drupal will be the last difficult Drupal migration project you ever do.

Need help?

If you’re running Drupal 8: We provide regular, monthly updates for Drupal core, contrib, and custom code. Not only does that help keep your website running smoothly and securely, but it keeps you ready for Drupal 9. Just get in touch and let us know you’re looking for help with monthly Drupal updates.

If you’re not running Drupal 8: We help organizations of all sizes plan, design, and execute Drupal 8 migrations. Drupal 8 migrations aren’t easy, but they’re worth the effort. Get in touch and we’ll share some of our favorite new features for Drupal 8 – like workflow management and drag-and-drop page building. This would be a good time to revisit your overarching digital strategy and approach to user experience.

Want to learn more about getting ready for Drupal 9? 

Contact US

About Drupal Sun

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

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

See the blog post at Evolving Web

Evolving Web