Sep 03 2019
Sep 03

Debugging is not something us developers look forward to. Developer detest bugs but to be able to build a fine quality software, debugging is an indispensable part of a developer’s life. Every PHP developer has a different style and go-to methods for debugging their code. This depends on their experience, their problem-solving approach and most importantly - the amount of time they have in hand! 

How important is debugging and why do you need to debug your code? 

Debugging is an integral part of a software development life cycle that assures quality results. 
Picture this - The codebase is big, You are new to the project, You do not have much details of the project/functionality. But you are supposed to fix a bug. Where do we start from? We start by analyzing the code step by step to understand what is done and where things are going wrong. That, my friends, is Debugging. Debugging is an art that can get better with practice and experience.

How to debug your PHP code

Okay so here is a case that I have come across in my development career. There is a commerce site built on Wordpress in which the checkout process was taking around 5-8 minutes and I was asked to solve it. In this case, I don’t have much knowledge on how things work with Wordpress. So I started with checking off the options from the list one by one such as, (a) Is it because of some plugin? (b) Is it Theme related? (c) Is it any custom code base? etc. 

The tool that helped me in php debugging and solving this case is Blackfire. This gives you a more user-readable option of the stack trace of all the functions, the time taken for each function in the whole process. By using this, I found the function that is eating up the checkout process. All you need is some setup to add the key to your code base and you are all set to analyse any functionality using the documentation.  
So, you can solve the bugs if you have knowledge on multiple methods of php debugging.

Code Debugging Techniques

Let me talk about a few techniques that I have used for debugging PHP.
A simple and most common way to check if the function or the method you have written is being called up, write an exit. There wouldn’t be any developer who hasn’t used this!
To check the value of some variable, print_r(), var_dump(), var_export(). Okay, let’s see the difference.


Assume an array 
$a = array( 1, array( "a", "b") );

    [0] => 1
    [1] => Array
            [0] => 'a'
            [1] => 'b'
    [0] => 1
    [1] => Array
            [0] => 'a'
            [1] => 'b'

This gives a human-readable format and information about the variable. Also, we can store it to a variable with print_r($var, true).

var_dump( $a );
array(3) {
  array(2) {
    string(1) "a"
    string(1) "b"

This prints along with type, length of each value. And this is faster comparatively to print_r()
 var_export( $a );

array (
  0 => 1,
  1 => 
  array (
    0 => 'a',
    1 => 'b',

This prints along with type, length of each value. And this is faster comparatively to print_r()

var_export( $a );

This returns valid php, if variable exists, else returns false. Which means, the output of var_export can be used directly in a php file.

Have you ever made use of debug($var, NULL, TRUE) provided by Drupal core? This uses print_r() or var_export based on the arguments passed to the php debug function.

What about the warnings like below, which you don’t have a clue on which line of code is causing such a warning.

warning: Invalid argument supplied for foreach() in /modules/node/node.module on line 485.

We know that there are so many places that the node module will be called. So, how do you resolve this? One faster way without using any other external resources is using PHP function debug_backtrace(). Go to “drupal_set_message”, because you know, this is the method that is printing the warning. Put the below line, in that function



    [0] => Array
            [file] => /includes/
            [line] => 552
            [function] => drupal_set_message
            [args] => Array
                    [0] => warning: Invalid argument
supplied for foreach() in /modules/node/node.module on line 504.
                    [1] => error


    [1] => Array
            [file] => /modules/node/node.module
            [line] => 504
            [function] => error_handler
            [args] => Array
                    [0] => 2
                    [1] => Invalid argument supplied for foreach()
                    [2] => /modules/node/node.module
                    [3] => 504
                    [4] => Array
                            [param] => 
                            [revision] => 
                            [reset] => 



    [2] => Array
            [file] => /sites/all/modules/custom/custom_module/
            [line] => 10
            [function] => node_load
            [args] => Array
                    [0] => 


    [3] => Array
            [file] => /includes/
            [line] => 365
            [function] => custom_module_form_alter
            [args] => Array

This function shows the stack of all the functions that are called in the process of causing the warning. Make sure you restrict the limit, otherwise PHP shows a “memory exhausted” message if the stack takes too long to be displayed.

Debugging through CLI:

Heard of phpdbg! Yes, there is a php extension that is available from PHP 5.6+ which is used to debug a php file from command line.
Open you terminal, enter “phpdbg”. This starts  an interactive php debugger shell. You can also use breakpoints! Just try it out - the hidden way of debugging PHP. 
The only problem is: you will have to get used to the commands of phpdbg to make better use of it.

Debugging through Drupal:

Devel Kint:

Drupal developers use this pretty often. Kint is a submodule of the Devel module that can be used to debug Drupal 8 twig templates together with dump(); 

DB Log: 

Who is not aware of this Drupal module?! In D7 it is watchdog() and D8 it is logger service.


But the only reason why we don’t encourage the use of this module even though we are in love with this is that the log message is written into the database every time!

And imagine if it is a huge database, this would be even worse and will affect the performance. That’s the reason, it is not recommended to use DBLOG module on Production sites.

Do you still want to use DBLog, module and reduce the performance impacts? There is a solution for that as well - DBlog Filter. This is a contributed module which helps in restricting the type of logs to be written into the database. For example, if you want to store only logs of severity “error”, you can configure them with this module. So you don’t have to completely get rid of Dblog module. Oh yes, and this module is contributed by me ;) 

Web profiler

Web profiler is a contributed module provided by Devel again. Once you have the module enabled, you will see a report at the bottom of the window. Whenever a page is loaded, this report gives us the page load time, number of queries running in the page, number of forms, number of js/css files, etc. in that page.

web profiler

Yes, This even offers details of each section by clicking on them. For example, the following image shows the queries in the home page.


XDebug - Debugging through IDE:

The best and more user-friendly way of debugging most of the people prefer if they are using an IDE for coding is using XDebug. XDebug is a PHP extension that helps in the development and debugging and provides a single step debugger that you can use with an IDE like PHPStorm. Of course to get the best results, you have to put more effort to install and configure the extension with the IDE you are using.

Sep 03 2019
Sep 03

The ADCI team keeps the tradition of organizing Drupal Cafe. It’s a great opportunity for networking, learning new information and improving competence. Drupal Cafe celebrated its round anniversary! We organized the 20th event, where we kept sticking to our high standards of sessions' quality.  

5 speakers told us about:

  1. Data science. The influence of mathematical, philosophical phycological problems during constructing Artificial Intelligence models.

  2. Drupal components. How a component approach to front-end developing helps to improve relationships between front- and back-end developers.

  3. React/Redux apps unit tests - effective approaches and cases.

  4. How to solve the tasks that suck: tips which help to save work time and be effective.

  5. How not to burn out. How to keep a healthy attitude to the work and refill your resources.

Many Q&A after each lection tell us about what smart and engaged audiences attend our events.

Sep 03 2019
Sep 03


The Drupal CMS is one of the most secure CMSs.

Advantage: the Drupal security team constantly tests the performance of new modules and helps developers to fix errors in the code.

Note: Drupal is used to host government websites such as a website of the Prime Minister of Canada or a website of the French government.

System update


A WP system update can be done in a few clicks from the WordPress control panels. 

Advantage: the massive WP community will help to resolve any issue.


An update of this system can be difficult if you are not a website developer. 

Note: You will not be able to update Drupal from the user interface, you will have to find a professional specialist for help.

What kind of websites can be made on each platform


Personal branding websites, websites for freelancers and bloggers, small businesses, consulting services (finance, marketing, advertisement), etc. 


Digital service providers, travel and tourism websites, websites for creative agencies, educational websites and e-learning platforms, governmental websites, news and entertainment websites, healthcare websites.  

Here is a tip! Make sure you know the exact goals of your business website, learn essential information about platforms under consideration, and then make a decision which platform to use.


Drupal is a multifunctional and secure CMS. It is translated into 110 languages ​​and allows you to implement any project you may think of. E-commerce websites, social networks, large corporate sites have been successfully created on Drupal. Drupal was created by professionals for professionals. You can create large projects with a unique set of functions, but you will have to spend time learning or finding a web developer for help. 

If you don’t want to waste time learning, WordPress will be the best choice for building your first website. The WordPress platform is available for users with any level of knowledge. Just find the right combination of plugins, choose a theme and high-quality hosting, then you can create large and customizable websites, but do not forget about security, especially if you plan to create a website for your business.

To learn more about Drupal, we recommend you to read Why you should migrate your site to Drupal


Liked the article? Twit @adcisolutions and let us know what you think about this article on Twitter.  

Sep 03 2019
Sep 03

I’ll admit to having watched a few episodes of Marie Kondo’s show on Netflix. She has definitely inspired some of the downsizing my wife and I done over the last few years. I even applied her thought process to my personal website. When I moved it to a new host I thought about how much of the content on it was not sparking joy.  If I didn't really care about stuff did my readers?

This thought process is probably even more valuable for a large business-focused Drupal site than it was for my goofy personal website.

Kondo's six principles for tidying up your house are:

  1. Commit yourself to tidying up.
  2. Imagine your ideal lifestyle.
  3. Finish discarding first.
  4. Tidy by category, not location.
  5. Follow the right order.
  6. Find joy.

Commit yourself to tidying up

This one is pretty obvious. Make a plan or create a schedule with a hard due date for a wide, sweeping content audit. Require every department to provide a list of their content that needs to stay. Question why stuff needs to stay on the site. "Because it's always been there" is not an acceptable answer.

Image your ideal lifestyle

If we substitute website for lifestyle this one starts to be helpful. What websites do you love? How can you apply inspiration from those websites  to your site?

Finish discarding first

This one is important. Migrating content to a new CMS or new website is expensive. Don't pay to move content that doesn't need to be there. Make sure the timeline requires the content audit to be done first, prior to migrating to the new site.

Tidy by category, not location

Don't worry about whether or not press releases deserve a place in the top-level navigation. Worry about whether or not press releases need to be on the site at all. When is the last time somebody other than a Googlebot visited the 2005 press release archive? If regulatory or other pressures force you to keep them around, do they need to actually be on the site? Consider options, such as keeping the last two years of press releases on the site, and drop everything else into a public Dropbox folder.

Then repeat the above process for every other category of content on your site.

Follow the right order

With houses, Kondo recommends clothes, books, papers, miscellany, and finally sentimental items. In our house, we still haven't gotten through eight boxes of loose photos because every time I start, I waste three hours looking at old pictures, without making any decisions. This is why sentimental stuff needs to come last. For your website, maybe you want to follow the 80 / 20 rule. First, clean out 80 percent of the content that gets no action. As you are doing so, be mindful of SEO and any decisions that might undermine strategies for how search engines treat your site. 

Find joy

OK, does any website really spark joy? Well, maybe XKCD does. The annual blog post recapping the company retreat may not spark any real business value, but it may spark a smile when you remember it. That's okay. You can keep those posts.

Finally, remember to greet your website and thank the content that you are removing, like Marie does when she enters a house or determines an old sweater can go.  

Not exactly sure how this relates, but I needed an ending.

If you need help wrangling your content or migrating to a new site, get in touch. We can help!

Sep 02 2019
Sep 02

In previous posts we introduced the concept of defining migrations as configuration entities. These types of migrations can be executed from a user interface provided by the Migrate Tools module. In today’s article, we will present the workflow to import configuration entities and execute migrations from the user interface. Let’s get started.

Important: User interfaces tend to change. In fact, Migrate Tools recently launched a redesign of the user interface. Screenshots and referenced on-screen text might change over time. Some exposed settings might work, but give no feedback indicating a successful outcome. Some forms might only work with specific versions of modules. The goal is to demonstrate what is possible and what are the limitations of doing so. In general, executing migrations from the command line offers a better experience.

Getting the example code

You can get the full code example for today’s example at The module to use is `UD configuration group migration (JSON source)` whose machine name is `ud_migrations_config_group_json_source`.  It comes with three migrations: `udm_config_group_json_source_paragraph`, `udm_config_group_json_source_image`, and  `udm_config_group_json_source_node`. Additionally, the demo module provides the `udm_config_group_json_source` group.

You could install the module as we have done with every other example in the series. Instructions can be found in this article. When the module is installed, you could execute the migrations using Drush commands as explained in this article. But, we are going to use the user interface provided by Migrate Plus instead.

Importing configuration entities from the user interface

The first step is getting the configuration entities into Drupal’s active configuration. One way to do this is by using the "Single item" import from the "Configuration synchronization" interface. It can be found at `/admin/config/development/configuration/single/import`. Four configuration items will be imported in the following order:

  1. The `udm_config_group_json_source` using "Migration Group" as the configuration type.
  2. The `udm_config_group_json_source_image` using "Migration" as the configuration type.
  3. The `udm_config_group_json_source_paragraph` using "Migration" as the configuration type.
  4. The `udm_config_group_json_source_node` using "Migration" as the configuration type.

When importing configuration this way, you need to select the proper "Configuration type" from the dropdown. Otherwise, the system will make its best effort to produce a valid configuration entity from the YAML code you paste in the box. This can happen without a visual indication that you imported the wrong configuration type which can lead to hard to debug errors.

Image removed.

Note: If you do not see the "Migration" and "Migration group" configuration types, you need to enable the Migrate Plus module.

Another thing to pay close attention is changes in formatting when pasting code from a different source. Be it GitHub, your IDE, or an online tutorial, verify that your YAML syntax is valid and whitespaces are preserved. A single extraneous whitespace can break the whole migration. For invalid syntax, the best case scenario is the system rejecting the YAML definition. Otherwise, you might encounter hard to debug errors.

In today’s example, we are going to copy the YAML definitions from GitHub. You can find the source files to copy here. When viewing a file, it is recommended to click the "Raw" button to get the content of the file in plain text. Then, copy and paste the whole file in the designated box of the "Single item" import interface. Make sure to import the four configuration entities in the order listed above using the proper type.

Image removed.

To verify that this worked, you can use the "Single item" export interface located at `/admin/config/development/configuration/single/export`. Select the "Configuration type" and the "Configuration name" for each element that was imported. You might see some extra keys in the export. As long as the ones you manually imported are properly set, you should be good to continue.

Note that we included `uuid` keys in all the example migrations. As explained in this article, that is not required. Drupal would automatically create a `uuid` when the configuration is imported. But defining one simplifies the update process. If you needed to update any of those configurations, you can directly visit the "Single item" import interface and paste the new configuration. Otherwise, you would have to export it first, copy the `uuid` value, and add it to the code to import.

Executing configuration entities from the user interface

With the migration related configuration entities in Drupal’s active configuration, you should be able to execute them from the user interface provided by Migrate Tools. It is available in  "Manage > Structure > Migration" at `/admin/structure/migrate`. You should see the `UD Config Group (JSON source)` that was imported in the previous step.

Image removed.

Note: If you do not see the "Migration" link in "Manage > Structure" interface, you need to enable the Migrate Tools module.

This user interface will list all the migration groups in the system. From there, you can get to the individual migrations. You can even inspect the migration definition from this interface. It is important to note that only migrations defined as configuration entities will appear in this interface. Migrations defined as code will not be listed.

Image removed.

For the `udm_config_group_json_source` group, click the "List migrations" button to display all the migrations in the group. Next, click the "Execute" button on the `udm_config_group_json_source_image` migration. Then, make sure "Import" is selected as the operation and click the "Execute" button. Drupal will perform the import operation for the image migration. A success status message will appear if things work as expected. You can also verify that images where imported by visiting the files listing page at `/admin/content/files`.

Repeat the same process for the `udm_config_group_json_source_paragraph` and `udm_config_group_json_source_node`migrations. The final result will be similar to the one from the JSON source example. For import operations, the system will check for migration dependencies and execute them advance if defined. That means that in this example, you could run the import operation directly on the node migration. Drupal will automatically execute the images and paragraphs migrations. Note that migration dependencies are only executed automatically for import operations. Dependent migrations will not be rolled back automatically if the main migration is rolled back individually.

This example includes a paragraph migrations. As explained in this article, if you rollback the node migration, any paragraph associated with the nodes will be deleted. The Migrate API will not be aware of this. To fix the issue and recover the paragraphs, you need to rollback the paragraph migration as well. Then you re-import the paragraph and node migrations again. Doing this from the user interface involves more manual steps compared to running a single Drush command in the terminal.

Limitations of the user interface

Although you can import and execute migrations from the user interface, this workflow comes with many limitations.The following is a list of some of the things that you should consider:

  • Updating configuration in production environments is not recommended. This can be enforced using the Configuration Read-only mode module.
  • If the imported configuration entity did not contain a `uuid`, you need to export that configuration to get the auto generated value. This should be used in subsequent configuration import operations if updates to the YAML definition files are needed. Otherwise, you will get an error like "An entity with this machine name already exists but the import did not specify a UUID."
  • The following operations to not provide any user interface feedback if they succeeded: "Rollback", "Stop", and "Reset". See this issue for more context.
  • As of this writing, most operations for CSV sources fail if using the 8.x-3.x branch of the Migrate Source CSV module. See this issue for more context.
  • As of this writing, the user interface for renaming columns in CSV sources produces a fatal error if using the 8.x-3.x branch of the Migrate Source CSV module. See this issue for more context.
  • As of this writing, it is not possible to execute all migrations in a group from the user interface in one operation. See this issue for more context.
  • The Migrate source UI module can be used to upload a file to be used as source in CSV migrations. As of this writing, a similar feature for JSON and XML files is not working. See this issue for more context.

To reiterate, it is not recommended to use the user interface to add configuration related to migrations and execute them. The extra layer of abstractions can make it harder to debug problems with migrations if they arise. If possible, execute your migrations using the commands provided by Migrate Tools. Finally, it is recommended to read this article to learn more about the difference between managing migrations as code or configuration.

What did you learn in today’s blog post? Did you know you can import migration related configuration entities from the user interface? Did you know that Migrate Tools provides a user interface for running migrations? Share your answers in the comments. Also, I would be grateful if you shared this blog post with others.

This blog post series, cross-posted at as well as here on, is made possible thanks to these generous sponsors. Contact Understand Drupal if your organization would like to support this documentation project, whether it is the migration series or other topics.

Sep 02 2019
Sep 02

The Drupal 8 Allowed Formats module allows you to configure what text formats are available for each field. By default, all the text formats a user has permission to use are available for every field that uses text formats. Sometimes you want a field to have html, but have a more limited set of html tags. This can easily be accomplished by creating a new text format and using the Allowed Formats module to limit the field to using that text format.

Download the Drupal 8 Allowed Formats module.

composer require drupal/allowed_formats

Install the Drupal 8 Allowed Formats module.

Go to Admin > Structure > Content Types and select Manage Fields. If you edit the Body field you will see an Allowed formats section that allows you to specify what formats you can use on this

Allowed formats checkboxes

This means you could easily create a new field on a content type and set it to only allow the Restricted HTML text format. You could also create a new text format that could be used on specific text fields.

Sep 02 2019
Sep 02

Drupal 8.7.7 expected later this week is the first Drupal release to support extensions compatible with multiple major versions of Drupal. This is huge!

Drupal 9 is planned for June 3, 2020 and we are aiming to make the transition as smooth as possible. In fact we build Drupal 9 in Drupal 8 with API deprecations and optional support for new dependencies (Symfony 4.4 is getting very close, while Drupal 8.7.0 was already Twig 2 compatible). Extensions following these deprecations and making sure they are compatible with the updated dependencies could have codebases that are both compatible with Drupal 8 and 9 at the same time, meaning less support burden and earlier Drupal 9 compatibility. In March 48% of contributed projects on were already "Drupal 9 compatible" (as we could detect at the time), and that increased 54% by July (highfive!). These projects will now have one more thing to do, a one line info.yml file addition, to allow their existing codebase to also run on Drupal 9.

✋Drupal contrib maintainers, thank you! You are already contributing a lot to a successful Drupal 9. Projects that are "compatible with Drupal 9" (as much as we know now) are up to 54% from 48% since March. Deprecated API use is decreasing overall.

You are awesome, keep it up!

— Gábor Hojtsy (@gaborhojtsy) August 2, 2019

The core: 8.x key did not cut it anymore

Drupal 8 looks at extension .info.yml files and checks for the core: 8.x key to check if the extension can be used with Drupal 8. Unfortunately this was not adequate already due to API additions in Drupal 8 minor releases. You could not specify an extension was only compatible with Drupal 8.4+. People devised clever tricks with dependency on certain versions of the system module, but that was still limiting due to inability to depend on specific patch releases. In case your extension depended on a bugfix being present, you cannot set a dependency on Drupal 8.4.1+ in any way.

Introducing the core_version_requirement key

While solving this issue it became apparent that solving it with the existing core: 8.x key is going to cause backwards compatibility problems with existing Drupal 8 sites. The format of the value could not be changed without causing issues, so a new core_version_requirement key was introduced. This now allows to depend on major and minor versions of core as well as specify multiple version requirements even between multiple minor Drupal versions. For example if you would need a bugfix that is to be included in both Drupal 8.7.23 and 8.8.3 (imaginary future versions) but you wouldn't care for the minor version, then you would use the following, making your module incompatible with versions before the particular bugfix you need on both minor branches, as well as incompatible with all older Drupal 8 branches:

name: My Module
type: module
core_version_requirement: ~8.7.23 || ~8.8.3

Such precision was never possible before!

The new feature is made available in 8.7.7 to help prepare for Drupal 9, as this makes it possible to also declare Drupal 9 compatibility with the existing codebase you already have. Drupal 8.7.x will get security support up until the planned release of Drupal 9 on June 3, 2020. For extensions that only support Drupal 8.7.7 and later you can now exclusively use the core_version_requirement key. If the extension is also Drupal 9 compatible:

name: My Module
type: module
core_version_requirement: ^8.7.7 || ^9

For extensions that also support older versions, you should keep the core: key as well. The core_version_requirement key will be ignored by older Drupal versions, and new versions will validate that you specified non-conflicting requirements in the two keys (with regards to Drupal 8 support) so for extensions supporting older core versions, core_version_requirement also needs to be permissive, but could also allow compatibility with Drupal 9 too:

name: My Module
type: module
core: 8.x
core_version_requirement: ^8 || ^9

Read more about this change in the change notice. There is also work ongoing to support dependency metadata from composer.json to drive Drupal's dependency resolution as well. That will coexist with this simpler approach and will provide a more composer-native solution for those who already adopted composer for their extensions. In the meantime at least core_version_requirement will limit what Drupal would install while composer.json requirements will limit what composer will download. Because both Composer and Drupal use the term install, but those don't mean the same thing, here is a comparison chart:

  core: 8.x system module dependency core_version_requirement composer.json dependencies Can be used from Drupal 8.0.0+ Drupal 8.0.0+ Drupal 8.7.7+ Drupal 8.0.0+ Allows minor version precision No Yes Yes Yes Allows patch version precision No No Yes Yes Allows multiple constraints No No Yes Yes Limits composer install (download) No No No Yes Limits Drupal 8 install Yes Yes Yes No, unless explicit support is added. Allows Drupal 8 and 9 install with same codebase No No Yes No, unless explicit support is added.

What happens to project version numbers then?

So a 8.x-1.3 version of an extension on may only be compatible with a subset of core, but that was already the case earlier. Now an 8.x-1.3 version of an extension on may also be compatible with Drupal 9. How will this work? Drupal's composer integration already ignores the 8.x prefix from version numbers and only cares about the project specific version. Drupal core already only installs extensions where the core compatibility requirements are met regardless of which version number was the package you used to download (8.x modules may be only compatible with 8.4+ already). So the ultimate plan is to do away with the 8.x prefix in extension numbers entirely on and support semantic versions for contributed extensions instead. In the short term, the project browser also needs to be updated to take the dependency metadata and use that to power compatibility filters, instead of merely using the version number prefix.

Sep 02 2019
Sep 02

Software solutions come in all shapes and sizes. Perhaps you’re looking for software that will help you build valuable links back to your company. Or maybe, you need a custom CRM to manage all of your valuable patrons. Either way, it’s vital to find a reliable technical partner to make your software solution dreams a reality.

At Vardot, we understand that all web development is not one-size-fits-all. We know exactly how can help your organization transform its website to meet the demands on the digital landscape. Our solutions help increase and refine distinguished companies’ digital presence through Drupal, a powerful open-source CMS.

In acknowledgment of our efforts, we’ve been recognized by Clutch, as one of the top developers in Jordan! We’d like to thank our valued customers for participating in brief client interviews on our behalf. We’ve been awarded a 4.9-star rating (Out of a possible 5 stars). We’re excited to keep this momentum going and maintain ourselves as a top provider in our field! Check out a recent review below!

Clutch Reviews of Vardot

“We are honored and pleased to see our team's innovation and hard work recognized.” – Mohammed Razem - CEO, Vardot.

Clutch is an objective resource for business-to-business services. The platform lauds a unique rating methodology that objectively reviews similar companies. The Manifest’s directory also features us a top Drupal development company. For those unfamiliar, The Manifest is a sister site of Clutch that specializes in business news. Another great resource and Clutch sister site is Visual Objects. Each Visual Objects profile features a catalog of businesses’ visual work.

If you’re interested in learning more about how we can help maximize your Drupal success, drop us a line today!

Sep 02 2019
Sep 02

The first step is to download the Drupal 8 Scheduler module and install it. Downloading the module is easy with composer:

composer require drupal/scheduler

In this example, we are only going to cover the Scheduler module. The module comes with a Scheduler Rules Integration module that can be used to integrate Scheduling conditions, actions, and events with the Drupal 8 rules modules.

Drupal Scheduler Module module page

If you navigate to the User permissions page, you can see there are three permissions for the Scheduler module. Typically, you will allow your content editors to schedule content to be published and possible see the list of all content that is scheduled.

Drupal Scheduler Module permissions page

In the Admin menu, navigate to Configuration > Content authoring > Scheduler to get to the Scheduler settings page. Here you can set it up so a content administrator only has to enter the date and the content will be published at a default time. This is useful if you always want content to be published at the same time of day. For now, leave everything at the default.

Drupal Scheduler Module settings page

Click on the Lightweight cron menu item from the Scheduler settings page. If you are only scheduling content to be published occasionally and don’t care if it’s published at exactly the correct time, then you will not need to worry about this admin page. If you need more fine grained control and would like up to the minute publishing, this page provides useful information.

By default, the scheduler actions happen on the default Drupal cron run. Typically you will set up cron to run every hour or possibly once a day, depending on your site needs. The Scheduler module provides a more lightweight cron process available at a callback URL that only runs the scheduler instead of all the default Drupal cron hooks. This makes it more efficient for up to the minute publishing.

Drupal Scheduler Module lightweight cron page

Navigate to Admin > Structure > Content Types. Select Edit on one of the content types you would like to allow scheduling on. In this example, we will use the Article content type.

Content Type Edit

Click on the Scheduler section. Here you can turn on the ability to publish or unpublish this type of content using the Scheduler module. You can specify that creation time should match the publishing time, require that the content be scheduled, and even make sure a new revision is created when the content is published. You can also change how the scheduler options appear on the node edit page (when creating or editing content). For now, just check to turn on Publishing and to change the content creation time to match the scheduled publish time. Then click the Save content type button.

Drupal Scheduler content type options

Now create a new Article and set the Scheduling date and time. Make sure the Article is unpublished and save it. Once that date and time passes and the Drupal cron process runs, this new Article will now be published! Keep in mind, the date/time is based on your site’s timezone settings.

Drupal Scheduler options

You can go to the Content admin page and click the Scheduled menu tab to view all the scheduled content on your site.

As you can see, it’s incredibly easy to set up and start using the Scheduler module. You should now be able to empower your content editors to schedule their content to be

Aug 31 2019
Aug 31

Make sure to download the Quicklink module using composer.

composer require drupal/quicklink

Enable the module just like you enable any other module.

Head on over to the configuration page at Admin > Configuration > Development > Performance > Quicklink.

In the Prefetch Ignore Settings section, you can configure what Quicklink should not prefetch. You can specify URL patterns on this page that should be ignored.

Quicklink Settings

In the Optional Overrides section, you can configure some various override options such as the parent CSS selector for the prefetch links, the allowed domains, and prefetch paths.

Quicklink Settings

In the When to Load Library section, you can control when QuickLink will be loaded on the page. You can even specify for it not to load on specific content type pages.

Quicklink Settings

The Extended Browser Support section allows you to load the Intersection Observer polyfill which allows quicklink to work in IE11 and some older browsers.

Quicklink Settings

The last section allows you to enable debug mode. For the most part, the defaults work well so leave everything at the default.

Quicklink Settings

To test this out, you will want to make sure you have a webpage with multiple links on it. A blog listing page works well. In my example, I used the Devel Generate module to generate a bunch of Article content to fill up my homepage.

Next make sure you are logged out. I recommend using an incognito or private browsing window. Open up your developer tools and go to the Network tab. Now refresh the page, wait for everything to load and start scrolling. You will notice that the network tab shows additional activity as the links are pre-fetched.

Aug 31 2019
Aug 31

I’ll admit to having watched a few episodes of Marie Kondo’s show on Netflix. She has definitely inspired some of the downsizing my wife and I done over the last few years. I even applied her thought process to my personal website. When I moved it to a new host I thought about how much of the content on it was not sparking joy.  If I didn't really care about stuff did my readers?

This thought process is probably even more valuable for a large business-focused Drupal site than it was for my goofy personal website.

Kondo's six principles for tidying up your house are:

  1. Commit yourself to tidying up.
  2. Imagine your ideal lifestyle.
  3. Finish discarding first.
  4. Tidy by category, not location.
  5. Follow the right order.
  6. Find joy.

Commit yourself to tidying up

This one is pretty obvious. Make a plan or create a schedule with a hard due date for a wide, sweeping content audit. Require every department to provide a list of their content that needs to stay. Question why stuff needs to stay on the site. "Because its always been there" is not an acceptable answer.

Image your ideal lifestyle

If we substitute website for lifestyle this one starts to be helpful. What websites do you love? How can you apply inspiration from those websites  to your site?

Finish discarding first

This one is important. Migrating content to a new CMS or new website is expensive. Don't pay to move content that doesn't need to be there. Make sure the timeline requires the content audit to be done first, prior to migrating to the new site.

Tidy by category, not location

Don't worry about whether or not press releases deserve a place in the top-level navigation. Worry about whether or not press releases need to be on the site at all. When is the last time somebody other than a Googlebot visited the 2005 press release archive? If regulatory or other pressures force you to keep them around, do they need to actually be on the site? Consider options, such as keeping the last two years of press releases on the site, and drop everything else into a public Dropbox folder.

Then repeat the above process for every other category of content on your site.

Follow the right order

With houses, Condo recommends clothes, books, papers, miscellany, and finally sentimental items. In our house, we still haven't got through the eight boxes of loose photos because every time I start, I just waste three hours looking at old pictures, without making any decisions. This is why sentimental stuff needs to come last. For your website maybe you want to follow the 80 / 20 rule. First, clean out 80 percent of the content that gets no action. As you are doing so, be mindful of SEO and any decisions that might undermine strategies for how search engines treat your site. 

Find joy

OK, does any website really spark joy? Well, maybe XKCD does. The annual blog post recapping the company retreat may not spark any real business value, but it may spark a smile when you remember it. That's okay. You can keep those posts.

Finally, remember to greet your website and thank the content that you are removing, like Marie does when she enters a house or determines an old sweater can go.  

I have no idea what that means, but I needed an ending.

If you need help wrangling your content or migrating to a new site, get in touch. We can help!

Aug 30 2019
Aug 30

In this 5-part series, take a deep dive into universal design concepts in the context of creating component-based systems for dynamic web content. Get a birds-eye view of the inner workings of user experience (UX) architecture. Brand strategy, user psychology, objective methodology, and data-driven decisions come together, guided by timeless fundamental ideas, to construct today’s digital journeys.

a dancer mid-split

The Art of Setting Type for Dynamic Systems

It is the typographer’s task to divide up, organize, and interpret this matter in such a way that the reader will have a good chance of finding what is of interest to him.

- Emil Ruder

In the 1950s, Swiss typographer and graphic designer Emil Ruder was involved in developing the International Typographic Style. Cleanliness, objectivity, and the use of “the grid” are key features of this approach which still plays a major role in design today.

In 2006, Oliver Reichenstein said,

Web Design is 95% Typography.

And while faster connection speeds have allowed us to provide more media-rich experiences, text-based information is still vital - and the only thing that devices like Google, Alexa, and assistive technologies for the differently-enabled “see.”

Today, the timeless challenge of how to visually present text-based information is as formidable as it’s ever been. Contemporary design decisions take into account the experiences of billions of potential users, located anywhere in the world, in front of screens of all sizes, with a wide range of backgrounds, situations, and abilities. 

Fortunately, standards such as those for Heuristic Evaluation, the W3C’s Web Content Accessibility Guidelines and user testing tools such as the System Usability Scale and the Single Ease Question have provided an objective structure to inform the creative works of designers today.

Fast, Scalable, Legible Type Styling

Guiding principles for font selection and implementation 

Limit the number of fonts 

In the name of consistency, efficiency, and optimized load times, consider combining two harmonious fonts that create a visual hierarchy. Two is considered an ideal number for fonts. Choose a font with enough members in its family to allow design options, however. A font with light and black versions, as seen on some of Google’s best fonts, will provide a versatile UI toolkit.

Most brand standards contain definitions for print and well as web fonts. In the absence of such standards, a review of mission and vision statements can guide you to a font that reflects the brand identity.

Use a responsive type scale

Responsive modular typography scales, when designed and implemented, are an easy way to preserve visual hierarchy across the various screen widths of devices. A modular type scale is a series of type sizes that relate to each other because they increase by the same ratio. 

Mediacurrent Rain typography example shows Raleway and Merriweather fonts

Example of how responsive typography looks across various breakpoints on Mediacurrent’s Rain demo site.


Avoid All Caps for headings and paragraph text

Not only have studies shown text formatted in All Caps decreases reading speed by 10-20%, but this styling presents substantial barriers for users with dyslexia. According to the latest estimates, that is 15-20% of the population.

When headings are less than around 25 characters, all caps is still considered readable for everyone. All caps can also be a valid choice for short navigation titles and concise button copy.

Avoid Italics for headings and paragraph text

A first-time user may spend seconds on your website, not minutes, and as reading speed is dependant on legibility, styling is of paramount importance for all users. In terms of accessibility, italicized letters are nearly illegible to some with reading issues.

Addressing accessibility concerns is a great investment that provides an opportunity to bring in objective best practices to increase usability, readability, and visual impact for all users, opening up your website to a larger audience.

Modern, Readable, Accessible Type Styling 

Guiding principles for line and paragraph spacing

Look to the gold standard for accessibility

Because Section 508 compliance is currently attuned to the A and AA Level WCAG 2.0 guidelines, the AAA Guidelines are sometimes left out of the conversation. The guidelines around line and paragraph spacing, however, are especially easy to incorporate. Because they improve the experience for all users, they are well worth considering. 

a diverse group of people laughing

Avoid justified text

People with certain cognitive disabilities have problems reading text that is both left and right justified. The uneven spacing between words in fully justified text can cause "rivers of white" space to run down the page making reading difficult and in some cases impossible. Text justification can also cause words to be spaced closely together so that it is difficult for them to locate word boundaries.

Implement a maximum width for containers of heading and paragraph text

For people with some reading or vision disabilities, long lines of text can become a significant barrier. They have trouble keeping their place and following the flow of text. Having a narrow block of text makes it easier for them to continue on to the next line in a block. Text blocks must be no wider than 80 characters. 

When determining how to limit the width of a responsive text block, it can be helpful to use a character counting tool. Or try advanced math! The Golden Ratio Typography Calculator generates suggestions for your entire type hierarchy based on the Golden Ratio: a pattern found in nature that is inherently pleasing to the human eye.

Provide ample line spacing for paragraph text

People with some cognitive disabilities find it difficult to track text where the lines are close together. Providing extra space between lines and paragraphs allows them to better track the next line and to recognize when they have reached the end of a paragraph. Provide line spacing that is at least 1.5 (a space and a half) in text blocks and spaces between paragraphs are at least 1.5x line spacing.

In the first post of this series, we discussed the advantages of generously-sized type comfortably line-spaced within a width-restricted column. Not only does this approach align with that of today’s best-in-class websites and provide a comfortable, welcoming reading experience, it is universal design that is accessible and all-inclusive.

Preparing to Reach a Global Audience

Scratching the surface of localization

Designing type for Right To Left (RTL) languages

Arabic is the 4th most popular language globally and 60% of Arabic speakers prefer browsing internet content in Arabic. Aligning text to the right side is key, and so is upsizing the font to preserve text readability. Factoring in the shorter length of words as most Arabic words. Read more about web design for RTL languages. screenshot

Example of RTL language typography on

Accommodating translated text

Character counts expand or contract according to language. Expect a 15 - 30% expansion when translating English to Spanish or Portuguese, for example. When planning to translate English to Chinese or Japanese, however, expect variation. Read more about typography for translated text here.

Planning for character-based languages

Written Japanese, for example, consists of thousands of characters across four character sets: hiragana, katakana, kanji and the Latin alphabet. Japanese users perceive carelessly designed websites as reflective of brand quality. They describe products as “unnatural”, “foreign”, and “suspicious.” The work to get from unnatural to perfect is not hard. Read more about standards for presenting Japanese text on the screen.

Applying and Iterating Type Systems

Continuous improvement based on user feedback

After carefully selecting type styles representative of the brand experience, applying them with accessibility in mind, defining parameters within responsive components, and perhaps including specifications for translated type, what comes next?

We take these specs and build a living style guide to catalog the site’s elements and components. Having the building blocks all in one place not only ensures consistency but allows developers to rapidly adjust or efficiently leverage the existing pieces to create more complex components.

A living style guide makes it easier to add new patterns to meet your needs and the needs of your users that arise as “the rubber hits the road” when content editors begin using the site and feedback is collected from users, ideally through methodical tests.

Technology has evolved rapidly since pioneers like Emil Ruder developed the Swiss style, and is always offering new challenges for designers. But happily, this evolution has allowed us to collect data to objectively guide our practice and to create, share, and continuously improve standards for accessibility and usability, allowing us to meet the challenge of designing with confidence for the global audience. What a great time to be a designer!

In the next installment, we’ll cover pattern libraries/ living style guides in greater detail. We’ll discuss how style libraries ensure a consistent experience and make ongoing enhancements much easier. Learn about the steps it takes to build an emotion-rich, brand-true user journey within the restricted structure of a website built to last for years displaying dynamic, user-entered content.

Aug 30 2019
Aug 30


The quantum leap in technology and the ubiquitous demand for delivering personalized content has made it pivotal for companies to embrace the web content management system for all the right reasons. It begins from engaging customers, lead generation, to snowballing overall revenue from various platforms.

However, it can be daunting and tricky sometimes for enterprises to choose the right one as per their requirements on the basis of the varied features and potential that these CMS offers. 

One of the most cited reports by Gartner, Web Content Management Magic Quadrant report, has proclaimed that Acquia Drupal, Adobe Experience Manager, and Sitecore are the three most prominent WCM Managers. 

A square divided into 4 with text and dots insideThese three were at the forefront in Gartner’s report based on the two factors majorly, “ability to execute”, and “completeness of vision”. They undoubtedly outperformed on both these parameters and hence it goes without saying that all three are proficient in fulfilling enterprises’ WCM needs.

However, as one-size does not fit all and there can be multiple parameters for comparing these, it’s better to largely group them into different stakeholder perspectives- the business decision-makers’, the content and marketing teams, and the IT teams. Each of these teams play a vital role in the process. 

Source: Gartner

The content, marketing, and IT team because they’ll be the ones directly working with the CMS they choose. The business decision-makers, CIO, CTO, and the freshly-coined Chief Data Officer (CDO) are the ones who will be held accountable for their choices and showcasing adequate ROI.

This blog will deal with the comparison of AEM and Drupal from the perspective of business decision-makers. Here we’ll primarily focus on factors like cost of implementation, scalability, security, and maintenance to see how Drupal and AEM fare against each other.

Pick What’s Best For Your Organization

Rectangular box with logo and text of Drupal and AEM

Identifying the company’s particular requirement should be the first task on your to-do list. This will only help you out as a decision-maker to draw the conclusion.

Cost of Implementation

"A high price may be a part of its charisma in selling difficult art”, quoted by Robert Genn, a renowned Canadian artist. 

You should get the desired output for the price you pay for a CMS. 

Setting up any large technology solution is always an eye-catching question as it involves the cost associated with it for implementation. Though it is justified as CMS forms a framework for the enterprise technology architecture, and further paves way for digital transformation; the expenditure made on this part is yet always under analysis.

“Being expensive doesn’t make CMS equipped or competent enough for the enterprises”

Furthermore, migrating to new CMS is also a cumbersome task for any enterprise IT team. So, this crucial decision of investing in any particular CMS is made after several rounds of deliberation. And once deployed, organizations become extremely perceptive of acclimating to a change.

The objective behind all such discussions is to get this done right in the very first time & the investment and ROI of any particular enterprise CMS is one of the biggest factors to consider. 

Licensing Fees

The first and foremost difference between AEM and Drupal is their nature of availability- AEM is proprietary while Drupal is open-source. AEM’s licensing fee starts from somewhere 40,000 USD, with additional cost implications based on organizations’ size and expected usage. And this is not a one-time investment. It is a recurring expenditure every year.

Contrarily, Drupal is an open-source platform and hence discards any licensing fee completely. 

Build vs. Buy

The way current market trends are soaring up does not allow enterprises to consider the deployment of CMS a good idea as it will consume a considerable amount of time. Their expectations lie in finding out an unconventional and innovative solution which is readily available with the quick installation process and some training for content, marketing, and larger digital experience teams to run full-fledged campaigns. 

The general perception that surfaces with Drupal being an open-source, developer-driven solution, is the requirement of complete expert teams to deploy it. There is a definite apprehension around the fact that enterprises have to build from scratch to set up a Drupal CMS, and that without second thoughts, consumes ample amount of time, resources, as well as cost. 

AEM is perceived as a ready-to-roll product requiring minimal expert set up.

“In contrast to the assumption, Drupal does have over 20,000 modules and distributions that provide on-the-go functionalities and features”

However, it’s paramount to apprehend that build vs. buy debate is not as straightforward as it appears. Because:

  • In contrast to the assumption, Drupal does have over 20,000 modules and distributions that provide on-the-go functionalities and features like multisite, multilingual, dynamic content, personalization, and more. With distributions like Acquia Lightning, Drupal caters to highly targeted, easy-to-implement enterprise-level content management solutions, unlike AEM.
  • The other noteworthy point is that AEM does need specialized teams for design, hosting and maintaining an efficient digital platform. They demand an almost similar degree of the build like that of Drupal. But even here, the total cost of implementation for Drupal would be around 250,000 USD to 350,000 USD on an average, and around 500,000 USD if you compute hosting too. On the other hand, typical AEM implementation budget starts exceeding the limit of 500, 000 USD and can go as high as 1 million USD.

Support & Maintenance

Both Drupal and AEM demand substantial maintenance post-deployment.

In regards to the maintenance, Drupal will safeguard your content but to lay the foundation for modern architecture it won't hesitate from breaking some components to ensure that the platform is up-to-date and relevant. To achieve the same, It will eliminate unnecessary bloatware associated with rote adherence to backward compatibility.



Build or Buy

Support & Maintenance


No licensing fees

Considerable build. Cost approx 250,000-350,000 USD

Support costs can be tailored to fit different enterprises


Licensing fee applicable

Needs specialized teams for build. Costs approx 500,000 - 1 million USD

Dedicated support teams by Adobe


AEM is certainly a secure platform with predefined functionalities to ensure security and administration. User identification and access can be easily managed. There are tried-and-tested techniques by which risk of inter-site request forgery, can be alleviated, and third party data storage, and role-based authentication and access to data objects can be successfully secured.

A bar graph with 11 bars of different height in peach color on white background

Source: Sucuri

As per the stats, Drupal performs substantially better than other leading CMS platforms in terms of protecting websites from any external attacks.

Sucuri, security platform for websites, compiled the Hacked Website report, analyzed more than 34,000 infected websites. Among the statistics that it shared, one of the factors for comparison was affected open-source CMS applications.

The infection crippled other CMS due to improper deployment, configuration, and the poor maintenance.

With Drupal being an open-source platform, it is generally presumed less secure in comparison to a proprietary platform like AEM. However, that’s not the case! 

Drupal has almost similar security and governance features embedded within it similar to AEM. Drupal has dedicated modules for identification, authentication, and access-based controls.

“Drupal’s security standards are set by the Open Web Security Project, making it secure by design”

The database encryption at various levels vouches for data security so that no unauthenticated user can breach the security. Also, there is built-in security reporting feature to let teams highlight and raise the security concerns within the community. 

It is to take heed that AEM’s security initiative is led solely by one team, with Adobe extending support whenever necessary. 

But Drupal has a different story to narrate! The security advisory not only works on to safeguard the platform but also ensure that there are multiple touchpoints to resolve the issue.

Security documentation, helps developers write secure code, and maintain modules for added security - all this creates a larger system that continuously safeguards Drupal. It’s security standards are set by the Open Web Security Project, making it secure by design.

Scalability and Future Proofing

CMS lays the foundation for providing the unique digital experience to users so it ought to be scalable and customizable. It should be capable of integrating seamlessly with other technologies and simultaneously support new solutions so that its ready to serve the growing needs of the organizations shortly. 

So how are Drupal and AEM different in this regard?

The Adobe ecosystem of products offers all-powerful solutions to amplify the enterprise digital experience. However, its features and full potential can only be realized when organizations are using a combination of several different Adobe solutions. While they continuously come up with new capabilities, the chance to leverage these is often dependent on having up-to-date versions of other Adobe products. AEM is a part of the Adobe Marketing Cloud and makes a pertinent case for buying all the other products to create an efficient digital platform.

For instance, Adobe’s  Smart Layout was a new AI feature rolled out in 2018. However, to make use of this feature, enterprises will need the most recent versions of AEM sites, AEM Assets, Target Analytics, and Audience Manager. And that just adds up to the overall budget by several thousand dollars.

While large enterprises might think of implementing it, the vendor lock-in associated with Adobe does not bode well for scalability.

That's because most enterprises today opt for those solutions which are best-of-breed and best-of-need philosophy. The complete enterprise technology stack gets build in an agile manner, where every new piece appended is the best possible solution for the enterprise with given current requirements and constraints. But in case you decide to choose products from Adobe ecosystem, the need to stick to Adobe becomes crucial. And if you want to leverage any of its products to its full capacity, you may lose out on your flexibility of opting for other solutions that might be more suitable to your needs.

In a nutshell, once you have decided to go with Adobe or even with just AEM, getting out of it becomes difficult even if you keep on adding new moving parts to your digital experience stack.

“Drupal empowers enterprises with the flexibility of choosing any technology solution that works best as per their respective requirements and integrates with them hassle-free”

Four circles with text written over them

However, with Drupal, scalability, expansion, and flexibility have never been a cause of concern. Since Drupal is co-created by a whole community of developers, its feature of integrating seamlessly with various other technology solutions is inculcated in its DNA.

  • The Drupal CMS integrates effortlessly with multiple enterprise systems, even Adobe, and does not rely on the existence of other drupal based solutions to work effectively
  • The potential of decoupled Drupal applications has proven it as best content manager-while letting other technologies to build atop to deliver augmented user-facing functionalities.
  • The open-source community also takes care that new modules and functionalities built on any project get contributed and made readily available for others to use and worked upon.

In essence, Drupal empowers enterprises with the flexibility of choosing any technology solution that works best as per their respective requirements and integrates with them hassle-free. 

The Drupal community also ensures to keep the core up-to-date and the platform is always up to speed to work with other enterprise technologies.

The question that arises here is that whether you want to completely switch to Adobe solutions or want to keep that option with you where you have the flexibility to choose the best solutions for your company.

For uninterrupted flexibility and extensibility, it’s suggested to avoid vendor lock-in and choose Drupal.

Have a look at this video to get more understanding of different web content management systems and their capabilities-

[embedded content]


Drupal or AEM

Here is a compiled list of factors arranged in tabular form to carry out the comparison between Drupal and AEM to help you reach the final decision-

Attributes Drupal  AEM

Major Differentiation

A web content management system built by the largest community of developers. A web content management system with implicit personalization and analytics feature.   Agility, cost, and open-source availability are its USPs. Proprietary and licenses are require Flexibility

Being an open-source platform, it does not require any roadmap to implement change.

It is innovation-friendly!

Since it is proprietary and requires a license, it has to wait for rolling out a roadmap to implement changes. Development Speed Easy prototyping leads to faster implementations

Requires considerable time to execute the process


Highly responsive! It helps in building interactive websites for the enhanced digital experience of users

User Experience and building responsive interfaces are available Integration Capabilities

Rest APIs in the core is easy to integrate

Integratable-Relies on partners for integration

Enterprise Fit

Meets all the criteria of the enterprises

Meets all the criteria of the enterprises Security

Dedicated teams to ensure the security of the platform.

Has a more transparent and open process to communicate the issues within the community

Security directed as by proprietary team Scalable

Highly scalable

Scalable Maintenance

Sign up with any Drupal shop. Vendor Agnostic approach is possible.

Proprietary Cost

Source code is free but organizations have to pay more for adding up functionalities

License costs are high

Final Words

The final choice between Drupal and AEM will be made by the decision-makers based on the array of questions around the cost of building, hosting, and maintenance. This also involves considering the associated ROI with both Drupal and AEM to ensure easy workflow. 

The trade-off between making Adobe products work together well and the freedom to choose the best technology solutions as per your requirements needs to be carefully evaluated.

And even though both Drupal and AEM ensure top-notch security, your enterprise internal security and compliance requirements will also need to be taken into account before choosing one over the other.

Aug 30 2019
Aug 30

For over a decade* the Drupal community has gathered in volunteer-led “camps”, based on the BarCamp model, to follow in that camp’s initial goals:

  • Introduce web developers to the Drupal platform.
  • Skill sharing among established Drupal developers
  • Give back to the Drupal project (e.g. fix bugs, documentation, lesson materials)

The scope of Drupal Camps has expanded as our community has grown and matured, and camps now serve everyone in the community, not just developers. They serve as an on-ramp for new developers, a networking opportunity for clients and agencies, a marketing opportunity for service providers, and much more.

The Drupal Event Organizers have documentation of over 50 volunteer-led events with over 10,000 attendees worldwide in the past year, and we know there are almost double this number that we don’t have good data for. These events have evolved organically, with little central organization, and are estimated to comprise more than one million dollars in sponsorship and ticket sales worldwide, yearly.

The Event Organizers have organized in various forms over that time… from various documentation efforts to our current monthly meeting format. With Kaleem’s instigation, the group started toward a more formal organization in late 2018, and that process is almost a reality. 

We’ve established a formation board composed of organizers from across the globe and have been collaborating on a charter for the Event Organizers Working Group over the past few months. We’re looking forward to presenting it soon and beginning the next chapter of the Drupal Event Organizers.

Thanks to the following folks who have contributed to the effort thus far.

Our Formation Board members:

And our trusted advisers:

* Possibly starting at Drupal Camp Toronto, 2006? If you know of an earlier camp, please let us know in the comments.

Aug 30 2019
Aug 30

The first step is to install Drupal Console. You may have already watched the last episode that covers this, however, if not, you can install with composer using:

composer require drupal/console

This will install Drupal console in your project in the ./vendor/bin/ directory. This means you can run Drupal console using:

./vendor/bin/drupal [command]

Note, in my examples I am using Lando for my local development environment. I have it set up to allow me to run Drupal console commands on my site by running lando drupal. You can decide to install Drupal Console globally and add it to your path. Depending on the development environment your setup might be slightly different.

You can get a list of all the Drupal console commands by running Drupal Console command with no command argument:


To generate a boilerplate module with Drupal console run:

drupal generate:module

Fill out the questions asked by Drupal console. Make sure to enter a module name and description. In this example, I added a package name, didn’t include a composer.json file, and didn’t include a themable template:

Drupal Console Generate Module

At the end of the questions Drupal console will ask you if it should proceed with creating the module for you. Hit enter to default this to yes.

Drupal Console Generate Module

The next step is to create our custom entity. We want our entity to be a content entity, not a config entity. This can be accomplished with the following Drupal console command:

drupal generate:entity:content

Make sure to select the module you just created. In this case, I will call the entity Statistic and accept everything else at its defaults.

Drupal Console Generate Entity

When you get through all the questions, you will see all the files that were created:

Drupal Console Generate Entity

Now before you go turn this module on, we are going to take a quick look at the code. At the time of this guide, there is a bug that will cause you some headaches if you don’t fix it prior to enabling the module!

Take a look through all the files generated to create the entity. Don’t worry if you are a bit confused at this point, there are a lot of files and a lot of things going on here!

Open up the Statistic.php file (located in the src/Entity folder). If you called your entity something else, it will be the name of the Entity class.

At the top of the file you might notice that the line of code importing EditorialContentEntityBase is missing a semicolon. This is a bug in the code generation tool, make sure to add a semicolon there!

Fix Content Entity Error

This file is doing a lot, but the core of what it is doing is create the structure for your entity. This structure will be created in the database when you install the module. Go ahead and install the module to see how it works. You will notice that once you install the module you are given some menu options under the Admin > Structure menu.

The Statistics setting page is a placeholder where you could eventually add additional configuration settings. This file is controlled by the src/Entity/StatisticSettingsForm.php file.

You will notice you can manage field and display field just like you can with a content type. At this point, we could be done and just use the UI to configure the entity from here. However, in this case we want to add one more field to our entity before we call it finished.

Uninstall the module and open back up the Statistic.php file. Go down to the baseFieldDefinitions method and add the following code after the $field[‘name’] variable is set.

$fields['value'] = BaseFieldDefinition::create('string')
  ->setDescription(t('The value of the Statistics entity.'))
    'max_length' => 50,
    'text_processing' => 0,
  ->setDisplayOptions('view', [
    'label' => 'above',
    'type' => 'string',
    'weight' => -4,
  ->setDisplayOptions('form', [
    'type' => 'string_textfield',
    'weight' => -4,
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE)

What this will do is add a new field called value. In this case we are making it a string field and the form will be displayed as a textfield. We could have made this an integer field or a decimal field, but for simplicity we will just make it a string.

If you re-install the module, you will now notice your value field is available. Go ahead and create some Statistics now!

There is a lot more you can do with it. You could spend an hour looking through all the code that was generated as there is a lot to learn! This is a good stopping point for now, as we were able to quickly create our own custom entity using Drupal console!

Aug 29 2019
Aug 29

Masonry is a very popular JavaScript library, that stacks items in columns and rows, like a masonry brick wall.

The items reorder themselves according to their size as the viewport size changes with a nice animation effect. For some examples, take a look at the official Masonry site.

It is possible to create a view in Drupal with this style of layout. Keep reading to learn how!

Example of the Masonry layout

Step #1. Install the required modules

  • Open the Terminal application of your PC and type:

composer require drupal/masonry

Type the composer installation command

composer require drupal/masonry_views

Type this command

This will download the required modules. Masonry API and Masonry Views. The API provides integration between the Masonry JavaScript libraries and Drupal. Masonry Views defines the style of the view (its layout).

There are two more libraries to install for the proper functioning of the modules:

  • Create the /libraries folder in the root of your site
  • Inside this folder create two more folders called /masonry and imagesloaded
  • Right-click on the masonry library page and select Save As
  • Place this file (masonry.pkgd.min.js) inside the /masonry folder
  • Do the same with the imagesloaded.pkgd.min.js file.

Create the folders and move the files

  • Click Extend
  • Select Masonry API and Masonry Views
  • Click Install.

Click Install

The system will prompt you to enable also the Libraries module.

  • Click Continue.

Step #2. Create the View

For this tutorial, I’ve generated some dummy content with the Devel Generate module.

Some dummy content

Some more dummy content

Use this module only on development stages. I generated 50 articles with their images. These images have different width and height values.

  • Click Structure > Views > Add View
  • Select Create a block
  • Show Content of type Article
  • Display format: Masonry of fields
  • Items per block: 12
  • Click Save and edit

Click Save and edit

  • In the Fields section click Add

Click Add

  • In the Category Content, select the fields Body and Image
  • Click Add and configure fields

Click <i>Add and configure fields

  • Change the Formatter and set a character limit for the text
  • Click Apply and continue

Click Apply and continue

  • Leave the default image style
  • Link the image to the content
  • Click Apply.

Click Apply

  • In the Fields section click the dropdown and select Rearrange
  • Put the image between title and body
  • Click Apply.

Click Apply

  • Save the view

Step #3. Place the Block

  • Click Structure > Block Layout
  • Scroll down to the Content section
  • Click Place block.

Click Place block

  • Search for the block you created in the last step
  • Click Place block.

Click Place block

  • Hide the title
  • Click Save block.

Click Save block

  • Rearrange the block above the Main page content
  • Scroll down and click Save blocks.

Scroll down and click Save blocks

If you used the Devel module to generate content like I did, you will notice that the body text is not trimmed. Apart from that, you will see the content inside the block neatly organized in a mason grid.

You will see the content inside the block neatly organized in a mason grid

Step #4. Theming the Grid

There are two classes you can target in your stylesheet to change the appearance of the container and the items inside it:

  • .masonry-layout
  • .masonry-item

The two CSS classes to target

More on Drupal theming at OSTraining here. I hope you liked this tutorial. Thanks for reading!

About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Aug 29 2019
Aug 29

In my opinion, there’s nothing in the world quite like learning a new skill. It’s a huge rush figuring out how to do something you didn’t know how to do before. You start with the basics, and then once you’ve got the gist of it, you begin to improve. Over time you’ll get better at it, and you’ll get faster at it. Aside from just improving your abilities, your confidence level might change too. This process can go a few different ways. One is imposter syndrome, where you feel like a fraud that doesn’t know what they’re doing. The other is overconfidence, where you think that your skills are better than they are. Be it due to imposter syndrome, overconfidence, or just plain ol’ inexperience; you’re bound to make some mistakes. And we don’t wanna make mistakes, do we?

Chef at workLike everything else in the world, managing Drupal modules takes time and effort to learn. There’s so much going on under-the-hood that it’s all too easy to make a mistake accidentally. In this article, I’ll point out a couple of common mistakes that new Drupal users make, and how you can avoid them. This is all going down while I do my best to make everything fit my metaphor that compares Drupal to a professional kitchen. Let’s get right into it!

Too Many Modules

Have you ever watched the Too Many Cooks video by Adult Swim? No? Well, here it is. Watch the whole thing; it’s worth it. Trust me. Okay, done with that? Cool. Where were we… Oh yeah, too many modules!

[embedded content]

Having too many cooks (or modules) working in one kitchen (your Drupal site) is a disaster waiting to happen for a whole schwack of reasons. Each module you have installed needs to be downloaded and loaded on the user’s device. More modules mean longer load times. Did you know that 53% of mobile users will abandon a page if it takes over 3 seconds to load? Yeah, so I’d say your load times are pretty important. By keeping your number of modules to a minimum, you’ll reduce your load times, sometimes drastically.

Another problem that can be caused by having too many modules is compatibility. For example, let’s say that you installed a contact form module that enables a user to send you an email along with an attachment. For some strange reason though, the blog comments module you’ve installed is broken now! Something somewhere in the new module is causing compatibility issues. Going back to our kitchen metaphor, it’s like the head chef is cooking a great Italian meal, but the sous chef is preparing Chinese food. That’s just not gonna work out for anyone. 

Outdated or Unsupported Modules

If your site has been around for a few years, first of all, great job! Secondly, you should check to see if your modules are all up to date. Not only that, but you should be checking to see if they’re even still supported. Why? Because as time goes on, the nature of the web changes. The nature of web tools, applications, systems, and services all change with it. Sometimes those changes mean that there are additions, alterations, or subtractions to a piece of code that your website relies on to run. When that happens, it could break the functionality of one of your modules. Since this is all happening behind the scenes, deep in code-world, it can be tough to spot the source of your problem. 

Let’s think about it as a restaurant again. In this scenario, our restaurant and kitchen are Drupal, the cooks are our modules, and the food we’re serving is our site content. Our modules work together using features built into Drupal to put all the code, copy, images, and other assets together into one big tasty meal. I mean website.

Alrighty, so, you’ve closed your restaurant this weekend for some remodelling, but forgot to tell some cooks. Fortunately, most of the kitchen floorplan is still familiar. However, it looks like some of the tongs, several knives, and a couple of pans got moved around. Oh, and the salad station has been completely removed. Gone. Vanished. Poof! This is sort of what can happen to a website and its modules when there’s a Drupal update.

Chef at workThe unprepared staff are like outdated modules. Since they don’t know where everything in the kitchen is anymore, their job performance has dropped drastically. Until they get a new tour of the remodelled kitchen, they won’t perform to their fullest, and might not be able to perform at all. In a Drupal update, there might only be tiny changes that barely impact performance, but because your module wasn’t updated to run on this new version, it’s stopped working or slowed down. It’s critical always to ensure your modules are running on the latest version for whichever version of Drupal you’re on.

Your salad tender is another story. That guy’s an unsupported module. For some strange reason, you still offer salads on the menu, but you’ve removed the station for it, and your salad tender wants to get paid under the table from now on. He’s still coming in to work every day even though there he’s got no station, recipes, or even acknowledgement from management. Occasionally though, he still gets salads out to the guests. Sometimes they look great, and other times, your guests might get food poisoning. For the health and safety of your guests, you should look at getting someone who actually has their Food Safe certification and the proper tools to make the salads. In Drupal terms, an unsupported module is a module that’s been abandoned by the team, retired for security reasons, or has been rendered obsolete in some other way. While an unsupported module might function properly and give your site the feature you want it to have, they can also present significant security risks. Unsupported modules don’t get regular updates, so hackers and other black-hats have all the time in the world to leisurely look for exploits in the module’s code. Since their code isn’t being updated along with Drupal’s, their functionality and performance suffer, too. When you use unsupported modules, you’re opening your site up to any number of security risks and performance issues. Just don’t do it!

What Can I Do?

Well, first of all, be sure only to install modules that are still supported and being actively developed. They should be vetted by the community so that you know what you’re installing is high-quality code that’s both functional and secure. Make sure to read the documentation that comes with your modules so that you can make sure you don’t have any compatibility issues with other modules. Keep the number of installed modules to a minimum to improve load times and performance. Look for modules that have overlapping or similar features and decide, “Do I really need both of these?” To put it plainly: carefully research each module, make sure it’s what you need, make sure it works with your site, and make sure the developers and community are still supporting it.

A great way to get a detailed look at your site is to perform a site audit. With a site audit, you’ll see what’s working, what’s not working, where your problems are, and tons of other information. It's kinda like when the health inspector walks through a kitchen and points out the things that need to be improved on. At Cheeky Monkey Media, when our expert team of Drupal developers perform a site audit, they collect all the information that you need to know about your site into one simple, concise, and easy to read the document. Get in touch with one of the monkeys today to get started. We know how hard it can be to try and manage a site on your own, so reach out! We’d be happy to help.

Cooks working
Aug 29 2019
Aug 29

Drupal 8 has a wonderful migration system that generally boils migrations into a particular entity type down into a single YAML file. This file specifies the data source, the output entity type, and how to process input fields and where in the entity they get stored.  

However, there can be a number of complications. Two, in particular, are bad or unexpected input data values, and exactly what form the input data - or even, the partially processed data - is in (eg, is it a scalar, an array, a nested array, etc.). Because the migration system doesn’t provide a way to look at what’s going on inside the process pipeline, it can be difficult and frustrating to debug these kinds of issues.

One way to quickly see what’s going on without having to get into xdebug and grope around in the code for the various plugins provided by the migrate, drupal_migrate, migrate_plus, and migrate_tools modules, is to create a debug plugin and place it wherever you need in the process pipeline.

Usually, the custom migration module code will be structured like this:

├── config
│   └── install
│       ...
│       ├── migrate_plus.migration.node_article.yml
│       ...
├── README.txt
└── src
    └── Plugin
        └── migrate
            ├── destination
            ├── process
            │   ...
            │   ├── Debug.php
            │   ...
            └── source

We’re going to look at the node_article migration pass for an example. The YAML file could look something like this:

id: node_article
label: Node - Article
migration_group: migration
  - Drupal 6
  plugin: node
  node_type: blog
    type: article
  nid: tnid
  type: constants/type
    plugin: default_value
    source: language
    default_value: "und"
  title: title
  uid: node_uid
  status: status
  created: created
  changed: changed
  promote: promote
  sticky: sticky
      plugin: static_map
      source: format
        2: 'filtered_text'      # Filtered HTML "no links"
        3: 'html_text'          # HTML
        5: 'plain_text'         # PHP code
        6: 'filtered_text'      # Filtered HTML
        7: 'plain_text'         # Email Filter
      plugin: default_value
      default_value: 'html_text'
  'body/value': body
  'body/summary': teaser
  revision_uid: revision_uid
  revision_log: log
  revision_timestamp: timestamp
  plugin: entity:node

But say that it turns out that the body/format is not getting translated correctly when the node_article migration pass is run. How can this be debugged to understand if the YAML structure is wrong, or the data values are wrong?

Let’s have a look at migration/src/Plugin/migrate/process/Debug.php:

namespace Drupal\migration\Plugin\migrate\process;

use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

 * Debug process pipeline
 * @MigrateProcessPlugin(
 *   id = "debug"
 * )
class Debug extends ProcessPluginBase {

   * {@inheritdoc}
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    echo "DEBUG: " . $this->configuration['message'] . "\n";
    print_r(['value' => $value]);
    if (!empty($this->configuration['row']) &&
        $this->configuration['row']) {
      print_r(['row' => $row]);
    return $value;


Debug.php provides a process plugin that can be placed “invisibly” into a process pipeline and gives details about what’s happening inside there. The transform method for all process plugins receives the $value being processed and the $row of input values, among other things. It should return a value that is the result of processing that the plugin does.

The ProcessPluginBase object also contains a configuration object, where named parameters that appear in the process pipeline YAML code are stored. For example, the static_map plugin can find the source value in $this->configuration[‘source’].

In this case, the debug plugin returns exactly the value it receives, so it doesn’t change anything. At base, it prints a message parameter and dumps the $value so it can show what actual data is being passed and what format it is in. It has been useful to also be able to look at the $row values. To see them, simply add the parameter row: 1.

For example, to see what the result of the body/format mapping is before passing it along to the default_value plugin:

      plugin: static_map
      source: format
        2: 'filtered_text'      # Filtered HTML "no links"
        3: 'html_text'          # HTML
        5: 'plain_text'         # PHP code
        6: 'filtered_text'      # Filtered HTML
        7: 'plain_text'         # Email Filter
      plugin: debug
      plugin: default_value
      default_value: 'html_text'

If it would also be useful to see what the input row values looked like:

      plugin: static_map
      source: format
        2: 'filtered_text'      # Filtered HTML "no links"
        3: 'html_text'          # HTML
        5: 'plain_text'         # PHP code
        6: 'filtered_text'      # Filtered HTML
        7: 'plain_text'         # Email Filter
      plugin: debug
      row: 1
      plugin: default_value
      default_value: 'html_text'

This produces output for each row processed, which can get quite large. If you know what rows are causing problems, the migration can be run with the --idlist=”<source keys>” parameter. If not, simply redirect the output into a file and use an editor like vim to hunt through it for the cases that are problematic.

This idea can be expanded: if there is some logic to the problem, this can be added so that output is only created for rows that create an issue. It’s possible to create more than one debug plugin (with different names, of course) if there are multiple special purpose needs.

Aug 29 2019
Aug 29

The first step is to install Drupal Console. You can do that with composer using:

composer require drupal/console

This will install Drupal console in your project in the ./vendor/bin/ directory. This means you can run Drupal console using:

./vendor/bin/drupal [command]

Note, in my examples I am using Lando for my local development environment. I have it set up to allow me to run Drupal console commands on my site by running lando drupal. You can decide to install Drupal Console globally and add it to your path. Depending on the development environment your setup might be slightly different.

You can get a list of all the Drupal console commands by running Drupal Console command with no command argument:


To generate a boilerplate module with Drupal console run:

drupal generate:module

Fill out the questions asked by Drupal console. Make sure to enter a module name and description. The rest of the options can be left at their defaults (in the example below I also added a Package name):

Drupal Console Generate Module

At the end of the questions Drupal console will ask you if it should proceed with creating the module for you. Hit enter to default this to yes.

Drupal Console Generate Module

You can now see that this has generated a boilerplate module for you. You can now look at this generated code and even install this module on your Drupal site.

We will now use Drupal console to generate and administrative form. This can be started by running the following command:

drupal generate:form:config

The first step is to enter your module name. This should autocomplete as you type. After that you need to add a Form Classname. In the example below, I used SettingsForm. The next four questions can be left at their defaults:

Drupal Console Generate Form Config

When you tell Drupal console you want to generate a form structure, it will provide you a list of form elements and walk you through a form builder process. In this example, I just created a textfield called My Textfield. Go ahead and generate some form fields.

Drupal Console Generate Form Config

When you are finished, just leave the New field type question blank and press the Enter key. It will then ask you some questions regarding the path and menu links.

Drupal Console Generate Form Config

After this it will generate the code for you.

Drupal Console Generate Form Config

Now all you need to do is enable your module, find the link in your admin menu, and you now have an Admin settings form!

Custom Drupal Admin Form

There is so much more you can do with this. As the module currently sits, it doesn’t do much, however, it provides a solid base for you to start developing your own custom module. Spend some time looking through the generated code and feel free to make modifications to the custom module you built.

Aug 29 2019
Aug 29

In a recent press release, declared Agiledrop one of 2019’s best Drupal development firms in the world. With over 10 years of extensive Drupal expertise and several Acquia certified developers, we see this recognition as a true testament to the quality of our work, both with clients and within the Drupal community.

We’re proud to announce that Agiledrop has been chosen as one of the Best Drupal Development companies of 2019! 

For those of you who don't know us - Agiledrop is a web development company specializing in the Drupal CMS. We're based in Central Europe in Slovenia, with headquarters in the capital Ljubljana and offices in several other cities in Slovenia.

Since our beginnings in 2008, our team has grown to over 50 members and we've distinguished ourselves as one of the country's top development companies as well as prolific contributors in the Drupal community, reserving a prestigious position on's list of top Drupal development companies.

As a proud member of the Drupal Association, we’re constantly giving back to the community through code contributions, as well as with frequently organized meetups and free Drupal courses where we train new generations of Drupal enthusiasts. Our specialty, however, lies in helping digital agencies scale up their businesses and take on more work.

Thanks to our 300+ successfully completed projects for a wide range of clients and our 40+ skillful developers, we’re naturally attuned to the needs of particular clients and are able to provide them with the right people for their project in just a few days. Agility is literally in our name! 

Our developers are well-versed in working with Drupal-related services such as Thunder, Drupal Console, Acquia Lightning, Drupal VM, Drush and Open Social. Along with Drupal development, we provide enterprise WordPress development and front-end solutions with modern JavaScript frameworks, e.g. Angular and React. 

We’ve worked with a varied set of clients which includes names such as Ogilvy, UNESCO, Wunderkraut (now Appnovation) and T-Systems - to name just a few. If you’d like to learn about other clients we’ve worked with and what their experience of working with Agiledrop was like, check out our portfolio of references and case studies

And if you're interested in more specific details about our work, such as service and industry focus? Then our profile page on is the place to go; their analysts were super friendly and helped us in building a top-notch profile on their website. 

Of course, we were also very curious to learn how we got chosen among all the amazing and proficient Drupal development companies. When we approached the spokesperson at and asked him about the reasons for choosing us, he was happy to provide us with quite an extensive list:

  • Agiledrop gives its clients only proven Drupal developers who have previously worked on enterprise-level projects, which eliminates the possibility of a bad hire. 
  • Our developers are ready to work on clients’ projects quickly, with individual developers being able to start in only a few days and entire teams being able to start in less than a week, which significantly speeds up the work.
  • We make it a priority to communicate clearly and frequently with clients, no matter the time difference, at least a few times a day, keeping all stakeholders up-to-date on the project’s progress.
  • Our developers adhere to strict coding and security standards, saving costly overruns in the later stages of the project.
  • A lot of Agiledrop’s clients are repeat clients who were so satisfied with our reliability and the quality of our services that they opted for a long-term partnership with us; see our portfolio for their immensely positive reviews.
  • Owing to their comprehensive skillsets, our developers have an excellent grasp of what technologies are most suited to a particular project and are thus able to always choose the most adequate solution to realize the client’s goals and needs.

Who is is a directory and review platform for IT service providers. They offer unbiased service to service seekers, by providing them with a listing of genuine and highly professional IT firms, which can help the service seekers in achieving their goals by providing high-quality technical services.  

The research team of chooses the best firms by filtering a vast list of companies and introduces only the competitive names to the businesses, enterprises, and entrepreneurs to partner with. 

The company has a friendly team of researchers and a hassle-free communication system. They provide the listing service for various technologies and services, which makes their platform a one-stop destination to find the perfect technology partner for any kind of project.

Are you just now considering taking on that big project, but lack the development capacity? Contact us at Agiledrop - our A-team will be happy to help you out!

Aug 29 2019
Aug 29

In the previous posts we talked about option to manage migrations as configuration entities and some of the benefits this brings. Today, we are going to learn another useful feature provided by the Migrate Plus module: migration groups. We are going to see how they can be used to execute migrations together and share configuration among them. Let’s get started.

Example definition of a migration group.

Understanding migration groups

The Migrate Plus module defines a new configuration entity called migration group. When the module is enabled, each migration can define one group they belong to. This serves two purposes:

  1. It is possible to execute operations per group. For example, you can import or rollback all migrations in the same group with one Drush command provided by the Migrate Tools module.
  2. It is is possible to declare shared configuration for all the migrations within a group. For example, if they use the same source file, the value can be set in a single place: the migration group.

To demonstrate how to leverage migration groups, we will convert the CSV source example to use migrations defined as configuration and groups. You can get the full code example at The module to enable is UD configuration group migration (CSV source) whose machine name is ud_migrations_config_group_csv_source. It comes with three migrations: udm_config_group_csv_source_paragraph, udm_config_group_csv_source_image, and  udm_config_group_csv_source_node. Additionally, the demo module provides the udm_config_group_csv_source group.

Note: The Migrate Tools module provides a user interface for managing migrations defined as configuration. It is available under “Structure > Migrations” at /admin/structure/migrate. This user interface will be explained in a future entry. For today’s example, it is assumed that migrations are executed using the Drush commands provided by Migrate Plus. In the past we have used the Migrate Run module to execute migrations, but this module does not offer the ability to import or rollback migrations per group.

Creating a migration group

The migration groups are defined in YAML files using the following naming convention: migrate_plus.migration_group.[migration_group_id].yml. Because they are configuration entities, they need to be placed in the config/install directory of your module. Files placed in that directory following that pattern will be synced into Drupal’s active configuration when the module is installed for the first time (only). If you need to update the migration groups, you make the modifications to the files and then sync the configuration again. More details on this workflow can be found in this article. The following snippet shows an example migration group:

uuid: e88e28cc-94e4-4039-ae37-c1e3217fc0c4
id: udm_config_group_csv_source
label: 'UD Config Group (CSV source)'
description: 'A container for migrations about individuals and their favorite books. Learn more at'
source_type: 'CSV resource'
shared_configuration: null

The uuid key is optional. If not set, the configuration management system will create one automatically and assign it to the migration group. Setting one simplifies the workflow for updating configuration entities as explained in this article. The id key is required. Its value is used to associate individual migrations to this particular group.

The label, description, and source_type keys are used to give details about the migration. Their value appear in the user interface provided by Migrate Tools. label is required and serves as the name of the group. description is optional and provides more information about the group. source_type is optional and gives context about the type of source you are migrating from. For example, "Drupal 7", "WordPress", "CSV file", etc.

To associate a migration to a group, set the migration_group key in the migration definition file: For example:

uuid: 97179435-ca90-434b-abe0-57188a73a0bf
id: udm_config_group_csv_source_node
label: 'UD configuration host node migration for migration group example (CSV source)'
migration_group: udm_config_group_csv_source
source: ...
process: ...
destination: ...
migration_dependencies: ...

Note that if you omit the migration_group key, it will default to a null value meaning the migration is not associated with any group. You will still be able to execute the migration from the command line, but it will not appear in the user interface provided by Migrate Tools. If you want the migration to be available in the user interface without creating a new group, you can set the migration_group key to default. This group is automatically created by Migrate Plus and can be used as a generic container for migrations.

Organizing and executing migrations

Migration groups are used to organize migrations. Migration projects usually involve several types of elements to import. For example, book reports, events, subscriptions, user accounts, etc. Each of them might require multiple migrations to be completed. Let’s consider a news articles migration. The "book report" content type has many entity reference fields: book cover (image), support documents (file), tags (taxonomy term), author (user), citations (paragraphs). In this case, you will have one primary node migration that depends on five migrations of multiple types. You can put all of them in the same group and execute them together.

It is very important not to confuse migration groups with migration dependencies. In the previous example, the primary book report node migration should still list all its dependencies in the migration_dependencies section of its definition file. Otherwise, there is no guarantee that the five migrations it depends on will be executed in advance. This could cause problems if the primary node migration is executed before images, files, taxonomy terms, users, or paragraphs have already been imported into the system.

It is possible to execute all migrations in a group by issuing a single Drush with the --group flag. This is supported by the import and rollback commands exposed by Migrate Tools. For example, drush migrate:import --group='udm_config_group_csv_source'. Note that as of this writing, there is no way to run all migrations in a group in a single operation from the user interface. You could import the main migration and the system will make sure that if any explicit dependency is set, they will be run in advance. If the group contained more migrations than the ones listed as dependencies, those will not be imported. Moreover, migration dependencies are only executed automatically for import operations. Dependent migrations will not be rolled back automatically if the main migration is rolled back individually.

Note: This example assumes you are using Drush to execute the migrations. At the time of this writing, it is not possible to rollback a CSV migration from the user interface. See this issue in the Migrate Source CSV for more context.

Sharing configuration with migration groups

Arguably, the major benefit of migration groups is the ability to share configuration among migrations. In the example, there are three migrations all reading from CSV files. Some configurations like the source plugin and header_offset can be shared. The following snippet shows an example of declaring shared configuration in the migration group for the CSV example:

uuid: e88e28cc-94e4-4039-ae37-c1e3217fc0c4
id: udm_config_group_csv_source
label: 'UD Config Group (CSV source)'
description: 'A container for migrations about individuals and their favorite books. Learn more at'
source_type: 'CSV resource'
        - ud_migrations_config_group_csv_source
    - UD Config Group (CSV Source)
    - UD Example
    plugin: csv
    # It is assumed that CSV files do not contain a headers row. This can be
    # overridden for migrations where that is not the case.
    header_offset: null

Any configuration that can be set in a regular migration definition file can be set under the shared_configuration key. When the migrate system loads the migration, it will read the migration group it belongs to, and pull any shared configuration that is defined. If both the migration and the group provide a value for the same key, the one defined in the migration definition file will override the one set in the migration group. If a key only exists in the group, it will be added to the migration when the definition file is loaded.

In the example, dependencies, migration_tag, and source options are being set. They will apply to all migrations that belong to the udm_config_group_csv_source group. If you updated any of these values, the changes would propagate to every migration in the group. Remember that you would need to sync the migration group configuration for the update to take effect. You can do that with partial configuration imports as explained in this article.

Any configuration set in the group can be overridden in specific migrations. In the example, the header_offset is set to null which means the CSV files do not contain a header row. The node migration uses a CSV file that contains a header row so that configuration needs to be redeclared. The following snippet shows how to do it:

uuid: 97179435-ca90-434b-abe0-57188a73a0bf
id: udm_config_group_csv_source_node
label: 'UD configuration host node migration for migration group example (CSV source)'
# Any configuration defined in the migration group can be overridden here
# by re-declaring the configuration and assigning a value.
# dependencies inherited from migration group.
# migration_tags inherited from migration group.
migration_group: udm_config_group_csv_source
  # plugin inherited from migration group.
  path: modules/custom/ud_migrations/ud_migrations_csv_source/sources/udm_people.csv
  ids: [unique_id]
  # This overrides the header_offset defined in the group. The referenced CSV
  # file includes headers in the first row. Thus, a value of 0 is used.
  header_offset: 0
process: ...
destination: ...
migration_dependencies: ...

Another example would be multiple migrations reading from a remote JSON. Let’s say that instead of fetching a remote file, you want to read a local file. The only file you would have to update is the migration group. Change the data_fetcher_plugin key to file and the urls array to the path to the local file. You can try this with the ud_migrations_config_group_json_source module from the demo repository.

What did you learn in today’s blog post? Did the know that migration groups can be used to share configuration among different migrations? Share your answers in the comments. Also, I would be grateful if you shared this blog post with others.

This blog post series, cross-posted at as well as here on, is made possible thanks to these generous sponsors. Contact Understand Drupal if your organization would like to support this documentation project, whether it is the migration series or other topics.

Aug 29 2019
Aug 29

In the previous post we talked about migration groups provided by the Migrate Plus module. Today, we are going to compare them to migration tags. Along the way, we are going to dive deeper into how they work and provide tips to avoid problems when working with them. Let’s get started.

Example migration group definition containing migration tags.

What is the difference between migration tags and migration groups?

In the article on declaring migration dependencies we briefly touched on the topic of tags. Here is a summary of migration tags:

  • They are a feature provided by the core Migrate API.
  • Multiple tags can be assigned to a single migration.
  • They are defined in the migration definition file alone and do not require creating a separate file.
  • Both Migrate Tools and Migrate Run provide a flag to execute operations by tag.
  • They do not allow you to share configuration among migrations tagged with the same value.

Here is a summary of migration groups:

  • You need to install the Migrate Plus module to take advantage of them.
  • Only one group can be assigned to any migration.
  • You need to create a separate file to declare group. This affects the readability of migrations as their configuration will be spread over two files.
  • Only the Migrate Tools provides a flag to execute operations by group.
  • They offer the possibility to share configuration among members of the same group.
  • Any shared configuration could be overridden in the individual migration definition files.

What do migration tags and groups have in common?

The ability to put together multiple migrations under a single name. This name can be used to import or rollback all the associated migrations in one operation. This is true for the migrate:import and migrate:rollback Drush commands provided by Migrate Plus. What you have to do is use the --group or --tag flags, respectively. The following snipped shows an example of importing and rolling back the migrations by group and tag:

$ drush migrate:import --tag='UD Config Group (JSON Source)'
$ drush migrate:rollback --tag='UD Config Group (JSON Source)'

$ drush migrate:import --group='udm_config_group_json_source'
$ drush migrate:rollback --group='udm_config_group_json_source'

Note: You might get errors indicating that the "--tag" or "--group" options do not accept a value. See this issue if you experience that problem.

Neither migration tags nor groups replace migration dependencies. If there are explicit migration dependencies among the members of a tag or group, the Migrate API will determine the order in which the migrations need to be executed. But if no dependencies are explicitly set, there is no guarantee the migrations will be executed in any particular order. Keep this in mind if you have separate migrations for entities that you later use to populate entity reference fields. Also note that migration dependencies are only executed automatically for import operations. Dependent migrations will not be rolled back automatically if the main migration is rolled back individually.

Can groups only be used for migrations defined as configuration entities?

Technically speaking, no. It is possible to use groups for migrations defined as code. Notwithstanding, migration groups can only be created as configuration entities. You would have to rebuild caches and sync configuration for changes in the migrations and groups to take effect, respectively. This is error prone and can lead to hard to debug issues.

Also, things might get confusing when executing migrations. The user interface provided by Migrate Plus works exclusively with migrations defined as configuration entities. The Drush commands provided by the same module work for both types of migrations: code and configuration. The default and null values for the migration_group key are handled a bit different between the user interface and the Drush commands. Moreover, the ability to execute operations per group using Drush commands is provided only by the Migrate Tools module. The Migrate Run module lacks this functionality.

Managing migrations as code or configuration should be a decision to take at the start of the project. If you want to use migration groups, or some of the other benefits provided by migrations defined as configuration, stick to them since the very beginning. It is possible to change at any point and the transition is straightforward. But it should be avoided if possible. In any case, try not to mix both workflows in a single project.

Tip: It is recommended to read this article to learn more about the difference between managing migrations as code or configuration.

Setting migration tags inside migration groups

As seen in this article, it is possible to use set migration tags as part of the shared configuration of a group. If you do this, it is not recommended to override the migration_tags key in individual migrations. The end result might not be what you expect. Consider the following snippets as example:

# Migration group configuration entity definition.
# File: migrate_plus.migration_group.udm_config_group_json_source.yml
uuid: 78925705-a799-4749-99c9-a1725fb54def
id: udm_config_group_json_source
label: 'UD Config Group (JSON source)'
description: 'A container for migrations about individuals and their favorite books. Learn more at'
source_type: 'JSON resource'
    - UD Config Group (JSON Source)
    - UD Example
# Migration configuration entity definition.
# File: migrate_plus.migration.udm_config_group_json_source_node.yml
uuid: def749e5-3ad7-480f-ba4d-9c7e17e3d789
id: udm_config_group_json_source_node
label: 'UD configuration host node migration for migration group example (JSON source)'
  - UD Lorem Ipsum
migration_group: udm_config_group_json_source
source: ...
process: ...
destination: ...
migration_dependencies: ...

The group configuration declares two tags: UD Config Group (JSON Source) and UD Example. The migration configuration overrides the tags to a single value UD Lorem Ipsum. What would you expect the final value for the migration_tags key be? Is it a combination of the three tags? Is it only the one key defined in the migration configuration?

The answer in this case is not very intuitive. The final migration will have two tags: UD Lorem Ipsum and UD Example. This has to do with how Migrate Plus merges the configuration from the group into the individual migrations. It uses the array_replace_recursive() PHP function which performs the merge operation based on array keys. In this example, UD Config Group (JSON Source) and UD Lorem Ipsum have the same index in the migration_tags array. Therefore, only one value is preserved in the final result.

The examples uses the migration_tags key as it is the subject of this article, but the same applies to any nested structure. Some configurations are more critical to a migration than a tag or group. Debugging a problem like this can be tricky. But the same applies to any configuration that has a nested structure. If the end result might be ambiguous, it is preferred to avoid the situation in the first place. In general, nested structures should only be set in either the group or the migration definition file, but not both. Additionally, all the recommendations for writing migrations presented in this article also apply here.

What did you learn in today’s blog post? Did you know the difference between migration tags and groups? Share your answers in the comments. Also, I would be grateful if you shared this blog post with others.

This blog post series, cross-posted at as well as here on, is made possible thanks to these generous sponsors. Contact Understand Drupal if your organization would like to support this documentation project, whether it is the migration series or other topics.

Aug 29 2019
Aug 29

Make sure you have downloaded and installed the ECK module. Once installed, click on the Configure link or go to Structure > ECK Entity Types.

ECK Module Install

The ECK module allows you to define different entity types. These are similar to the way you define content types, but at a slightly higher level. When you create a content type, you are technically creating a bundle within the node entity type. In the case of ECK, you are defining your own Entity type that may or may not have bundles within it.

Click on the Add entity type button.

ECK Add Entity Type

In this example, we will be creating a new entity to keep track of important statistics. We will use the label Statistic and check all the available Base Fields. You can use whatever Label you would like and the base fields are all optional. I would highly recommend adding a Title field though.

Once finished, click the Create entity type button.

ECK Add Stat Entity Type

Your new Entity will now be displayed in the Entity Types list.

ECK Entity Type List

Click the Add bundle button to add a new bundle to this entity type. In our example, we will only create one bundle. The bundle will be called Number Stat and we will use it to track numeric statistics. Once you have your bundle information filled out, click the Save bundle button.

ECK Add Entity Bundle

The new bundle is now listed on the Statistic bundles listing page.

ECK Bundles List

We could create additional bundles if we had different types of statistics. Similar to how you can have different content types in Drupal 8. In this case, we will stick with just the one bundle and click on the Manage fields button.

Here you can add fields just like you add fields to a content type. In this case, just add a decimal number field called Statistic.

ECK Add Field

You can now go back to the ECK Entity Types admin page and click the Add content button on your Statistic entity type. Go ahead and fill out the form to add a few stats. Once you create some stats, you can go to the ECK Entity Types admin page and select the Content list option from the dropdown button. This will list all the entities for that entity type.

ECK Content

Now that you have the data stored on your site you can use Views or entity reference fields to display or reference this content throughout your site.

The ECK Module has a number of permissions available. These allow you to decide which roles can administer your ECK entities, bundles, and types. Typically you will give all of these roles to only your administrative users. However, the module provides flexibility if you have more complicated use cases.

ECK Permissions

You now know how to create custom entity types using the ECK module. Now go out and build all your entity data structures!

Aug 29 2019
Aug 29

usability testing and great government UX webinar

Crafting UX - for the people, by the people takes a data-informed approach to site decisions. An open ear to constituent feedback ensures a "wicked awesome" user experience. So it's no surprise that when the site’s navigation needed improvement, user testing became a guiding light.

In our upcoming webinar, hear how Mediacurrent teams with on a user testing strategy leveraging Drupal 8 and Google Optimize. 

Join our webinar

Watch how to deliver a constituent experience that is discoverable, accessible, and truly “for the people, by the people.” Join us on September 18, 2019, at 2:00 EDT to follow along with our process. Learn tips to user test your way to better website UX. 

Register for the webinar.

You'll learn

  • Our approach to testing and gathering user feedback
  • The A/B testing variants we used to steer site navigation and layout
  • Deep dive into testing with Google Optimize 


  • Clair Smith, Senior Front End Developer, Mediacurrent
  • Becky Cierpich, UX/UI Designer, Mediacurrent

We hope to see you there!

Aug 28 2019
Aug 28

Join Hook 42 for Another Exciting BADCamp

Some of our team will be at BADCamp this year with a combination of to-do's and goals. Our team is not only going to be on-site for training, sessions, booth-sitting, and attending sessions, we're also behind the scenes helping organize and plan for this year's event. Our sponsorship, and those of many other amazing donors, is going towards putting together another BADCamp you don't want to miss!

We're excited to be so hands-on for this event and would like to send a special thank you to those involved in the planning and coordination that have embraced Hook 42's participation thus far. The variety of ways we can contribute to this event and make an impact is extensive, and our team is happy to be giving back to an amazing community. We can't wait for October!

Hook 42 Trainings at BADCamp

We're excited to have four of our team members teaming up to give two trainings this year. The first, Adam Bergstein and Ryan Bateman will be talking about GatsbyJS and Drupal 8. In this training you'll learn how to take a brand new Drupal 8 site running the Umami Demonstration Install Profile and build a recipe blog front-end using GatsbyJS and React, with no React experience required! 

We'll also have Aimee Hannaford and Lindsey Gemmill giving training on web accessibility, covering a beginning to end high-level dive into how to be inclusive on the web. For more information about each training, visit the respective training page BADCamp website linked below.

Hook 42's Adam Bergstein and Ryan Bateman deliver a full day Drupal 8 and GatsbyJS training at BADCamp 2019

Hook 42's Aimee Hannaford and Lindsey Gemmill deliver a full day web accessibility training at BADCamp 2019

Registration For Training Sessions Is Now Open!

There is limited availability for training sessions, so sign up soon. Each room holds approximately 30 people. If you're interested in one of our training sessions, or any other training at BADCamp this year, please be sure to register to reserve your spot. See the training detail page on the BADCamp website for more information.


Beyond full-day training, our team will also be giving a few sessions at BADCamp. We're passionate about the topics we submit to camps and conferences and are excited to be sharing our ideas and expertise with all of you.

Hook 42's Adam Bergstein and Ryan Bateman deliver a session at BADCamp

Hook 42's Aimee Hannaford and Ryan Bateman deliver a session at BADCamp

Hook 42's Lindsey Gemmill delivers a session at BADCamp

Hook 42's John QT Nguyen and Pantheon's David Needham deliver a session at BADCamp

We Hope To See You There

If we aren't behind the computer talking, you can find us out and about. Our team will be fully immersed in BADCamp 2019, so we're just as excited to attend the other amazing presentations selected for this year's event as we hope you are.

Hook 42 will also have a booth at the event this year. We're always looking to make new connections with people at these events and can't wait to talk about the amazing things our team has to offer. Whether you're a new face or an old face, come stop by and say hello!

Aug 28 2019
Aug 28

To always work smoothly and be up-to-date, your Drupal website needs support and maintenance. It’s nice to know you can rely on experts for things like Drupal updates, website performance audit, bug fixes, or anything else. However, you need to choose them carefully. 

First of all, there are plenty of reasons to choose a support company over a freelancer. But there are also the must-have characteristics of a good Drupal support agency. Let them help you with your choice. 

Good Drupal support agency’s features 

  • Decent time on the market

All companies were once startups. However, if a Drupal support agency popped up a week ago, it might be risky to immediately entrust it with major website tasks. After a little while, the agency is able to prove its stability on the market. 

Drudesk support agency has celebrated its 4th birthday and its parent company InternetDevels is preparing to have its 12th anniversary. They have gained a lot of solid experience in challenging Drupal support projects and complex cases.

  • Positive customer feedback

No one says that 100% trust in online feedback is a panacea. Still, it’s important to know what experiences other people have had with a Drupal support agency, so it definitely should have positive reviews.

Drudesk’s customers speak warmly about the agency, call it a forward-thinking and conscientious team, communicative and organized, quick to respond to queries, a reliable partner, and more. Drudesk reviews on Clutch, testimonials on the company’s main page, and other feedback will give you a better picture. 

positive customer feedback

  • A wide range of support services

Website support embraces a wealth of various aspects. It’s convenient and effective to have the same agency working with all of them. So your ideal Drupal supporting partner needs to have broad expertise. 

Drudesk offers all kinds of support and related services. Among them:

and many more.

But this is not all — Drudesk has a strong web development background that allows it to develop websites from scratch. 

In addition, the agency employs quality assurance engineers, DevOps experts, SEO specialists, and others whose expertise may be needed for your case. 

a wide range of support services

  • Warranty for the work performed

Drupal support services, like any others, need to have a warranty. This means that the agency is responsible for their work. 

It should be noted that website support services have their peculiarities. Websites often have old bugs and legacy code that may interfere with the website’s work, making it harder to give a warranty for particular tasks. 

Still, Drudesk cares about customers and offers a warranty for the tasks performed. The standard acceptance period lasts 31 calendar days. During this time, you can check the results. If you find any bugs, everything is fixed free of charge.

  • Transparent task tracking

A good Drupal support agency will give you full control over the tasks performed. Its workflows will be transparent and open to you.

With Drudesk, all customers can see the working progress in real-time. All tasks are managed in Drudesk’s CRM. You can leave your comments on tasks and approve the results. You can also be notified about the team’s new comments in any way convenient to you. 

Since Drudesk relies on the Agile methodology, it has an iterative approach to projects. Large ones are broken into sprints and your feedback is considered at every stage in order to make the result more suited to your needs.

transparent task tracking

  • Openness to communication

When working with a decent Drupal support agency, you should feel they are ready to answer your questions and hear your feedback.

Effective communication is one of Drudesk’s priorities. The agency has English-speaking customer service managers and project managers. 

They make sure your ideas are brought to the developers in the right ways, and they are always open to communication and ready to schedule a Skype call with you or reply by email.  

  • profile & community engagement

Every agency working with the Drupal open-source CMS is part of the Drupal community. Its engagement into Drupal life is directly connected to its attitude and expertise. 

Drudesk is listed on and its developers make their contribution to various Drupal projects. They help newbies understand Drupal through discussion forums and willingly mentor new talents. Drudesk developers also actively participate in Drupal events like code sprints, Drupal Camps, etc.

Drupal community engagement

Your Drupal support agency is here

When all these characteristics are met, this means you have found a perfect Drupal support services partner. Contact our Drupal support agency and let’s discuss how we can make your website’s work better. This is where good website support starts!

Aug 27 2019
Aug 27

Carole Bernard's user profile photoThe Drupal Association (DA) is pleased to announce the recent hire of Carole Bernard as the Director of Marketing and Outreach. She and her team will focus on increasing visibility for the Drupal Association and opportunities for Drupal adoption through marketing, community engagement, volunteer management and public relations activities.

With extensive nonprofit and public sector experience, Bernard has served in senior leadership roles for more than 15 years at local, regional and national organizations.  

Bernard, a Boston native, began her career as a speechwriter for the Mayor of Boston. She then worked as the Director of Public Information for the largest human service agency in New England, Action for Boston Community Development, Inc. She started her own consulting business in 2015, providing strategic communications, fundraising and executive management services to nonprofit organizations in the Washington, DC area. She recently served as the Director of Communications and Marketing for Sickle Cell Disease Association of America, Inc. She also has worked for Paralyzed Veterans of America, National Center for Women and Children and the National Minority AIDS Council as their Director of Communication.

“I am so excited to be a part of the dynamic team at the Drupal Association,” says Bernard. “I am blown away by the passion and commitment of the Drupal community, and I look forward to working with everyone to tell the DA story, to showcase the Drupal project, to broaden the organization’s reach to new audiences and to increase opportunities for Drupal adoption around the world through strategic communications and outreach efforts.”

“We want to continue to position Drupal as the leading open-source CMS for ambitious digital experiences that reach audiences across multiple channels around the world,” says Heather Rocker, DA Executive Director. “We also want to expand our efforts to bring new entities and individuals to the table to participate in our global community. We are excited to have Carole join us and to help us lay out and execute a plan that leverages all of the DA assets for growth, inclusion, awareness and participation.”

Bernard received her bachelor’s degree in Political Science from Framingham State College and her master’s degree in Journalism from Boston University.

Aug 27 2019
Aug 27

So you want to turn those plain URL’s into something a little more fancy? Well, you have come to the right place. First make sure you have downloaded and installed the Drupal 8 URL Embed module. It’s recommended to download and install this module using composer so it will download the Embed module and the PHP Embed library automatically. You can do that with

composer require drupal/url_embed

The next step is to customize the embed button, if you want to. To do this, go to Configuration > Content Authoring > Text editor embed buttons.

Essentially, you can change the icon and add additional embed buttons. These buttons will be able to be used within your Text formats. It’s fine to leave these at the defaults for now. By clicking on the Settings link you can change where the button icon files should be stored.

Leave these settings at their defaults as well. Next, navigate to Configuration > Content Authoring > Text formats and editors. Here you will see a list of all the text formats on your website. Click the Configure button on the Basic HTML text format.

This will bring you to a page that will allow you to edit the Toolbar Configuration. Drag the URL Embed button into the Toolbar Configuration. You can place this wherever you want, but it likely makes the most sense in the Media section.

We now need to enable and configure two additional filters. Check the boxes next to Display embedded URLs and Convert URLs to URL embeds.

In the Filter Processing order section, make sure to rearrange the filters so Convert URLs to URL embeds comes before Display embedded URLs. This kind of makes sense as you need to first convert the URL before you can display it! You may also want to drag the Align images below both of these filters if you want to be able to align the embed codes. To use the Align images you will need to make sure you have the alignment buttons added to your toolbar configuration.

Under Filter settings, you now need to allow in the Limit allowed HTML tags and correct faulty HTML section.

Still in the Filter settings section, you can specify an optional prefix which can be used to indicate what URLs to accept. This could be useful if you only wanted Twitter links to be used for example. If you don’t specify anything here, then all of the embed urls from any provider will work.

Click the Save configuration button and now create some content on your site. You can go to Content > Add content > Article and go to the Body field to see your new Embed button in action. Make sure you add some content then click the URL Embed button and paste in a link (the example below used a Twitter link).

Now when you save the page, it will show up exactly like you would expect an embedded Tweet to show up.

Feel free to try out different types of links, the next example uses a Youtube link.

That’s all there is to it! As you can see, it’s incredibly easy to use the Drupal 8 URL Embed module to embed Twitter, Youtube, Instagram, Spotify, and many more types of links directly in your Drupal content. Now go out and start sharing those links on your Drupal site!

Aug 27 2019
Aug 27

Congrats, Drupal 9 release is planned for June 2020! In the meantime, you should ensure that your platform is ready for the upgrade. Although it should arrive easily and smoothly, your website still needs a plan.

The team at WishDesk explains how to get ready and plan for Drupal 9.

What should I know about Drupal 9?

Dries Buytaert, the Drupal creator, announced the planned release of D9 for June 3, 2020. This new version is developed in the same codebase as D8, which means that migration from Drupal 8 to Drupal 9 will be painless. What about D7 and D8? They will reach their end-of-life in November 2021. This means that there will be no official support and no more updates for these versions.

plan for Drupal 9

We recommend upgrading to Drupal 9 by November 2021.

How to plan for Drupal 9 if you are using Drupal 8

If you are using D8 and keep it updated, the migration will be no harder than a minor release. When planning for Drupal 9, make sure that all your modules are updated and deprecated code is removed from the codebase.

Why will migration from Drupal 8 to Drupal 9 be effortless?

  • there will be no need to rewrite the whole code for D9
  • regular D8 updates will keep your platform up-to-date and ready for migration
  • D8 modules will be compatible with D9

How to prepare for Drupal 9 if you are on Drupal 7

Things are more difficult for those whose website is still built on D7. We strongly recommend starting the upgrade process now if you want to have fewer problems when planning for Drupal 9. There are numerous reasons to upgrade to D8:

  • better development experience
  • powerful layout building
  • easy upgrades
  • improved media management
  • improved theming experience
  • decoupled content delivery
  • improved performance
  • and more!

Although the best option for D7 website owners is to migrate to Drupal 8, you can contact a web development company for support of your Drupal 7 website even after the official end-of-life.  

Plan for Drupal 9 with WishDesk!

Get ready for Drupal 9 with the web development specialists at the WishDesk team! No matter what version of this CMS you are using now, we will help you plan for Drupal 9, as well as perform the migration process effortlessly. Just contact our experts!

Aug 27 2019
Aug 27

Want an easy way to extend your market reach and ultimately your sales? Do you feel you need to personalize your website to every user no matter which country they belong to or what language they speak? Getting yourself a multilingual website is your best bet. Not only is it a more cost-effective marketing strategy, it also helps in increasing your website traffic and overall SEO. Drupal CMS has particularly taken up this challenge of providing not only users but also developers with the ability to access Drupal in a language that they prefer. And with Drupal 8 being multilingual out-of-the-box, it has become an ideal choice for businesses and developers. Powerful Drupal translation modules offer developers with granular configuration capabilities where every content entity can be translated.

What are Multilingual Websites?

Multilingual basically means written or available in different languages. Multilingual websites connect better with users from different countries as it immediately adds an element of familiarity. Drupal 8 provides an easy and a great experience of building a multilingual website. Currently Drupal 8 supports 100 different languages for translation.

Drupal 8 has a multilingual feature which comes along with the installation interface. As soon as you install Drupal, based on the browser preference, it provides a language for your Drupal website. Based on the option selected the site is installed in that particular language. Drupal 8 basically provides 4 different modules for language and content translation. We can enable the required Drupal modules in our site and use according to our needs in the website. 


The four core modules provided by drupal are

  1. Language module
  2. Content translation module
  3. Interface translation module
  4. Configuration translation module

Let’s catch up with what each module does, its configurations and how each module can be used in our Drupal website.

Firstly, you need to enable all the 4 core modules in your drupal site. All the translation modules can be configured at path /admin/config/regional

Drupal Language Module

This Drupal 8 language module is one of the core modules located at core/modules/language. It provides a feature of adding and choosing a new language to your Drupal website. Under /admin/config/regional/language/ you can simply add a new language to your site by clicking on the “Add Language” button. It provides a list of different languages from which you can choose the language you need for the development.

drupal-8-migrationdrupal language module

Choose the preferred language from the list and add it

Once the language is added the interface will look similar to this. In the above picture, the default language of the interface is set as English and spanish is the additional language installed. The 9172/9340(98.2%) under Interface translation indicates that 9172 words out of 9340 words available for translation are translated i.e 98.2% of the words in the interface are translated.

It also provides a block( Language switcher) to switch the language from one to another which can be placed at  any region of your Drupal website. Under /admin/structure/block we can place the language switcher block with which we can switch the default language of our website.

Drupal Language Switcher                                                                                Language Switcher

Once the block is placed in the region we will be able to switch to the different languages in the web page itself.

Content Translation Module

The Drupal Content Translation module allows you to translate content entities such as comments, custom block, contents, taxonomy terms, users etc. In order to translate the content entities, the website should have at least two languages installed. The content translation can be configured at path admin/config/regional/content-language . It provides a list of entity types which can be translated. 

For example, click on the content configuration option that appears for each content type.

Let us consider that the content translation is being enabled for the article content type. It provides an option to decide if each subtype entity to be translatable or not. We can also change the default language for a particular content type. Each field has an option to translate its content or not. 

Content Translation Module - Choosing the content                                            Content Translation Module - Choosing the content

It also provides an option to input the content in the language which is suitable for the user while adding content from the backend interface. Once the above configuration is set up and when we try to add content to the Article content type we can see a Select option with the languages installed in our site. We can select any language and add content in the particular language selected.

Content Translation Module - Select the language                                       Content Translation Module - Select the language

Once the contents are saved, users with translate permissions will see links to Translate its content. It provides an additional tab called “Translate” along with the  "Edit" links, and you'll be able to add translations for each configured language.

Content Translation Module - Select the language                                                           
                                                         Content Translation Module - Select the language

Interface translation Module

 The Drupal Interface translation module is also a part of core module and can be easily enabled like any other drupal module. Once this module is enabled it is possible to replace any string in the interface with string which has been customized. Whenever this module encounters any string it tries to translate the particular string to the current language of the interface. If a particular translation is not available it is remembered and we can lookup into the untranslated string in the table.   

Interface translation Module                                                                Interface translation Module

In the above example, the strings which are both translated and untranslated are displayed and we are able to modify the strings for the language that is installed as well.
The translations for the strings are put up in a single place called and the Localization Update module will automatically import the updated translation strings for your selected language. In Drupal 7 and previous versions, this was a contributed module. In Drupal 8 it is a part of a core module.

Configuration translation Module

The Drupal 8 Configuration Translation module allows configuration to be translated into different languages. The site name, views name, and other configurations can be translated easily using the configuration translation.

Configuration translation Module                                                                    Configuration translation Module

It also provides an option to input the content in the language which is suitable for the user while adding content from the backend interface. Once the above configuration is set up and when we try to add content to the Article content type we can see a Select option with the languages installed in our site. We can select any language and add content in the particular language selected.

Aug 26 2019
Aug 26

August 26th is a special day for the owners of Hook 42. As a woman-owned company, we are very familiar with the adversity women face in the workplace. We’re even more familiar with how intense that can get depending on the industry you’re in.

Our inspiration for starting Hook 42 was a culmination of many different things, but one of those things was creating our own voice outside of a male-dominated workforce. The signs were clear that everywhere we looked we found areas of improvement, so our owners took things into their own hands and built a business to solve those problems. 

Hook 42 strives to be a fully inclusive workplace, and we encourage our team to voice their opinions and work towards a better version of themselves, no matter what it takes. 

But what does this philosophy have to do with today specifically?

National Women’s Equality Day and National WebMistress Day fall on August 26th. Both of these topics are influenced by a history of inequality and strive to create an inclusive space that gives everyone an equal opportunity. We’d like to take time to recognize the fights that were won and those we’re still fighting today with the celebration of these two holidays.

A Little Bit of History

The United States Congress passed the 19th Amendment to the Constitution granting women full and equal voting rights on this day in 1920. [ source ]

“Later, On July 30, 1971, Rep. Bella Abzug (D-NY) presented a bill designating August 26th as Women’s Equality Day. That year, rallies, celebrations and political debate filled the country on August 26th. By 1973, Congress passed a joint resolution declaring the day to be observed on August 26th of each year. Every year since each president declares this day as Women’s Equality Day commemorating the certification of the 19th Amendment to the United States Constitution.” [ source ]

We’re predicting that it is no coincidence Kat Valentine founded National WebMistress Day on this very same day quite some years later. In only its third year, National WebMistress Day is putting a more granular focus on supporting equal rights for women and recognizing the adversity women face in the technology industry.

As members of that industry, we want to share our support for every woman in tech that is fiercely making an effort to leave their mark and find their place in a chaotic environment. We’re 100% behind supporting the wave-making, change-inducing women of tech and cultivating that same culture right within our company.

We talked to the ladies within Hook 42 to gather some insights into their journey within tech so far, and what the future holds. Let’s continue to drive change, and support those who are advocating these rights.

The Women of Hook 42


What would you tell your younger woman-self if you had the chance to give her advice based on what you know now about the tech industry?

Don’t dress down. You don’t need to compromise your personal appearance to fit into the “hoodie and t-shirt crew”. If you want to rock your comfort wear then embrace it!

Believe in yourself. You are the only one that can affect change around you. Make goals, strive to reach them, and calibrate when you need to. You are the only one that can improve yourself and your life.

And enjoy the journey. 

How can people be an ally to women in tech?

Be supportive in all aspects of a woman’s life. The tech industry has long days, off-hours, and overtime baked into its core. This combined with the added mental and physical workload we may experience outside of work thrives on a supportive culture.

What helps you push boundaries in tech?

Technology is one of the fastest platforms to implement and execute change. I love bringing peace to chaos and to create new “things” that help improve our lives. Being able to leverage technology for good is a big driver for me.

Is there a woman in tech you look up to, maybe a mentor? (Can be someone you've never talked to but are just inspired by)
Gerri Sinclair. She balances a loving family and a wonderful extended group of friends while bringing bold technology changes through the years. Thank you for all of your energy and impact on technology Madame Modem!

What are you looking to accomplish with your career in tech?

I like to have a place where people can feel they can work safely where they can grow in their personal and professional lives. I like to build cool things. My goal is to have more people be able to have positive interactions which said cool things. :) I’m working to extending the tech environment beyond the tech to include the human side of things, like growth, authenticity, inclusion, and accessibility.

Were there struggles in your journey? Do you still face them? How did you push past it?

There are and have been many struggles in my journey. Some struggles have changed over time, some are still the same. Struggles include breaking through glass ceilings, having to work harder / smarter / stronger / faster than men, and being criticized for having the courage to lead the charge and search out brave new worlds.

Mentors, friends, professional guidance, education, and grit got me through the struggles. Once again, a person (me) is fully responsible for my own actions, regardless if I’m advised in one way or another.


What would you tell your younger woman-self if you had the chance to give her advice based on what you know now about the tech industry?

Even though you hear a lot about bad things about being a woman in tech, you can find nice communities who will welcome you and be supportive. If you are in a bad environment in tech (no matter what gender), try to talk to other people in tech who are in healthy environments and consider switching before leaving.

How can people be an ally to women in tech?

Be a good person and call out bad behavior. Try to show that you welcome others in your groups with your words and actions (e.g. the "Pac-Man Rule"). Be open to differing opinions when offered respectfully.

What helps you push boundaries in tech?

Having a supportive community helps us stand on the shoulders of giants and continue to innovate.

What fuels your passion to keep doing what you do every day?

Seeing something I helped build used by real people, in real life.

Is there a woman in tech you look up to, maybe a mentor? (Can be someone you've never talked to but are just inspired by)

Although there are a lot of great people in the Drupal community, there are 3 people who are amazing role models for all genders who immediately pop into my head: Angie Byron, Amanda Gonser, and Gábor Hojtsy.

What are you looking to accomplish with your career in tech?

Using the skills I have for giving back to the greater good and improving humanity.

Were there struggles in your journey? Do you still face them? How did you push past it?

Yes, often. Some things that may help: stay away from toxic people, give yourself permission to fail, give yourself permission to say "no" without guilt, be kind to yourself, and talk to people who have gone through similar things so you know you aren't alone.


What would you tell your younger woman-self if you had the chance to give her advice based on what you know now about the tech industry?

Keep learning and never give up.

How can people be an ally to women in tech?

Support, mentor, and encourage.

What fuels your passion to keep doing what you do every day?

I like working in tech. I’m passionate about what I do and am looking forward to learning new things and grow professionally. I have a dream to become a successful woman, and this dream keeps me going.


How can people be an ally to women in tech?

Start nurturing curiosity at a young age. Encourage the girls and young women in your life to have bold dreams, because that’s the age where kids start conceptualizing what is “possible” and “impossible.” When I was little, I wanted to be an actress or a ballet dancer, but I never dreamed of being a scientist, astronaut, engineer, or inventor. Young people need to hear and see that women totally belong in every sector of public life.

What fuels your passion to keep doing what you do every day?

I’m lucky to have a strong network of family and friends who are my cheerleaders. My community has supported me every step of the way, and so far I’ve had a diverse, and storied career. I’m a career-changer, and my background is primarily in education, so I didn’t find my way into the tech world until recently. My passion comes from knowing who I am, where I come from, and the community that’s helped me along the way.

What are you looking to accomplish with your career in tech?

Build amazing websites and web applications! Make the digital universe a little more accessible with every project I touch. Along the way, I hope to encourage other underrepresented folks in the tech industry to keep chasing their curiosity.


What would you tell your younger woman-self if you had the chance to give her advice based on what you know now about the tech industry?

Do more research. It’s amazing to see how many companies flourish in the tech industry. I didn't know how well rounded it was until I got into it myself.

How can people be an ally to women in tech?

I feel there is a stigma around women in the tech industry that they aren't as smart or as innovative as a lot of men. I feel that if women were given the chance to prove themselves, that they are willing to improve their skills and show they want to learn and progress, there would be a lot more women in the industry and a lot more women-owned companies.

What fuels your passion to keep doing what you do every day?

My passion to do what I do every day comes from the great people I work with. Not only do they support me and encourage me to expand my knowledge, but they give me opportunities every day. My coworkers, leaders, and bosses all work hard to make this company run smoothly, and I strive to work like them. I want to prove that I am capable of taking on challenges and exceeding expectations. I want to be a better me everyday.


What would you tell your younger woman-self if you had the chance to give her advice based on what you know now about the tech industry?

Confidence from a woman might seem to be threatening, but continue to show your value and stand tall. Make sure the words you use are thoughtfully crafted before raising concerns and contradictions. The strong voice of a woman is often mistaken, so delivery is important. Take the time to think before you react in conflicting situations. 

How can people be an ally to women in tech?

When you see something awry, say something. If a woman confides in you, listen with the intent to help. See us based on our level of experience, not based on our gender. Fight our fights with us, and support our equality in the workplace.

What fuels your passion to keep doing what you do every day?

There are two parts of this for me, the first being the people around me. If it wasn’t for the support system I have inside and outside of the office, it would be much harder to hold my head high in the moments of struggle. 

I also thoroughly enjoy what I do and had the luxury of choice in deciding where my career would take me. Every career path comes with struggles, and being able to work through them and come out with something to show for is very rewarding for me and makes the work even more enjoyable.

Were there struggles in your journey? Do you still face them? How did you push past it?

There have always been struggles. My confidence is quite frequently confused with attitude. Things men often receive praise for, like telling it like it is and not backing down, are things women get reprimanded for. Not letting that defeat me, and keeping my head held high is what helps push past the discrimination. It’s not just men that take offense to it either, other women are often threatened by frequent requests to do better, and be better for all of us. There is a fine line between intimidation and confidence when conversing with women, and its a struggle I face daily and work to eliminate. It's in part learning how receptive people are to certain words, and others being open to strong opinions coming from a variety of people.

Knowing who I am and keeping sight of my worth, not letting other people’s opinions of me think any differently of myself, and knowing that my experiences and education are just as valid and just as those around me are how I stay my course. That confidence that gets "in the way" is also what keeps me going every day.

What About You?

Do you want to share your support for the women around you? It's imperative that we cultivate an environment of acceptance and one where everyone feels welcome. Take a moment to give a special shout-out to a woman in tech, or any woman you know that deserves some recognition.

Aug 26 2019
Aug 26

Promet Source is humbled to announce that this summer, two websites that we designed and developed for our clients have won three prestigious awards. 

2019 is the 25th year in which the widely recognized Communicator Awards have recognized “work that transcends innovation and craft” -- work that stands to make a “lasting impact.” The Communicator Awards receive more 6,000 entries and is sanctioned and judged by the Academy of Interactive & Visual Arts, an invitation-only group consisting of industry-leading professionals from media, communications, advertising, creative and marketing firms. AIVA also judges the W3 Awards, and the Davey Awards.  

The American Association of School Librarians’ 2019 Best Websites for Teaching & Learning rankings are peer reviewed and awarded based on the following criteria: innovation, creativity, active participation, collaboration, free to use, user friendliness, and encouraging for a community of learners to explore and discover. 

Awarding Endeavors

At Promet Source, the satisfaction of a job well done and a client whose expectations have been exceeded is the award we seek and the primary driver of creative solutions, collaborative passion, and constant dedication to staying on top of our game. 

Occasionally, though, there’s another level of achievement and recognition -- prestigious awards in which third parties evaluate our work and judge it to be at the leading edge of the rapidly evolving marketing and media landscape.

Both of these award-winning websites represented a labor of love for both Promet Source and our clients. Ready to Code was sponsored by Google and stemmed from a longstanding collaborative effort between the American Library Association and Google. The depth and breadth of resources available on the site are designed to empower librarians to advance computational thinking among children and teens of all backgrounds as an essential component of 21st Century literacy.

The Martin County Florida website served as an opportunity to optimize a utilitarian user experience that streamlined access to the full range of county services, updates, news, and social media connections, while strengthening civic pride with a visually engaging site that leveraged images of the county’s spectacular natural beauty and stunning infrastructural achievements.   

For Martin County, knowledge that their website has received recognition and attention on an international scale has compounded the impact of key objectives: heightened civic pride and greater awareness of a centralized location for conducting all county business.

For the American Library Association Ready to Code site, the recent ranking from the American Association of School Librarians represents a stamp of approval that has served to advance the mission of the site by increasing its credibility and magnifying its objectives, according to Marijke Visser, associate director and senior policy advocate for the American Library Association.

Why Awards Matter

In the rapidly evolving digital landscape, pushing the bounds of possibilities is an essential success factor. Leaning on what passed for innovation last year is the path toward tired solutions that don’t resonate with clients and constituents. That’s why we at Promet Source take awards such as these seriously and are honored to be in the company of agencies that share our dedication.

Ultimately, websites win awards because they work. They are built upon a deep level of inquiry that leads to extreme empathy for what users need and what they are hoping to accomplish when they visit a site. 

Users are bombarded every day with messages, media, and technologies that confuse and get in the way. The websites that win awards offer a surprisingly delightful experience in which extra effort and expertise on the part of designers and developers translates into streamlined simplicity -- a breath of fresh air within a cluttered and complex world.

Interested in the calibre of design and web development that wins awards while driving big-picture goals? Contact us today.

Aug 26 2019
Aug 26

In order to achieve a consistent user experience and interface design, Atomic Design is a great approach.

Atomic Design is not only a budget saver, but also your best friend for future requirements and allows you to fulfill customers wishes quickly and easily. 

The first step is to define the elements that are most in use. This would be, for example, colors, fonts, buttons and images. Starting with these simple elements, different components can be assembled, such as cards or sliders.

Example: Image + Text + Link = Card

Example: Image + Text + Link = Card

The analogy for atomic design is that it is organized along chemical notation, ranging from atoms to molecules to organisms to templates to pages. On each level the components are assembled from smaller components of the lower levels.

Chemical notation in 'Atomic Design'

Chemical notation in `Atomic Design`

When we design user experiences (UX) at 1xINTERNET we try to build the best possible user interfaces with the fewest amount of components.

The focus is to create efficiency in the project and to potentially save budget. When fewer components are designed in UX, fewer components need to be programmed and tested. 

This approach not only reduces initial efforts considerably but also reduces the cost of the project and its maintenance.

Imagine the following example: You have three different interaction pages and you create a great but different UX for each of those. Then, the users have three different systems to learn. If you instead create an equally good UX by reusing as many components as possible, the user has to learn much less and can interact much faster with your application.


A strict design process and the right integration with the website technology certainly offers efficiency benefits. We plan to write more blog posts on the topic in the next few weeks and are looking forward to your feedback.

Aug 26 2019
Aug 26

Our lead community developer, Alona Oneill, has been sitting in on the latest Drupal Core Initiative meetings and putting together meeting recaps outlining key talking points from each discussion. This article breaks down highlights from meetings this past week. You'll find that the meetings, while also providing updates of completed tasks, are also conversations looking for community member involvement. There are many moving pieces as things are getting ramped up for Drupal 9, so if you see something you think you can provide insights on, we encourage you to get involved.

We've had some gaps in August with limited meetings, so we're happy to be back in the swing of things and reporting a lot of great updates.

Drupal 9 Readiness (08/19/19)

Meetings are for core and contributed project developers as well as people who have integrations and services related to core. Site developers who want to stay in the know to keep up-to-date for the easiest Drupal 9 upgrade of their sites are also welcome.

  • It usually happens every other Monday at 18:00 UTC.
  • It is done over chat.
  • Happens in threads, which you can follow to be notified of new replies even if you don’t comment in the thread. You may also join the meeting later and participate asynchronously!
  • Has a public Drupal 9 Readiness Agenda anyone can add to.
  • The transcript will be exported and posted to the agenda issue.

Symfony development updates

Composer initiative issues affecting D8 and D9

Simpletest deprecation process

The active issue [meta] How to deprecate Simpletest with minimal disruption is one of the biggest deprecations in Drupal 8 while being one of the least trivial to update for, however, work on it is still a priority. 

Composer in Core meeting 08/21/19

  • It usually happens every other Wednesday at 15:30 UTC.
  • It is for contributors to the composer initiative in core who are working on improving drupal's relationship with composer.
  • It is done over chat.
  • Happens in threads, which you can follow to be notified of new replies even if you don’t comment in the thread. You may also join the meeting later and participate asynchronously!
  • Has a public migration meeting agenda anyone can add to.
  • The transcript will be exported and posted to the agenda issue.
  • For anonymous comments, start with a bust in silhouette emoji. To take a comment or thread off the record, start with a no entry sign emoji.

Scaffold files in core

The issue Add core scaffold assets to drupal/core's composer.json extra field is currently waiting on committer attention.

File security component

The issue Add drupal/core-filesecurity component for writing htaccess files has been fixed.

Relocate the scaffold plugin

The issue Relocate Scaffold plugin outside of 'core' directory has also been fixed.

Vendor Hardening Plugin

The issue Add Composer vendor/ hardening plugin to core is ready to be reviewed.

Template files

We have the current template files but still needed are the scaffold files as well as the vendor hardening plugin. Then we will be able to make a template that can be used to make a tarball. changes to support this

  • Change packaging so that it can package 8.7.x the old way and 8.8.x the new way using composer to create a project.
  • Add a variant of the tool that Webflow uses to generate the drupal/core-pinned-dependencies and drupal/core-development-dependencies into the jenkins workflow that publishes those 'somewhere'.

Optionally supporting composer.json for extensions

The issue [PP-3] Provide optional support for using composer.json for dependency metadata still needs work done on it.

Core cross-initiative meeting 8/22/2019



  • On 8/21 we discussed the best course of action to resolve.
  • We hoped to deprecate the Drupal 6 migrations and move them to contrib, but we do not have a way to validate how to make deprecations.
  • V Spagnolo has been working on several issues and they are all advancing well.
  • Nathaniel Catchpole shared some criteria for getting into 9.0-beta1.
  • Good progress has been made on multilingual (biggest blocker right now).
  • Multilingual components must land before 9.0-beta1, thankfully the initiative as a whole is pretty stable.

Blockers (Drupal 6 Deprecations)

  • Needs release manager sign-off on the plan to get deprecation made.
  • Plan for moving those elements deprecated into contrib projects.

Next Steps

  • Need release manager criteria for making the multilingual migration stable.
  • Need release manager review on deprecation plan.
    • Need to document it, our target this week.
    • Need sign off on this and what we’ll do next, the target being next week. 
    • Need a way to get deprecated items into contrib. 
      • Are there any dependencies to deprecate items? Do we have to have them in contrib first?

Auto Updates


  • Contrib Alpha-1 was released this week, it includes:
    • Notifying site owners when a public safety announcement has been released by the security team.
      • Optionally this can be done via email, or in a set message on the page (similar to existing alerts).
    • 8 or so readiness checks to determine if your site can be automatically updated.
    • The above features are available in drupal 7 and 8.
    • Signature signed package now on packagist (dev-master), credit to MWDS folks.
      • This will ensure that MITM attacks are not possible because files are known.
      • This is a base that actual automated updates will rely on.
      • Timelines in the initiative update are still accurate.
      • No impact on 8.8, if added they will be new features on the update module.
      • More user-testing is needed for the PSA. We would like it to be in 8, but it could be in contrib in the meantime. The module is future-proofed enough to disable in contrib when it comes time to enable in core.


There are currently no blockers.

Next Steps

  • Following the PSA there will be the beta release and user testing.
  • The core release is targetting 8.9?



  • The API patch was committed since the last call, it’s in an experimental module.
  • By the 8.8 feature freeze, the UI portion of the module will not yet be ready.
  • This means we can’t release it in core until 9.1.


  • Resources are limited, the patch is large, and more people are needed to help with other aspects of the tool (maybe at Drupalcon Amsterdam).
  • The plan requires the release manager review & discussion.

Next Steps

  • Requires sign off for accessibility on WYSIWYG.
  • Two views issues fixed for content moderation.

Drupal 9



There are currently no blockers.

Next Steps

Continue working on Symfony4, Drupal 8 not using deprecated API’s and multi-version compatibility Symfony3 requirements to open the Drupal9 branch.



  • We have made progress to the critical global issues, mini pager, messages, and others are not completed but are looking likely to land. Some specific one-off pages are most at risk.
  • Targeting 8.8 release, but hoping to descope some things to meet this goal.
  • Authoring components still need designs, hoping to get that work done to get into beta for 8.8
  • Roadmap to stabilize Claro.


There are two issues the release manager needs to review.

Next Steps

Composer (Much of the information here was covered in the Composer meeting on 8/21)


  • Moving well, major patches are in which are focused on bells and whistles that will make the experience better.
    • One major patch changed core development workflow there have been no complaints so far (requires composer 1.9 if you’re working w/ 8.8 repo).
  • Scaffolding plan today requires some duplication of some files. It still needs to be confirmed with the core team.
  • Vendor core clean up plugin now strips out all the testing files from the vendor directory and makes sure there is an htaccess file, this is now a vendor hardening plugin. Waiting to be committed.
  • After the scaffolding and vendor hardening plugin are complete we can create a template that will generate a tarball that is composer ready.


There are two patches waiting to be committed. 

Next Steps



Aug 26 2019
Aug 26

My previous post explores how requesting a medical appointment online begins a patient's digital journey. A hospital's appointment request form might be a new patient's first interaction with a healthcare institution. As such, it is one of the most public-facing forms for a healthcare institution, establishing the baseline for the quality of other external and even internal facing forms. The user experience of the appointment request form sets the tone for the entire patient experience.


A patient's successful user experience when finding, filling out, and submitting an appointment request form is determined by the visual, information, and interactive design of the website and form itself.

Visual design matters

Visual design identifies a healthcare institution’s brand and aesthetic. The quality of care at a healthcare institution is reflected on their website. The website's visual design should be clean, efficient, and caring. Since an appointment request form results in a call back from a live person, including a photograph of a nurse or clinician on the form or landing page can visually reinforce this expectation and experience.

Information design matters

Information design ensures that the patient understands how to navigate the form and makes it clear what information is required and what information is optional. Appointment request forms act as an ambassador of sorts, beginning an interaction between a patient and healthcare clinicians. The form's information design and corresponding editorial sets the tone of a patient's interaction with a healthcare institution.

Interactive design matters

Interactive design improves the flow and process for filling out a form. As someone fills out an appointment request form, conditional logic may hide or show different individual or groups of inputs. When a user clicks submit, how a form validates submitted data can increase or decrease a user's frustration.

Keeping the visual, information, and interactive design in mind, let's look at how the top US hospitals approach their request an appointment.

 U.S. News' Best Hospitals rankings

 U.S. News' Best Hospitals rankings


The U.S. News' Best Hospitals rankings is primarily based on the overall quality of a hospital's care, treatments, and outcomes. The U.S. News' patient experience ratings never directly ask questions about a patient's digital experience. However, the fact that the number 1 ranked hospital, the Mayo Clinical, has a 'Request Appointment' link on the U.S. News' Best Hospitals landing page reinforces the importance of this form.

Mayo Clinical's 'Request Appointment' link

Mayo Clinical's 'Request Appointment' link

We are going to look at how the top four hospitals allow patients to request an appointment on their individual websites. We will examine the positives and negatives to each hospital's appointment request form. The goal is to extrapolate some recommendations and best practices which can be used to build an appointment request form template for the Webform module for Drupal 8.

It’s essential for us to see how users navigate to the appointment form from a hospital's homepage. We will examine how many inputs, questions, steps, and conditions are included on a form, and then determining the level of effort needed to complete a form. Finally, we want to assess the overall user experience, which encompasses the visual, information, and interactive design of the form.

Mayo Clinic

Mayo Clinic's Request an Appointment

Mayo Clinic's Request an Appointment

On the Mayo Clinic's home page, the appointments link is the first and largest element on the page. It takes three clicks from the home page to navigate to their appointment request form. The appointment request form contains 20-30 inputs depending on who is completing the form. Inputs are grouped by contact, insurance, and medical information. Most inputs are required.

Information matters

On top of the U.S. News' direct link to the Mayo Clinic's appointment form as well as the prominent appointment link on the Mayo Clinic's homepage, Mayo Clinic's appointment landing page does a great job of providing all the relevant contact information needed to make an appointment by phone. This ensures even if a patient can't complete the form, they can call the hospital. This contact information, with links to dedicated international and referring physician form, are then included as a sidebar on Mayo's appointment request form.

Experimentation matters

The goal of this blog post's exploration is to identify best practices and recommendations, which helps to establish a baseline for a good appointment request form. Once there is a baseline, it also helps to experiment to improve a form's user experience

Typically, required inputs are marked with red asterisks. Since most inputs are required and there are only a very few optional inputs on the form, Mayo's team inverts the normal, more common, approach of noting required inputs. Instead, they include the message, "All fields are required unless marked optional" with a right aligned "(optional)" label next to optional inputs. This approach appears to be successful. The more important lesson is to be cognizant of a form's required and optional inputs.

Layout matters

The form groups related inputs into visually defined and well-labeled sections. The form also uses a vertical layout with left-aligned labels. Left-aligned labels are more difficult for users to comprehend the relationship between inputs and labels. Alternatively, the form's mobile layout uses the recommend top-aligned labels approach, and it is easier to fill-out. Mayo Clinic should experiment with using top-aligned labels for the desktop form and see if it increases the forms completion rates.

Improvement matters

Mayo Clinic values and promotes their appointment request form. The Mayo's Clinic digital team has put a considerable amount of thought, care, and consideration into their appointment request form's user experience. They should continue to experiment, test, and improve this form.

Cleveland Clinic

Cleveland Clinic's Online Appointment Request Form

Cleveland Clinic's Online Appointment Request Form

The Cleveland Clinic's homepage also includes a prominent link to appointments. It takes three clicks from the home page to navigate to the appointment request form. Their appointment request form is a multistep form with five pages and contains between 50-90 inputs. Most inputs are required. The form collects information about patients, caregivers, referring physicians, and comprehensive medical history. Entering this much information takes a considerable amount of time to complete.

Design matters

Cleveland Clinic's forms is a beautifully designed and logically arranged multi-step form. Multi-step forms makes it easier to collect a lot of information. It is important to ask, "Does an appointment request form need to collect a lot of information?"

Time matters​

When it comes to digital experiences, people have less patience. How long it takes to complete a task matters. Does a new patient need to supply their marital status or subscribe to a mailing list to book their first appointment? Wouldn’t it be more appropriate to collect a patient's medical history after the appointment is booked?

Information matters

Relating to how long it takes to fill out an appointment request form, it is important to ask the value and purpose of each question. Cleveland Clinic's form asks, "Has the patient been seen at Cleveland Clinical in the past?" if answered "Yes", the form then proceeds to ask for a Medical Record Number (MRN). It makes complete sense to collect an existing patient's MRN, which can be used to look up a patient's medical history. However, once the patient provides an MRN, does the form still need to obtain a comprehensive medical history?

Failure matters​

Asking for too much information increases the likelihood that a patient or caregiver might not be able to complete a form or result in them being frustrated with the process of completing the form. Let’s not forget the appointment request form facilitates a phone call that ultimately results in an appointment. Cleveland Clinic's form should also include the phone number on every page to ensure if someone is frustrated they can pick up the phone and still book an appointment.

Goals matters

Cleveland Clinic's form is an overwhelming user experience. At the very least, users should be given the option to complete a more straightforward appointment request form, but also provided a secondary option to provide a full medical history

Before even building any form, it helps to summarize the goal of the form with the scope of the information being collected. This summary can also become the form's introduction text. For public-facing forms, each input should be scrutinized to determine if the information is required to complete the immediate task at hand.

Johns Hopkins Hospital

Johns Hopkins Hospital's Request an Appointment

Johns Hopkins Hospital's Request an Appointment

The Johns Hopkins Hospital homepage includes a small icon with a label linking to their appointments landing page. It takes four clicks from the home page to navigate to the appointment request form. Their form contains 20-25 inputs with five optional inputs. The form has one conditional question asking, "Who are you seeking care for?"

Simplicity matters

By and large, the Johns Hopkins Hospital's appointment request form is the simplest form that we are going to review. There is no input grouping and it has a straightforward two column layout. This, despite the fact that grouping related inputs using top-alignment and a one column layout, is generally recommended. The simplicity of this form makes it easy for users to understand how much information is required to fill out the form. Having all the required inputs displayed before any optional inputs also makes it easier for a user to fill in the form quickly. The two column layout does make the form more difficult to fill out. When the browser is resized to a mobile layout, the form is easier and faster to fill out. Making a form easy for everyone to fill out, including users with disabilities, is essential.

Accessibility matters

The Johns Hopkins Hospital's appointment request form is not accessible to users who depend on screen readers. The form's inputs are missing the necessary code, which allows screen readers to accurately describe to an end-user the labels for each input. Instead of a screen reader saying something like, "Input first name required" the screen reader just states, "Input required" for all the form's inputs.

The inaccessibility of the Johns Hopkins Hospital's appointment request form is a significant problem. An inaccessible appointment request form is the equivalent to not having a wheelchair ramp to enter a building. Fortunately, this issue is not hard to fix. The John Hopkins Hospital digital team needs to become more aware of and monitor the accessibility of their forms.

Expectations matters

Nowhere on the Johns Hopkins Hospital's appointment request form does it indicate the patient or caregiver will receive a callback within a defined period of time. The Johns Hopkins Hospital's appointments landing does include this information. This information should be repeated at the top of the form just in case the user has not been to the appointments landing page. Users need to know what to expect when the click submit on a form. In the specific case of an appointment request form, users need to know when (i.e. how many days) and how they will be contacted (i.e., phone or email).

Massachusetts General

Massachusetts General's Request an Appointment

Massachusetts General's Request an Appointment

The Massachusetts General's homepage also includes two links to appointments. It takes three clicks from the home page to navigate to the appointment request form. The appointment request form contains 20-25 inputs in three groupings with only two optional inputs. Yes/no conditional logic is used to ask for more information about the patient and referring physician

Tone matters

Massachusetts General's appointment request form asks questions using a tone that guides the user through the process of completing the form. For example, every hospital wants to know if a patient has insurance. Instead of displaying a large dropdown menu labeled "Insurance", Massachusetts General's form states, "To facilitate processing, please provide insurance plan name if known." Using this type of phrasing explains to a user why this information is needed, while also stating it is optional. This is an excellent example of the relationship of asking the right question with collecting the best answer.

Questions matters

Many patients decide which hospital to be treated based on physician referrals. When intaking new patients, hospitals may need to contact a referring physician to get a patient's medical history. Most appointment request forms ask for the referring physician's contact information as individual inputs. Massachusetts General's appointment request form just asks for the "Name of referring provider, facility name, address and phone if known." This approach is a brilliant and deliberate decision. First off, it makes it very easy for a patient to enter what information they have about their physician ensuring that at least some information is collected. Appointment requests are always reviewed by an actual person who can take the plain text physician information, fix a misspelling, look up the referring physician's NPI (National Provider Identifier), and get all the needed information into a new patient's medical record.

Massachusetts General appointment request form is asking some very well thought out questions, which are being supported by the right process.

Consistency matter

Massachusetts General has an exemplary appointment request form. There are no immediate issues that need to be addressed by their form. Ironically, Massachusetts General's international appointment request form does have some design and user experience issues. Without getting into specifics, most of the problems on international appointment request form would be resolved if this form followed the best practices and care established by the domestic appointment request form. Providing a consistent user experience across an institution's webforms can ensure a better patient experience.

An appointment request form is a small but key piece to the complex puzzle of a patient’s experience and journey. Soon, someone is going to disrupt, change, and simplify this puzzle. For example, people will be able to schedule an appointment using voice-controlled systems. When we look at the user experience of these relatively simple appointment request forms, there is still some work to be done now and moving forward.

We have extensively explored four hospitals appointment request forms. In my next blog post, I am going to make some concrete recommendations and strategies for building an exemplary appointment request form.

Almost done…

We just sent you an email. Please click the link in the email to confirm your subscription!


Aug 26 2019
Aug 26

The Drupal CMS is a universal platform for website development. It is equally suitable for small business websites and complex e-commerce solutions. This article will tell you about the price formation of Drupal website development and answer the question “How much does it cost to build a website?”.

Website design

First of all, you need to understand what goals and objectives you set for your website. For example, you need a website for your blog with a standard set of features and simple design. Such a Drupal website can be created by yourself absolutely free. Just read a guide or watch tutorial videos. 

Another matter, if you need to develop a selling promotional website for your business with a custom design, it is a serious step that you will have to spend money on. It’s no secret to anyone that websites with a unique design increase sales (according to “The business value of design” by McKinsey). A professional web designer can help you to develop a custom design for your project, but that's not all. Also, you will need a front-end developer to run your website with a new design. Of course, if you have some extra money and your time is too expensive, you can hire a project manager who will monitor the progress of the project, but it’s not neсessary.

Drupal development

Every Drupal website contains Drupal modules. Drupal modules allow you to add the necessary features to your website and you can install them for free. But every business is unique and sometimes a standard set of features is not enough to implement a project, that's why the development of additional Drupal modules is required. To do this, you need an experienced Drupal development team. Below you can look at average hourly rates for mid-level developers.

  • North America: $60-$140 per hour

  • Western Europe: $40-$60 per hour

  • Eastern Europe: $20-$40 per hour

  • Asia and Pacific: $10-$20 per hour

As you can see, the per-hour rate can vary dramatically based on a region of the world, that’s why companies prefer to work with outsource web development firms from different countries. 

Website development cost

Mainly, the cost of a website is calculated based on an hourly rate multiplied by a number of hours spent on a project. 

The website development cost directly depends on the features that you need and on the complexity of website design. Below, you’ll find some examples of the existing types of sites and see how long it takes to develop a website, based on our experience.

Simple promo page

If you need an opportunity to edit the content of your promo page by yourself, the Drupal CMS will be the best solution. The development of a simple promo page will take 50-70 hours.

Approximate total cost:

  • North America: $4200-$9800 

  • Western Europe: $2000-$4200 

  • Eastern Europe: $1000-$2800 

  • Asia and Pacific: $500-$1400 

Company website

The development of creative custom design is very important for corporate websites because the reputation of your company will directly depend on this. Development of a standard corporate website with such sections as "About Us", "Services", "Portfolio", "News", "Blog", "Contacts" will take 200-250 hours.

Approximate total cost:

  • North America: $15000-$35000 

  • Western Europe: $8000-$15000 

  • Eastern Europe: $4000-$10000 

  • Asia and Pacific: $2000-$5000 

Mobile app

Drupal is universal. It suits not only the websites’ development, but it can also be used for the back-end development of mobile applications. This fact makes Drupal even more attractive for your choice. The minimum estimated time for the back-end run on Drupal is 150-200 hours.

Approximate total cost:

  • North America: $9000-$28000 

  • Western Europe: $6000-$12000 

  • Eastern Europe: $3000-$8000 

  • Asia and Pacific: $1500-$4000 


E-commerce websites are online stores and large trading platforms, such as Amazon. Perhaps, the most difficult type of projects to implement, so the time which will be needed for an e-commerce website development is appropriate. The minimum estimated time is 250-300 hours.

Approximate total cost:

  • North America: $15000-$42000 

  • Western Europe: $10000-$18000 

  • Eastern Europe: $5000-$12000 

  • Asia and Pacific: $2500-$6000 


In this article, we gave you approximate costs for different kinds of websites and now you have an idea of how the price is calculated.

Remember, that price for website development entirely depends on a development team and your requirements. It is very important to find the experienced development team to achieve excellent results in your project. And don't forget that every business is unique and requires individual solutions.

Liked the article? Twit @adcisolutions and let us know what you think about this article on Twitter.
Aug 25 2019
Aug 25

I have previously written about using Drupal’s definition files in component-based theming and how it is possible to have component-specific layout and asset library definition files. Now that Layout Builder is stable it is time to have a look at how it can be used with theme components.

Two schools

There are two main approaches to integrating independent theme components with Drupal. They could be described as the ‘Twig developer’ approach and the ‘site builder’ approach.

In the Twig developer approach integration is done entirely in Twig ‘presenter’ templates. A significant benefit of this straightforward approach is that no contrib modules are required (although Component Libraries is usually used). There is also no need for endless pointing and clicking in the admin UI, and dealing with related configuration. The downside is that in most cases this approach leaves the admin UI disconnected from the components. This means that a site builder not familiar with Twig or with no access to the Twig templates has no way of affecting the appearance of the integrated components.

In the site builder approach integration is done using the admin UI. Until now this has required sophisticated contrib modules like Display Suite and UI Patterns, with their own ecosystems of related modules. These are great modules, but ideally it should be possible to use just Drupal core for the site builder approach. With Layout Builder in core we are a huge leap closer to that goal.

Revisiting an old example

Back in January 2017 I wrote a blog post on how to use UI Patterns to integrate a simple Code component. I will now use the same component in an example of how to use Layout Builder for the same task.

Step 1: Create layout and asset library definitions

Starting from where we ended up in that old blog post, we need to provide information about the component’s variables and assets to Drupal in some other way than a .ui_patterns.yml file. This can now be easily done using Drupal core’s definition files.

Drupal core only supports theme (or module) specific definition files, but the Multiple Definition Files module can be used to add support for component-specific files. The results are identical in both approaches, so using Multiple Definition Files is completely optional.

Multiple Definition Files does add one useful feature though. Drupal places layout regions in content, so for example a code region would be accessed in Twig as content.code. To remove this Drupalism, Multiple Definition Files makes layout regions accessible in the Twig root context, so a code region is accessible in Twig as just code.

The definitions in this example are in component-specific files. If you want to use Multiple Definition Files, be sure to enable the module at this point.

The layout definition, shila-code.layouts.yml:

label: 'Code'
category: 'Shila'
template: source/_patterns/01-molecules/content/shila-code/shila-code
library: shila_theme/shila_code
label: 'Language'
label: 'Code'

and the library definition, shila-code.libraries.yml:

source/_patterns/01-molecules/content/shila-code/prism.css: {}
source/_patterns/01-molecules/content/shila-code/prism.js: {}

Note the library reference in shila-code.layouts.yml, linking the two definitions. Be sure to clear caches after adding the new definitions.

(As a side note, the UI Patterns From Layouts module makes it possible to use Drupal’s definition files with UI Patterns as well.)

Step 2: Enable Layout Builder

After enabling the Layout Builder module, Layout Builder has to be enabled for our Code paragraphs type’s display.

If you are moving away from a Display Suite layout, be sure to select - None - for the layout and save the settings before enabling Layout Builder. It seems that if you do not do this, Display Suite is still active and Layout Builder won’t work as expected.

Step 3: Integrate the component using Layout builder

Clicking on the ‘Manage layout’ button takes us to Layout Builder. Display Suite and UI Patterns show a textual representation of a layout, but Layout Builder is different as it displays the layout visually.

First we remove the default section, then we add a new section and choose the ‘Code’ layout for it.

As a reminder, this is what our extremely simple shila-code.html.twig template looks like:

<pre><code{% if language %} class="language-{{ language }}"{% endif %}>{{ code }}</code></pre>

Layout Builder’s visual representation will not be a problem in many cases. However, components often use variables for non-visual purposes or have layouts with overlapping regions. Our Code component is a good example, since language is used as a part of a CSS class name. Layout Builder does not expect layouts to be used in this way, and the result is a completely unusable UI.

Oh no. What we need is a text based way to configure the layout. The good news is that due to accessibility reasons a textual version of the Layout Builder UI is already in the works. So, let’s apply the patch from that issue, clear the caches, and see what happens.

A ‘Layout overview’ link has appeared! Let’s click on it.

This is looking good! We can now add the right paragraph fields to the respective regions in the Code layout and then click on the ‘Save layout’ button. Let’s have a look at a page that contains a Code paragraph.

Something is obviously going wrong here. Let’s have a look at the HTML source.

Since we have placed fields in Layout Builder blocks, there is unwanted HTML from the block and field templates. What we really need is just the contents of the fields, nothing else. This can be an issue with many independent theme components, since they often do not expect extra markup to be provided.

Display Suite has a ‘Full Reset’ field formatter and UI Patterns has an ‘Only content’ option. But what can we do here? Creating specific Twig templates to remove the HTML is an option, but not an ideal one. What we want is an easy UI based way to deal with the problem.

Step 4: Install and enable the Full Reset module (if required)

After searching for existing solutions and not coming up with anything, I ended up writing a small module for this particular purpose. Full Reset does two things: it provides a field formatter and adds a reset option to Layout Builder blocks. The name is a hat tip to the trusty Display Suite field formatter I have used so many times.

A good way to support third party settings for Layout Builder blocks is still being worked on, so a core patch must be applied for Full Reset to work.

With the core patch applied and Full Reset installed and enabled, we can select the ‘Full Reset’ field formatter and tick the ‘Full Reset this block’ checkbox.

Now the block and field templates are not used at all, and the component works and looks like expected! It still does not work in Layout Builder’s visual preview though, because Layout Builder expects the content to be a valid DOM node and have a surrounding HTML tag. For this reason Full Reset does not remove block theming in the preview.


Layout Builder can be successfully used in component-based theming today. There might be some problems with specific components like the one in this example, but these problems can be circumvented by applying two patches and using the Full Reset module.

For me this means that I can now stop using Display Suite, a module that I have used in almost all of my Drupal projects since 2011. Personally I find this change to be just as significant as it was when Field API and Views were added to core.

Aug 25 2019
Aug 25

The Drupal 8 Shield module allows you to protect your site using a simple htaccess authentication. It’s great for sites that you are working on that you don’t want the world (or Google) to see yet. This way you can send the site to a client or anyone really to test and just provide them the username/password to view the site. Once it’s ready to go, you can launch the site and remove this module.

If you have ever wanted to password protect your Drupal site, the Shield module will help with that!

Install the Drupal 8 Shield module like you would any other Drupal module. Note that it shows up in the module list as PHP Authentication Shield.

Once it’s installed, click on the Configure link to get to the configuration page.

It’s recommended to leave the Allow command line access checkbox checked. This will not let the Shield module affect command line access using tools such as Drush. You will want to fill out the Username and Password based on what you want a user to use to access the site.

Note: The Authentication message does not seem to work when I tested it with Chrome.

Click the Save configuration button and you should immediately see the authentication popup. You can test this out in a private browsing or incognito window to see it again. Once you enter the correct username and password, you will be able to access every page on your site.

That’s all there is to it. This works well for development and staging environment while you are developing the site but want the client to be able to look at it. Now go out and password protect your Drupal sites!

Aug 24 2019
Aug 24

Greg Anderson, Open Source Contributions Engineer at Pantheon joins Mike Anello to talk about the Drupal Community's Composer Support in Core Initiative.


DrupalEasy News

Upcoming Events


  • Drupal Aid - Drupal support and maintenance services. Get unlimited support, monthly maintenance, and unlimited small jobs starting at $99/mo.
  • - devPanel.

Follow us on Twitter


Subscribe to our podcast on iTunes, Google Play or Miro. Listen to our podcast on Stitcher.

If you'd like to leave us a voicemail, call 321-396-2340. Please keep in mind that we might play your voicemail during one of our future podcasts. Feel free to call in with suggestions, rants, questions, or corrections. If you'd rather just send us an email, please use our contact page.

Aug 24 2019
Aug 24

In the last blog post we were introduced to managing migration as configuration entities using Migrate Plus. Today, we will present some benefits and potential drawbacks of this approach. We will also show a recommended workflow for working with migration as configuration. Let’s get started.

Example workflow for managing migration configuration entities.

What is the benefit of managing migration as configurations?

At first sight, there does not seem to be a big difference between defining migrations as code or configuration. You can certainly do a lot without using Migrate Plus’ configuration entities. The series so far contains many examples of managing migrations as code. So, what are the benefits of adopting s configuration entities?

The configuration management system is one of the major features that was introduced in Drupal 8. It provides the ability to export all your site’s configuration to files. These files can be added to version control and deployed to different environments. The system has evolved a lot in the last few years, and many workflows and best practices have been established to manage configuration. On top of Drupal core’s incremental improvements, a big ecosystem has sprung in terms of contributed modules. When you manage migrations via configuration, you can leverage those tools and workflows.

Here are a few use cases of what is possible:

  • When migrations are managed in code, you need file system access to make any changes. Using configuration entities allows site administrators to customize or change the migration via the user interface. This is not about rewriting all the migrations. That should happen during development and never on production environments. But it is possible to tweak certain options. For example, administrators could change the location to the file that is going to be migrated, be it a local file or on a remote server.
  • When writing migrations, it is very likely that you will work on a subset of the data that will eventually be used to get content into the production environment.  Having migrations as configuration allow you to override part of the migration definition per environment. You could use the Configuration Split module to configure different source files or paths per environment. For example, you could link to a small sample of the data in development, a larger sample in staging, and the complete dataset in production.
  • It would be possible to provide extra configuration options via the user interface. In the article about adding HTTP authentication to fetch remote JSON and XML files, the credentials were hardcoded in the migration definition file. That is less than ideal and exposes sensitive information. An alternative would be to provide a configuration form in the administration interface for the credentials to be added. Then, the submitted values could be injected into the configuration for the migration. Again, you could make use of contrib modules like Configuration Split to make sure those credentials are never exported with the rest of your site’s configuration.
  • You could provide a user interface to upload migration source files. In fact, the Migrate source UI module does exactly this. It exposes an administration interface where you have a file field to upload a CSV file. In the same interface, you get a list of supported migrations in the system. This allows a site administrator to manually upload a file to run the migration against. Note: The module is supposed to work with JSON and XML migrations. It did not work during my tests. I opened this issue to follow up on this.

These are some examples, but many more possibilities are available. The point is that you have the whole configuration management ecosystem at your disposal. Do you have another example? Please share it in the comments.

Are there any drawbacks?

Managing configuration as configuration adds an extra layer of abstraction in the migration process. This adds a bit of complexity. For example:

  • Now you have to keep the uuid and id keys in sync. This might not seem like a big issue, but it is something to pay attention to.
  • When you work with migrations groups (explained in the next article), your migration definition could live in more file.
  • The configuration management system has its own restrictions and workflows that you need to follow, particularly for updates.
  • You need to be extra careful with your YAML syntax, especially if syncing configuration via the user interface. It is possible to import invalid configuration without getting an error. It is until the migration fails that you realize something is wrong.

Using configuration entities to define migrations certainly offers lots of benefits. But it requires being extra careful managing them.

Workflow for managing migrations as configuration entities

The configuration synchronization system has specific workflows to make changes to configuration entities. This imposes some restrictions in the way you make updates to the migration definitions. Explaining how to manage configuration could use another 31 days blog post series. ;-) For now, only a general overview will be presented. The general approach is similar to managing configuration as code. The main difference is what needs to be done for changes to the migration files to take effect.

You could use the “Configuration synchronization” administration interface at /admin/config/development/configuration. In it you have the option to export  or import a “full archive” containing all your site’s settings or a “single item” like a specific migration. This is one way to manage migrations as configuration entities which lets you find their UUIDs if not set initially. This approach can be followed by site administrators without requiring file system access. Nevertheless, it is less than ideal and error-prone. This is not the recommended way to manage migration configuration entities.

Another option is to use Drush or Drupal Console to synchronize your site’s configuration via the command line. Similarly to the user interface approach, you can export and import your full site configuration or only single elements. The recommendation is to do partial configuration imports so that only the migrations you are actively working on are updated.

Ideally, your site’s architecture is completed before the migration starts. In practice, you often work on the migration while other parts of the sites are being built. If you were to export and import the entire site’s configuration as you work on the migrations, you might inadvertently override unrelated pieces of configurations. For instance, this can lead to missing content types, changed field settings, and lots of frustration. That is why doing partial or single configuration imports is recommended. The following code snippet shows a basic Drupal workflow for managing migrations as configuration:

# 1) Run the migration.
$ drush migrate:import udm_config_json_source_node_local

# 2) Rollback migration because the expected results were not obtained.
$ drush migrate:rollback udm_config_json_source_node_local

# 3) Change the migration definition file in the "config/install" directory.

# 4a) Sync configuration by folder using Drush.
$ drush config:import --partial --source="modules/custom/ud_migrations/ud_migrations_config_json_source/config/install"

# 4b) Sync configuration by file using Drupal Console.
$ drupal config:import:single --file="modules/custom/ud_migrations/ud_migrations_config_json_source/config/install/migrate_plus.migration.udm_config_json_source_node_local.yml"

# 5) Run the migration again.
$ drush migrate:import udm_config_json_source_node_local

Note the use of the --partial and --source flags in the migration import command. Also, note that the path is relative to the current working directory from where the command is being issued. In this snippet, the value of the source flag is the directory holding your migrations. Be mindful if there are other non-migration related configurations in the same folder. If you need to be more granular, Drupal Console offers a command to import individual configuration files as shown in the previous snippet.

Note: Uninstalling and installing the module again will also apply any changes to your configuration. This might produce errors if the migration configuration entities are not removed automatically when the module is uninstalled. Read this article for details on how to do that.

What did you learn in today’s blog post? Did you know the know the benefits and trade-offs of managing migrations as configuration? Did you know what to do for changes in migration configuration entities to take effect? Share your answers in the comments. Also, I would be grateful if you share this blog post with others.

This blog post series, cross-posted at as well as here on, is made possible thanks to these generous sponsors. Contact Understand Drupal if your organization would like to support this documentation project, whether it is the migration series or other topics.


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