Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Apr 14 2021
Apr 14

Working with multimedia is one of the areas that large websites have to deal with. When multiple editors upload a large number of files, keeping your photos and videos in order can become difficult and time-consuming. Drupal has several proven recipes for managing the media library, which I'll present in this article.

Drupal modules for managing multimedia

Drupal offers great flexibility when working with files on a website. In the simplest terms, you can use fields like "File upload". A more complicated option is to use one of the modules to work with multimedia. Let's take a look at three interesting modules worth knowing about.

IMCE module

IMCE is a file viewer available to administrators and editors that also allows you to add, copy, and delete files and directories. It’s fast and convenient, it offers a preview of photos (including creating thumbnails), allows you to sort them and limit the disk space for individual users.

There was a time when the IMCE module was an absolute must-have for any Drupal website. To this day, over 340 thousand websites use it, but its popularity is steadily declining. The reason for this is that with more editors it's difficult to keep your file directories in order. Searching for a specific item is problematic, because the files have only a name and type. It's also impossible to filter them according to selected criteria. Despite the existence of the IMCE version for Drupal 8, new websites usually use other solutions.

IMCE module - Drupal file viewer


SCALD project

SCALD is a module designed for Drupal 7, with a very rich base of add-ons (over 50 additional modules). It allows you to add photos, videos, and other types of files as entities called atoms. Each atom can have any field list based on which the media list is filtered. There is no module version for Drupal 8, but there is a migration path for atoms to the Media module entity.

I mention the SCALD module due to its significant contribution to building the concept of media management. With the premières of Drupal 6 and 7, the era of entities and fields was slowly approaching. The first ideas began to emerge to present files as entities that could be described in any way. This is how the SCALD project was created – quite niche, although used over the years on large and popular sites with millions of multimedia, such as Radio France, ARTE TV and Le Figaro.

Media module

This is by far the most important of the modules presented here. It follows an idea similar to SCALD, because it turns files into entities. It’s currently used by over 180 thousand Drupal 7-based websites, as well as all the websites based on Drupal 8 and 9. That's because since version 8.4 it’s in the core.

Media is a mature module, prepared for years by a team of experienced programmers. I can confidently say that it's one of the best multimedia management solutions available on the Internet. What makes the Media module so special? I'd point out its four main advantages:

  1. Effective embedding of a file library in the Drupal's entity/field/view model. This solution gives virtually endless possibilities for web developers. The files can have different view modes and form view modes, they can be used in many independent contexts. A photo sent via the Media module can be used multiple times, both as a thumbnail in the content of the article and, for example, as a background of a large banner.
  2. Leaving the directory/file model. When uploading a photo or video, the editor no longer decides about the order in the directory structure. It’s done automatically. Ordering is done using the fields defined in the media. You can, for example, add a category to the files, and then use it to search through the list of multimedia.
  3. Independence from media sources. On a well-designed website, videos will work the same way whether they are uploaded directly or via YouTube or Vimeo. Photos can also be loaded from multiple sources (such as Pixabay or Google Drive). Such an approach makes the work of editors easier and allows quickly adding subsequent sources as needed.
  4. Media isn't only multimedia anymore. You can put documents, Facebook posts or excerpts from Google Maps in the media library. Your only limit is your imagination.

When it comes to migration, remember that the Media module comes in three forms:

In each of these cases, a migration path to the core version is available, so you can easily transfer the multimedia library to a newer Drupal.

Why isn't the Media module used on every website?

This begs the question – since the Media module is so great and also available in the core, why isn't it enabled by default and used in every Drupal development project? This is because many Media elements need to be set up by a programmer first. Therefore, this module is a tailor-made solution that is strongly adapted to the needs of a specific website.

It's particularly problematic to correctly display videos from external sources (due to the limited capabilities of external players) and to design appropriate display modes for the media. Getting through these issues can take a long time. Due to this fact, at Droptica we use a ready-made solution included in Droopler, the Drupal distribution.

Media module in Droopler

Since version 2.0, Droopler has built-in support for the Media module. All photos, graphics, icons and videos on the website are stored in the file library.

Usage of the Drupal Media module in the Droopler distribution


It's fine if you have a website based on Droopler 1.x. When upgrading to Droopler 2.x all "File upload" fields will be automatically converted to the new format.

The files put in the library can be used in many places on the website - as a paragraph background, an icon, a photo in a gallery or a cover for a blog post. In each of these contexts, the multimedia will be trimmed and adjusted accordingly. Here are examples of using the same photo in a completely different capacity:

As a tile

An example of using a photo as a tile on a website based on Droopler, thanks to the Drupal Media module


As a form background

An example of using a photo as a form background in Droopler


As a blog cover

An example of using a photo as a blog cover


Once you start using Droopler, you'll be amazed at the ease with which you can use YouTube and Vimeo videos. For example, try putting your video in a paragraph with a banner. In the paragraph edit options add the media in the "Background" field:

Adding a video in a paragraph with a banner in Droopler, the Drupal distribution


Then go to the "Video" tab, enter the video address, click ADD and choose a title for the newly added item. Finally, put the video in a paragraph.

Adding a video in a paragraph with a banner in Droopler


The effect of this action will be a moving background that stretches across the entire screen and is played in a loop. The YouTube controls will be hidden, and the video will have a transparent black overlay, improving the readability of the text.

Video as a moving background, played in a loop, on a website based on Droopler


You can add a video to a gallery in the same way, and e.g. next to the text, in the "Sidebar Image" paragraph. There are practically no restrictions here, all the elements fit together well.


The multimedia library included in the latest Drupal works great with even with a large number of subpages and blog posts. You will quickly notice that reusing the existing photos and videos saves time and effort. Even though the Media module requires a lot of coding for every new project, you can use "prepackages" such as Droopler to start working on the content right away.

Apr 01 2021
Apr 01

One of the most annoying errors on websites are broken links, going nowhere or showing completely different content than expected. Neither Internet users nor Googlebot like them. The way to avoid incorrect links in Drupal is to use the Redirect module.

The redirects created by this module are extremely useful when there are changes being introduced to the URL structure of the website - both global ones and those caused by simple editing of individual content. Redirects ensure that the user will always find what they are looking for, even if the URL is no longer valid.


The module was first made available in 2006 by Moshe Weitzman in a very simplified form. The first alpha version was released in 2010, and a stable version was released for Drupal 8 in 2017. For several years Redirect has been developing much more dynamically, with the support of the Drupal.org community.


Even the lack of a stable release for Drupal 7 didn’t discourage web developers from using the Redirect module. According to the official statistics, it’s currently used on over 260 thousand websites, 45% of which use Drupal 8.

The official usage statics for Drupal Redirect module

Module's creators

The module is being looked after by three programmers:

The last few releases had a lot of support from other Drupal.org users. So far, over 110 people have contributed to the creation of the module.

Purpose of the module

The Redirect module is used to create URL redirects within Drupal. Thanks to it, you can redirect the user from one address within the website to another. Note that there is a big difference between a redirect and an alias.

  • An alias is the "user-friendly" URL of the content that you see in the address bar of a web browser. If you won't define an alias for a given subpage, it will have a default address like “/node/123” or “/ taxonomy/term/456”.
  • A redirect is a rule that's triggered when you reach a given URL address. The rule specifies the target address the user will be redirected to, the language for the redirect, and the type of HTTP code returned. The target webpage will only appear in the browser's address bar when there are no more redirects to be carried out.

The URL redirects are primarily used to improve the linking structure within a webpage. Redirect, however, has a few more interesting applications resulting from the fact that in the version for Drupal 8 it received some of the functionalities of the Global Redirect module. I’ll mention them later in this article.


You can download the Redirect module from the Drupal.org website. The recommended installation method is to use the Composer command:

composer require drupal/redirect

You can find the module settings panel by going to Configuration → Search and Metadata → URL Redirects.

Module's use

The main element of the module's configuration is the list of redirects:

The list of URL redirects in Drupal Redirect module

To add a new redirect, select "+ Add redirect" and then fill in the necessary information, i.e. source address, target address, HTTP code and language.

Adding a new URL redirect in the Redirect module

It's good to explore the seven available HTTP codes. This is because they greatly affect the SEO. You will definitely need:

  • 301 Moved Permanently - the requested page has permanently changed its address. This is an important signal for search engines, which remove the previous page address from their resources and replace it with the new one.
  • 302 Found - the requested page is temporarily available under a different address. This code is useful in a situation where you test changing the linking structure on a webpage, but you want the change to be noted by search engine robots.

Other available codes are:

  • 300 Multiple Choices - there is more than one way to process the given query (rarely used, e.g. for processing different video formats).
  • 303 See Other - the response to the request is under a different address (used e.g. for POST requests).
  • 304 Not Modified - information for the browser that the webpage hasn’t changed since the last visit and it can be loaded from the cache.
  • 305 Use Proxy - the requested webpage is only accessible via proxy.
  • 307 Temporary Redirect - same as 302, but with the assumption that the HTTP method can't be changed.

Additional options

When you've mastered creating URL redirects, check the "Settings" tab. You'll find there two important options that will help you achieve better results with Google.

  • Automatically create redirects when URL aliases are changed - be sure to select this setting. It'll help you keep the webpage clean in the case of changes to internal linking. When you modify any alias on a webpage, a redirect from the old address to the new one will be automatically created.
  • Enforce clean and canonical URLs - this is the option that convinces many developers to choose the Redirect module. It redirects the user to the canonical address of the given webpage, so that they won't stay under a working address like "/node/123". This setting was available in Drupal 7 through the Global Redirect module.

Hooks and integrations

The module provides the following hooks:

  • hook_redirect_load() - launched when loading an array with redirects, allows you to add new items to it,
  • hook_redirect_load_by_source_alter() - used to modify redirections for a given source address,
  • hook_redirect_prepare() - changes the form of a given redirection in the module's administration panel,
  • hook_redirect_alter() - allows you to change the settings of a redirect just before it is triggered.

In addition, the Redirect works with the Pathauto module. It's a very harmonious tandem for managing creating redirects when changing page aliases.


The ease of creating and handling redirects is an important feature of a professional CMS. The Redirect module does this very well. It’s a stable solution that has been developed over the years. I recommend using it in any Drupal development project.

Mar 25 2021
Mar 25

A good CMS can be recognised by how it deals with the URL addresses of individual subpages. Convenient linking attracts users from search engines and has a significant impact on SEO. In this article, I'll introduce you to the Pathauto Drupal module, which is used to automate the creation of page aliases.

With this module, you can easily configure efficient, maintenance-free aliases for your content, including taxonomy terms and user pages.


The first version of Pathauto was released in February 2006 as an add-on to Drupal 4. Stable 1.0 version was released for Drupal 5 in 2007. The current code of this module from the 8.x-1.x branch is the result of a long evolution involving many members of the Drupal.org community.


The figures from the official statistics speak for themselves – the Pathauto module is used by over 640 thousand pages. And 32% of these are built on Drupal 8 and 9. We’re dealing here with one of the "essentials", installed immediately at the stage of creating new projects.

Official usage statistics for Pathauto Drupal module

Module's creators

The module is currently being maintained by four developers:

Since the beginnings of the Pathauto module, over 100 people have been involved in its development, creating a total of almost 1,600 commits. The tremendous contribution of the community is further evidenced by over 3,000 reported tasks and bugs on Drupal.org. Unfortunately, many of these remain unresolved.

Purpose of the module

With bare Drupal, you can create URL aliases for individual subpages, but you have to do it manually. If you don't fill in the field with the alias, the new content will have standard, inconvenient addresses like /node/123 or /taxonomy/term/456.

The Pathauto module automates the addition of aliases by generating them according to the template with tokens specified by you. For example, static pages may have a title derivative address (/foo-bar), and taxonomy terms may contain a vocabulary name (/vocabulary-name/foo-bar).


You can download the module from Drupal.org or join the project by running the following command:

composer require drupal/pathauto

After launching Pathauto, go to its settings by selecting Configuration → Search and Metadata → URL Aliases → Patterns.

Module's use

Pathauto offers a broad range of settings for the methods of generating aliases. It also allows you to carry out mass operations on already existing content. I'll briefly describe below the most important options available.

URL address templates

The basic functionality of the Pathauto module is creating URL address templates, i.e. strings of characters containing tokens. Individual aliases are generated based on them when content is being saved.

I'll explain it using the example of a blog. If you want your posts to be available under the address http://example.com/2021/foo-bar.html%20 containing the year of publication and the title, go to the panel Configuration → Search and Metadata → URL Aliases → Patterns and add a new template for the appropriate content type:

Adding a new URL address template in the configuration panel of Pathauto Drupal module

Try to create a new blog post now. It should get the address /2021/foo-bar.html. Note that you can still overwrite its URL alias, however by default it is generated automatically:

Generating URL alias in the Pathauto module


Page titles usually contain spaces and special characters. Pathauto module automatically converts them to the ASCII format separated by dashes. Then, a title like "How to Make Crème Brûlée?" will be replaced with a simpler version – "how-to-make-creme-brulee". The settings for this conversion can be found in the "Settings" tab.

I suggest that you leave most of these options at the default position, but pay special attention to the "Strings to Remove" field. It contains strings of characters that will be removed from the address, including numerous English prepositions and articles. If you create a blog post titled "A Guide To Drupal", you'll end up with an address like /2021/guide-drupal.html, which is not always the desired result.

The other settings allow for very detailed customisation of transliteration in aliases, which is useful for multi-language support. Here you can, for example, decide on how to handle punctuation.

Mass generation of URL addresses

By default, Pathauto only generates aliases when the content is being saved. This means that if you change the URL template, the modification will not be reflected immediately in the aliases on the entire page. Also, after adding a new template, all its content will not get a new URL address immediately.

When creating large websites, it is often necessary to quickly regenerate aliases for the existing content. This is done with the "Bulk Generate" function, which enables mass operations on URL addresses.

Regenerating URL aliases with Bulk generate function in Pathauto module

Be very careful not to accidentally overwrite the existing aliases with newer versions. Here I would recommend installing the Redirect module, which saves the redirects between the old and new subpage addresses.

Removing aliases

The Pathauto module also has an advanced panel for removing aliases. Be very careful when using it. Any changes introduced here are irreversible. You'll probably need the "Only delete automatically generated aliases" option to prevent deleting manually overwritten aliases.

Deleting URL aliases in Pathauto Drupal module

Hooks and integrations

Pathauto from the 8.x-1.x branch allows you to handle any kind of entities with plugins like @AliasType, and also provides some simple hooks:

  • hook_pathauto_is_alias_reserved() - blocks the creation of an alias if it is reserved by another module. In such a case, a number will be added to the alias (e.g. /foo-bar1).
  • hook_pathauto_punctuation_chars_alter() – it is used to add new punctuation settings.
  • hook_pathauto_pattern_alter() - allows you to modify the URL address template.
  • hook_pathauto_alias_alter() - allows you to change the alias after generating it.

When creating your own Drupal modules, you should think about adding an optional configuration for Pathauto to them. This is quite a common practice, for example in the Group module. As a result, the user receives default, ready-made alias templates.

Dealing with URL addresses in Drupal

Pathauto is an extremely powerful module that is used in most of our Drupal development projects. It keeps URL addresses consistent and frees editors from having to manually form aliases. Its usefulness is confirmed by hundreds of thousands of installations reported in the official statistics. I definitely recommend getting better acquainted with its abilities.

Mar 09 2021
Mar 09

A to-do list is the primary tool of a productive person. It helps in everyday work and allows you to carry out your duties better. As it turns out, some of its elements can also be entered into the administration panel of a Drupal website.

In this article I'll take a closer look at the Checklist API module, which provides Drupal users with an interesting implementation of a TODO list.


The first alpha release of the module was introduced in 2012 for Drupal 7. The stable version 1.0 was released several months later. To date, 12 stable versions have been created – including the newest, marked as 2.0, for Drupal 8 and 9.


Even though the Checklist API module isn't very popular, it has become quite recognisable over the years. Currently, according to the official statistics, it's used by over 30 thousand Drupal-based websites, 63% of which are the 7.x-1.x branch.

Official usage statistics for Checklist API Drupal module

Module's creators

The module is maintained by Travis Carden from Acquia, a very active member of the Drupal community. Besides him, 11 other people have also participated in the project so far. About 170 commits were created in total.

Purpose of the module

The Checklist API module is used to create lists with checkboxes. The status of the task execution is saved to the configuration or to the State API, and it can be modified using the code. Checklist API can be employed to build a to-do list, but that is only one way to use it.

In the case of the Droopler distribution, the Checklist API module was used as a mechanism supporting the update process. When automatic processes fail, we advise the user to perform the operations that aren’t checked on the list manually. There are detailed instructions and links available for them:

Usage of checklist API module in Droopler - Drupal distribution

Checklist API is used by many tools for checking websites in terms of SEO and quality, including SEO Checklist and QA Checklist.


The module is available on the Drupal.org website. You can install it both via Composer (using the composer require drupal/linkit command) and from the .zip file available on Drupal.org.

Module's use

After running the Checklist API module, you'll probably be surprised by the fact that it doesn't have any administration panel. New lists can only be created via the API. This is done using a hook – hook_checklistapi_checklist_info().

Here is an example of a hook that adds a simple to-do checklist when publishing a new website:

* Implements hook_checklistapi_checklist_info().
* Defines an example deploy checklist.
* .
function mylist_checklistapi_checklist_info() {
 $definitions = [];
 $definitions['mylist'] = [
   '#title' => t('Website deploy checklist'),
   '#path' => '/admin/config/development/website-checklist',
   '#callback' => 'mylist_checklistapi_checklist_items',
   '#description' => t('An example deploy checklist for the website.'),
   '#help' => t('

This is an example deploy checklist for your website, provided by the hook_checklistapi_checklist_items().

'), '#storage' => 'state', ]; return $definitions; }

This hook references the mylist_checklistapi_checklist_items function, which returns a multidimensional array. You divide the checklist into tabs with tasks. Each defined task can have a description and a list of links to help the user perform it:

* Implements callback_checklistapi_checklist_items() for mylist.
function mylist_checklistapi_checklist_items() {
 return [
   'tab1' => [
     '#title' => t('Drupal admin panel'),
     '#description' => t('

Set up the Drupal installation for PROD environment.

'), 'aggregate_css_js' => [ '#title' => t('Enable JS/CSS aggregation'), '#description' => t('Enable optimization of the site assets, it is crucial for page speed.'), 'handbook_page' => [ '#text' => t('Performance options'), '#url' => Url::fromUri('base://admin/config/development/performance'), ], ], 'disable_devel' => [ '#title' => t('Disable "devel" module'), 'handbook_page' => [ '#text' => t('Module list'), '#url' => Url::fromUri('base://admin/modules'), ], ], ], 'tab2' => [ // ... ], ]; }

After calling the above code, every authorised user of the website will get access to the new checklist. When they uncheck subsequent items, they'll obtain clear information about the level of completion of tasks:

Example of a checklist in Droopler, Drupal distribution

Defining the content via code has one major advantage – the ability to manipulate tasks, including automatically marking them as completed. Looking at the example above, you could write a module that will check by itself whether the CSS/JS aggregation is enabled and if the "devel" module has been uninstalled. This way, the potential user will save a lot of time.

Here's an example of a piece of code that loads the checklist and enforces its initial state. If the "devel" module is active, the relevant checkbox will be checked automatically.

$handler = \Drupal::service('module_handler');
$checklist = checklistapi_checklist_load('mylist');
$progress = [
 'tab1' => [
   'disable_devel' => $handler->moduleExists('devel'),


Checklist API is very useful for carrying out repetitive tasks, such as those you perform when publishing a new website. The module can also be used as a tool supporting security monitoring and website optimisation, performed as part of Drupal support.

With little effort, Checklist API provides plenty of possibilities and a convenient interface for non-technical users. I definitely recommend getting better acquainted with its functionalities.

Feb 25 2021
Feb 25

The work of a content manager requires intensive linking of various content together. Proper linking of subpages is one of the foundations of SEO. It also makes it easier to navigate your website, which may have a great impact on marketing effectiveness.

Drupal by default allows you to create links in text. You just select the appropriate button in the editor and enter the URL of the new link. However, when you need a more convenient autocomplete solution, I recommend trying the Linkit module. In this article, I’ll show you its abilities.


The module debuted at the beginning of 2010. The first stable version 1.0 for Drupal 6 was released back then. Since that time LinkIt has been updated regularly. The latest beta release, 6.0.0, saw the light of day in December 2020.


The LinkIt module is extremely popular in the Drupal world. Official statistics show over 110 thousand installations. This number also includes the websites based on our Drupal distribution – Droopler. 41% of the above websites are based on Drupal 7.


Module's creators

The module has been maintained by Emil Stjerneman for ten years, and he’s created over 900 commits in the project so far. In total, almost 80 users made contributions to it.

Purpose of the module

The LinkIt module adds to WYSIWYG editors the ability to conveniently link internal and external content. It offers built-in support for content types, taxonomies, users, files, and comments. Thanks to this, you don’t have to remember or copy the URLs you link to when you’re editing a webpage. All you have to do is enter a title fragment and the target page will be suggested by autocomplete. This is a very useful functionality, especially since errors in URLs are one of the most frequently detected problems in Drupal SEO audits.


The module is available on the Drupal.org website. Like other Drupal add-ons, you can install it from a .zip file or via Composer (using composer require drupal/linkit command).

The administration panel can be found in the menu by selecting Configuration → Config Authoring → Linkit.

Module's use

When you start editing any text format, pay attention to the "Drupal link" section.


After clicking the "Linkit enabled" checkbox, the standard link widget in CKEditor will be replaced with a new one, with built-in autocomplete.


At this stage, you can finish the module configuration.

Linkit profiles

If you want to customise autocomplete, create your own Linkit profile in the Configuration → Config Authoring → Linkit panel. Each profile has its name, description and a list of matchers.


You have the following types of matchers to choose from:

  • Content – basic matcher, searches for content by title among all or selected types of content,
  • Contact form – searches for contact forms,
  • Email – detects e-mail addresses and creates a mailto: link automatically,
  • File – searches for files from the sites/*/files directory managed by Drupal,
  • Front page – suggests a home page when you start typing "Front page",
  • Media – searches for media of selected types,
  • Taxonomy term – searches for taxonomy terms,
  • User – searches for website users.

Example of use

The easiest way to explain the operation of matchers is by using an example. I’m adding a new "Example profile" containing the following elements:


Notice that the “Metadata” fields are filled in, showing additional information about the link match found. Now, let’s set the “Example profile” as active in the text format configuration.

When you go to webpage editing, the effect of the above actions will be as follows:


You can see three matchers here, one below the other. The first one shows the article, the second one shows the Media object with a thumbnail, and the third one - the taxonomy term.

URL format

When you save the content with a link inserted via Linkit, you will notice that instead of a URL alias (of the /example-article type), the link contains its abbreviated form (e.g. /link/20). You can change this behaviour by activating the following filter in the text format settings:


Hooks and integrations

The Linkit module is object-oriented and highly flexible. You can extend it with:

  • "matcher"-type plugins, allowing you to easily add your own sources of link hints,
  • "substitution"-type plugins that return links to content.

There are currently no additional Linkit modules on Drupal.org. This is probably due to the fact that the basic version covers most cases of use.


Linkit is a simple and reliable solution that will improve the UX of your website at a low cost. It’ll also allow you to better control the structure of links and help you avoid linking errors. We’ve been using this module for many years – also as part of our own Drupal distribution – Droopler.

Feb 19 2021
Feb 19

When creating websites, you often need to quickly backup the data that isn’t in your code repository. In the case of Drupal, it’s possible to generate copies via the "Backup and Migrate" module.

This module offers options for both beginners and advanced users. In this article, I’ll present its functionalities in detail.


The module was released at the end of 2007 for Drupal 5. It’s been extensively updated since then. The 8.x-3.x branch appeared in 2015, along with Drupal 8, however it didn’t have a stable release. It took another three years for the stable 8.x-4.0 version to see the light of day.

Module's popularity

The popularity of the module is confirmed by the number of installations - according to the official statistics, it’s used by over 220 thousand pages, including approx. 40 thousand based on Drupal 8.


Module's creators

Four developers are responsible for maintaining the module:

There are 822 commits in the code repository, created by over 70 people.

What is the module used for?

Backup and Migrate is an advanced tool for creating backup copies. It operates on the database, as well as public and private files. It integrates with Drupal CRON, thus ensuring the possibility of making regular backups to various destinations.


The module is available at https://www.drupal.org/project/backup_migrate. You can install it from a .zip file or run the command composer require drupal/backup_migrate in the console.

You can find the settings administration panel in the Configuration → Development → Backup and Migrate menu.

Module's use

The module was designed with both beginners and advanced users in mind. The former don’t have to delve into the configuration of data export, they just need to use the quick backup option:


Clicking "Backup now" will download the database (or public/private files as selected in the "Backup Source" field). What’s more, the database backup will be devoid of cache and log entries, so it’ll take up much less space.

Some more settings are available in the "Advanced" tab. I’ll describe these later in the article.

Backup sources

By clicking Settings → Sources you’ll access the list of available backup sources.


By default, the sources can be:

  • databases,
  • public files,
  • private files,
  • whole page code along with a database.

This set can be extended slightly with external MySQL databases and any directories on the server. It can be done using the "Add Backup Source" option.

It’s possible to define own sources via the "Backup and Migrate" module's API.

Backup destinations

A backup destination is the place where it is to be put. This can be, for example, a server directory or a web browser. The available destinations are listed in Settings → Destinations.


As with sources, you can define your own destinations via the "Add Backup Destination" button and a corresponding hook. At the end of the article, I present some destination-adding modules like SFTP Server and S3 Cloud.


Remember that backups contain sensitive data and access to them should be strictly limited. Drupal is one of the most secure CMSs available, so it’s worth using its private file system. In addition, the possibility of encrypting files with backups comes in handy. To use it, add the Defuse library to the project using the command:

composer require defuse/php-encryption

After clearing the cache, the "Encrypt File" option will appear in the module configuration panel with the field for entering a password. It’ll be used to encrypt the generated archives.

Advanced backup

I’ve already covered how to create a quick backup. It’s time for its slightly more advanced version, which you can find in the "Backup" → "Advanced Backup" tab.

Here’s a quick overview of the options available:

  • Source - used to select a predefined source.
  • Backup file - allows you to configure the name and format of the backup file.
  • Backup encryption - enables archive encryption.
  • Take site offline - turns off the website while creating its backup.
  • Exclude database tables - allows you to exclude selected tables in the database (or only their contents) from the backup.
  • Exclude files - used to exclude selected files when creating a directory copy.
  • Destination - allows you to select the backup destination.

If you want to save such a set of advanced options for the future, take a look at the profiles in the "Settings" → "Settings profiles" tab.

Backup list

All backups on the server are listed in the "Saved Backups" list.


Interestingly, this list also works when saving backups to SFTP and S3 servers.

Backup restoration

Less often needed, but still an extremely interesting option, is to restore the website from a backup. For this purpose, you can use either one of the copies from the list presented above or upload any file via the form.


The last important functionality of the Backup and Migrate module is the ability to create backup schedules.


Here you have everything you need to build an efficient backup mechanism. These actions are performed using Drupal CRON functionalities. Therefore, no additional server configuration is needed.

Hooks and integrations

Backup and Migrate provides one basic hook hook_backup_migrate_service_object_alter(), allowing you to change practically the entire engine of the module. This is where additional plugins and filters are defined. You can define the following elements:

  • Backup sources - by default it is the database, public/private files and the entire website along with the source code.
  • Backup destinations - such as cloud storage or local directory storage.
  • Filters modifying the archives being generated - e.g. encryption.

On the basis of the above mechanism, many auxiliary modules that offer integration with external providers of disk space were created. Unfortunately, most of them run only under Drupal 7 control. These include:


In the face of new technologies, the Backup and Migrate module is sometimes considered redundant. However, we use it in our Drupal agency as it offers the easiest way to download a database and files from a Drupal-based website. It’s easy to set up and works almost immediately.

In the case of smaller websites, the module can be useful as a supplement to a standard backup. Especially when the code is on a shared server where you don't have full control of the system.

Feb 12 2021
Feb 12

When publishing a form on your website, you must be aware that sooner or later spambots will find it. It is one of the biggest scourges of the modern Internet. The Captcha module will protect you against such situations.

Further down the article, I will present the instructions for using the module and its potential possibilities. This is essential knowledge that we use in practice as part of the Drupal development services provided by Droptica.


The first version of the module was released in May 2005 for Drupal 4. Developing the version for Drupal 8 took many years. The first try-outs took place in 2013, but the première of a stable version took place only at the beginning of 2020.

Module’s popularity

Captcha is a popular and appreciated module. According to official statistics, it is used by almost 300,000 Drupal-based websites. The latest version from the 8.x-1.x branch is installed on 80,000 websites. The module’s popularity is gradually decreasing – probably due to the transition to other, more modern solutions.


Module’s creators

The Captcha module has five maintainers; they are Jakob Perry (Acquia and Lanfest), Fabiano Sant’Ana (Chuva Inc.), Lachlan Ennis (Expert1 Pty Ltd), Naveen Valecha (Acquia) and Andrii Podanenko (Open Y and ITCare). They are all very active and valuable members of the Drupal community. The official sponsor of the module is the Chuva Inc. company. The code repository consists of 606 commits by almost 120 users.

What is the module used for?

The Captcha module is used to protect forms against spam; it helps you ensure that the website’s visitor is not an Internet robot. There are many ways to check the user’s authenticity (such as reCaptcha) – they are delivered as dependent modules. By default, you can use a simple math challenge that will lock the form if the person completing it fails to add two numbers.


You can download the Captcha module at https://www.drupal.org/project/captcha.

After enabling the Drupal module, the only necessary step is to select the forms you want to cover by protection. Go to the module settings by selecting “Configuration → People → CAPTCHA module settings“ and select the “Form settings” tab. Find your form there and enable it by clicking on the “Enable” button.

CAPTCHA - list

If the form is not on the list, add it by clicking the “Add captcha point” button and enter form_id. The effect of the module for the user login form looks like this:

CAPTCHA - form

Module’s use

The Captcha module has several advanced settings that allow you to customise the protection of your websites better. The most important ones are:

  • Default challenge type - the ability to choose the type of a “trap”, by default it is a mathematical operation. External modules provide other types.
  • Default challenge on non-listed forms - a radical solution that enables protection for all forms that are not listed in the “Form settings” list.
  • Add CAPTCHA administration links to forms - a very useful option that allows you to manage the type of security directly from the given form. It saves a lot of time on complicated websites.
  • CAPTCHA placement caching - cache clearing, useful in the case of problems with forms.
  • Add a description to the CAPTCHA - adding a description explaining why the user needs to prove that they are not a bot.
  • Case sensitive/insensitive validation - determining whether there will be a distinction between uppercase and lowercase letters in solving the “puzzle” presented to the user.
  • Persistence - the ability to disable protection in certain special cases, e.g., when the user has previously confirmed their authenticity.

Hooks and integrations

Captcha provides two hooks to integrate Drupal modules that verify users. These are:

  • hook_captcha() - the main hook used to define your own submodules; it has a structure known from Drupal 7 (it transmits the $op variable containing the type of the currently performed operation).
  • hook_captcha_placement_map() - optional hook specifying the place in the form that should be modified.

This is where the real power of the module lies. At drupal.org, you can find a number of projects that implement various verification methods:

  • reCAPTCHA - to support the most popular verification services available, provided by Google.
  • Image CAPTCHA refresh - this module is an integral part of Captcha for Drupal 8; for Drupal 7 it functions as a separate project. It introduces a widget with an image from which one has to rewrite a text.
  • CAPTCHA Pack (alpha version only) - a collection of very interesting “traps” for bots, including completing a missing letter or word in a sentence.
  • Text CAPTCHA (Drupal 7 only) - integration with the textcaptcha.com website.
  • Captcha Riddler - allows you to define your own set of puzzles for the user.
  • Hidden CAPTCHA (Drupal 7 only) - cheats bots by inserting an invisible field that blocks the form from being sent.
  • CAPTCHA after (Drupal 7 only) - only runs Captcha after the user has submitted the form multiple times.
  • KeyCAPTCHA (Drupal 7 only) - integration with the keycaptcha.com website.
  • Draggable CAPTCHA (Drupal 7 only) - a drag & drop puzzle, no dependence on external websites.


The main arguments behind the module are the effectiveness and simplicity of implementation. It is perfect for fighting against Internet spammers.

We also use it in our Drupal agency as a tool that fits every form and does not require additional coding.

Jan 28 2021
Jan 28

Drupal's editing interface can be unclear to novice editors, and the number of options may seem overwhelming to many. The Simplify module comes in handy here, as it allows you to limit the available functionalities to the necessary minimum, thus making website editing easier.

Further down the article I will present the module's capabilities and the effects of its operation.


The first version of the module was released in December 2010. Since then, it has been slowly but steadily developed. At the end of 2015, a stable 1.0 version for Drupal 8 was released.

Module's popularity

According to official statistics, Simplify is used by over 15 thousand websites, however only 20% of this number are Drupal 8-based projects. The 7.x-3.x branch is currently by far the most popular.


Module's creators

The module has four maintainers, they are:

So far 72 commits have been created in the code repository. In addition to the developers mentioned above, several people have been involved in the project.

What is the module used for?

The module is used to simplify administration forms by hiding selected functionalities from the user. This makes it easier for those less proficient in the use of CMSs to edit pages and blocks.


You can download the module at Drupal.org / Simplify.

After launching Simplify, select the elements that should be hidden from the user. Go to Configuration -> User interface -> Simplify in the administration menu and check out the list of options there.

Module's use

The functionalities that can be disabled are divided into several categories according to the module that supports them. For example, try to disable all the "Nodes" type elements:


As a result, the users visiting the page editing form will see its significantly simplified version - without the author, text type selection, promotion and versioning.


As the administrator, you have the View hidden fields permission which ignores the changes made by Simplify. If you want to put administrators on an equal footing with all the registered users, check the Hide fields from admin users option.

By default, the Simplify module allows you to hide the editing elements of nodes, blocks, comments and taxonomies.

Hooks and integrations

The module provides two hooks for adding your own exclusions to any form. Their use is very simple:

  • hook_simplify_get_fields_alter() - is used to change the list of exclusions; here you can add your own options or remove the existing ones
  • hook_simplify_hide_field_alter() - in this hook you hide a given field by modifying the array containing the form


Simplify is a module that is simple by design but is a great help for novice editors. It is good to consider using it on corporate websites where the user may be overwhelmed by the number of options available. Referring to the experience of our Drupal agency in cooperation with clients, I recommend it, especially if you put a lot of emphasis on edit forms.

If you are interested in CMS optimisation, check out the article on 6 ways to improve editors' productivity.

Jan 22 2021
Jan 22

Paragraphs are one of the solutions competing for the title of the most convenient way to create content in Drupal. They are a great and consistent concept, however their UI leaves much to be desired. Thanks to the Geysir module, you will be able to improve your paragraph experience.

It is a module that cannot be easily ignored. We liked it so much that it has become one of the key elements of the Droopler distribution created by Droptica.


The first developer release of Geysir was introduced in September 2016, and the stable version was published exactly one year later. There were two major updates in 2020; many of the bugs they fixed were reported by our Drupal developers.

Module's popularity

Geysir is a relatively new module. According to the official statistics, it is used by about 500 websites. About 20% of this number are installations of the aforementioned Droopler.

Module's creators

The module has four maintainers from the Amplexor company, namely: Sander Vleugels, Jochen Verdeyen, Kevin Van Ransbeeck and Jan Lemmens. Together with 11 other developers, they have created 140 commits so far.

What is the module used for?

The module introduces a convenient interface for handling paragraphs, operating directly in the frontend part, bypassing the administration panel. Thanks to Geysir you can avoid the time-consuming browsing of the list of paragraphs. All you need to do is place the cursor over the content you are interested in and click the edit icon. In addition to editing, you can also add new paragraphs and move existing ones.

[embedded content]

For more videos on how Geysir works, check out our article on how to shorten time creating marketing campaigns using landing pages.


You can download Geysir at https://www.drupal.org/project/geysir - it has no configuration. The Paragraphs and Entity Reference Revisions modules are required for its operation. You can enable access for individual user roles via the "Manage Paragraphs from the front-end" permission.


Module's use

After launching Geysir, you will notice a "Paragraph overlay" button in the upper right corner of the page. It is used to switch between the edit modes.


Activate the button and go to the subpage with paragraphs. Note that from now on, you do not need to use the page edit form in order to change something. You can just use the icons provided by Geysir:


In the above screenshot from the Droopler distribution, you can see four new options:

  • Add a paragraph in the selected place.
  • Edit a paragraph.
  • Cut and paste a paragraph to move it within the page.
  • Delete a paragraph.

All these operations work via AJAX without the need to reload the page.

You will surely be interested in what adding and editing paragraphs looks like in this case. Well, the forms are launched in a modal window:


The advantage of this solution is the extraordinary speed of introducing changes. What is important, this method of content modification is much easier to understand, which makes training the employees responsible for the website easier. Try to create at least one website using Geysir, and I am sure you will notice a significant difference to the standard edit page.

Regarding the disadvantages of the Geysir module - note that the paragraph editing form above uses mostly the frontend skin. The skin of the administration panel (Seven, Claro, etc.) is sometimes overwritten here. Hence, functionalities such as views from the Media module require special treatment in order to ensure full compatibility and a consistent UI.

Hooks and integrations

The Geysir module provides one hook: hook_geysir_paragraph_links_alter () for changing the list of icons depending on the context of their use (paragraph type, parent entity and the reference field used in it).


If you use paragraphs, give Geysir a chance. It is a module that may cause some problems at first, but in the long run it will significantly speed up your work, which we can absolutely confirm in the case of many projects that we have carried out in our Drupal agency.

If you need a ready-made and proven solution, I encourage you to familiarise yourself with the Droopler distribution that we develop, which has a number of visual improvements to work between Geysir and Bootstrap 4. It is open source software and you can install Droopler yourself at no cost.

Jan 21 2021
Jan 21

In the era of increasingly distributed architecture of applications and web portals, there is a need to provide flexible methods of authentication while maintaining convenience for the user. From this article, you will learn how to easily create an authentication server and client application in Drupal using OAuth2 and OpenID Connect.

Distributed systems, their scaling and maintenance is a problem for many clients who come to our company to take advantage of the Drupal consulting services. Very often, there is a need to implement a central login system for all platforms belonging to a wider federation of websites. Large companies and organisations have separate portals – we have created image-building websites, intranet systems and Drupal Commerce services for them many times, taking into account various functions. The need to register a separate account and log in by users in every single place separately seems to be an archaic way of dealing with the problem. After all, who among us does not make it easier for themselves to register on websites on a daily basis – for example by employing quick registration methods using an account on a social network or a Google profile?

Why not do the same, especially since – as it will turn out in a moment – using Drupal for this is very easy.

OAuth2 and OpenID Connect

In order to shed some light on the whole problem, one should, first of all, focus on the commonly used standards in web applications that are used in the authentication process.

The first is OAuth2, an open standard for authorisation that does not require sharing authenticators between applications. Access to resources (if it has been granted) is being verified on the basis of a token issued to client applications by the authorisation server.

As OAuth2 was designed with authorisation in mind, that is – with granting specific access to given resources; it is not really directly intended for a standard user authentication (logging-in) process. For this purpose, it was decided to propose an additional (authentication) layer to the OAuth2 protocol, which standardises this exact process in it. This technology is called OpenID Connect and – apart from the logging-in process – it also unifies the method of exchanging user profile data between applications. We will, therefore, take a look at how to employ both technologies in practice.

Installation of the modules

If you want to set up both the OAuth2-based authentication server and the client applications based on OpenID Connect, in Drupal, you can basically use ready-made solutions. In the case of a server, you have several appropriate modules, including the most popular one (simple_oauth). In our example, we will use the OAuth2 Server module. It is slightly less popular and has not yet been released as a stable version for Drupal 8 and 9, but it is supported by significant companies and organisations related to Drupal.

Additionally, the second client application module, OpenID Connect, is a project being maintained and developed by exactly the same organisations and development team. You can, therefore, be sure that both projects will be developed simultaneously and that no problems with their compatibility will arise at a later time.

The modules' installation is standard. First, you need to download and install the modules on our server:

composer require drupal/oauth2_server
drush en oauth2_server -y && drush cr

Then, in a similar way – for the client:

composer require drupal/openid_connect
drush en openid_connect -y && drush cr

The main dependency needed to install the server is the oauth2-server-php library which provides the basic mechanisms to fulfil this role. If you are using Composer in PHP, all dependencies are already terminated automatically for you.

Server setup

The setup of the OAuth2 Server module is mostly based on entities. Therefore, among the things it provides are the entity of the server, client, token, etc. Our setup must begin with defining the server. So, we go to the setup page /admin/structure/oauth2-servers.


And add a new server (Add Server). In the next step, we see the server entity form:


In the simplest configuration variant, we leave all the values selected by default and filled out. In addition, we check the "Use OpenID Connect" option as the default layer used in the logging-in process.

As you can see from the settings, the authentication and authorisation process takes place without the use of the authentication data sent by the client, but on the basis of an authorisation code – exchanged then for the access token and the refresh token, which are exchanged during the communication between the applications. The technical details of the OAuth2 protocol go beyond the scope of this article, so if you want to know more about how the individual options and the protocol itself work, you can do so using the official documentation.

In the next step, we should define the clients that can connect to our server. We must, however, have at least one client application in order to do this.

Client setup

OpenID Connect is a very user-friendly module also in terms of setup. To configure the clients you want to use, go to /admin/config/services/openid-connect.


As you can see, there is a list of clients in the form. The module, therefore, allows you to easily login using, e.g., well-known social networks. Each type of client is defined as a separate plugin (OpenIDConnectClient), which makes it easy to extend the project with completely new clients. Our example, however, is about connecting to our own server, so we will use the client for generic uses (Generic).

The configuration is quite simple because it consists of defining the client's name and the so-called secret key, as well as providing the server addresses:


While we are at it, we will add a small improvement, namely – replace the logging-in form with a login button using our authorisation server. It is very simple and accessible from the setup form:


Great! The client looks ready to use. The only drawback is the lack of a convenient option of changing the name from "Generic" at the moment without a bit of coding, but the result still looks great for such a quick setup:


Server setup part two

We have a pre-configured server, as well as a ready client. So, let us define our client in the server setup so that it knows it can connect to it and request access to its resources. Drupal is a very secure CMS compared to the competition, but the security is also based on its correct setup.

Always remember that it is up to you to verify and configure what client applications should be able to connect to the server and use its resources.

In order to add new clients, go to the Clients tab, and then click the button for adding new clients.


You should see a form, the data of which should be filled out in the same way as what you set up in the OpenID Connect module in the client application.


We save the form, and it is ready... almost. You still have to grant the appropriate permission, so that it would be possible to use the OAuth2 server at all. In order to do this, go to the /admin/people/permissions page and assign the Use OAuth2 Server permission for the anonymous user.



All is set. So, let us check the actual logging-in scenario. First, we will register the test user on our server so that they can log in into our other applications.


Go to the client's application (login form) and click the Log in with Generic button (form screenshot).

You are redirected to the server login page on the server along with the destination parameter destination


After correctly entering the login and the password (test:test), you should see this additional step ...

the form

...in which you decide as a logging-in user whether you actually want to authorise our client page to your user data from the server, on the basis of which a local user account will be created.

After approving it, you are redirected to the client application page as a logged-in user:


Success! We can now fully enjoy our central login system.


The possibility of creating a central login system is a more and more frequently occurring need among the clients who have various types of distributed services, sites, and applications. By choosing Drupal, you can focus on implementing specific business rules, instead of reinventing the wheel. Using the ready-made solutions, such as OAuth2 Server or OpenIDConnect, supported by well-known organisations, gives you the certainty that you will easily implement the mechanism you need – even without the need for detailed knowledge of the protocols used in them.

In our Drupal agency, we always use the already available solutions which we often extend, and we adapt Drupal modules to the specific business model. I hope that the above article and the modules used will also prove useful in your project.

Jan 08 2021
Jan 08

Website statistical data is required knowledge if one wants to effectively manage the website, and thus – determine the directions for its further development. Thanks to numerous Drupal modules, you can make the necessary improvements also via integrations with Google Analytics. In this article, you will find information about the GoogleTagManager (google_tag) module, thanks to which you can conduct an effective and structured analysis of your website.

The need to put external scripts on websites dates back to the 90s, when webmasters got a taste for counters and guest books. Over the past three decades, simple external services have evolved into advanced and powerful solutions such as: Salesforce, Hotjar or Mautic, the implementation of which we provide at Droptica. Modern websites use dozens of tools to research user behaviour, collect the data on visits and for A/B testing. Today it is difficult to imagine effective marketing without them.


The Google Tag Manager service was launched in October 2012, and the Drupal module to support it was released in February 2014. A stable version of the module for Drupal 8 was released only at the beginning of 2018. The development was quite slow, however google_tag was very stable from the beginning.

The module's popularity

It must be said that the module has won over a large group of users. According to official statistics, it is used by over 51 thousand websites while more than half of this number are websites based on Drupal 8/9.

Module's creators

Jim Berry from Boombatower is responsible for the maintenance of the module. He is a developer who has made a huge contribution to the Drupal community. He is the author of over 1500 commits in dozens of projects.

What is the module used for?

The google_tag module is used for advanced integration with Google Tag Manager, reaching much further than simply pasting the GTM script into the website code. Here you have access to user roles and exclusion lists, among others. I will present all these functionalities later in the article.


You can download the module at https://www.drupal.org/project/google_tag. After the installation, add a new container and enter its ID obtained in the Google Tag Manager panel. You can find the module settings in the Configuration - System - Google Tag Manager menu.

Module's use

The google_tag module has a default configuration that will work for the vast majority of applications. However, it is worth looking into the advanced settings, which give more control over the included scripts.

Containers list

A novice user will certainly ponder what the list of containers available in the configuration panel actually is. Well, the latest versions of the module allow you to handle more than one GTM container (in other words: various unique identifiers assigned by Google). Such a solution works perfectly when you have a page farm for which you can separate common scripts stored in a shared container.


When adding a new container, you will see a form with the default settings filled out. If you do not want to waste time customising each of the containers, you can specify the default settings in the "Settings" tab.

Adding a container

The form for adding a container mainly contains its unique identifier (Container ID) obtained from Google and a label that will be used to recognise individual containers within the Drupal administration panel.

Google Tag Manager - Container add

In the "Advanced" tab you can find three interesting settings:

  • Ability to rename a data layer. In most cases, the standard dataLayer is enough, but it is worth keeping this option in mind in case of a conflict. To clarify: a data layer is an array (more precisely - an object) in JavaScript that is used to transfer data from a website to a GTM container.
  • Support for allowlist and blacklist options, described in more detail in GTM help. This is a rarely used, but useful functionality that allows for additional blocking of some tags in the production environment before they are ready for implementation, among other things.
  • Configuration of the current environment which enables switching between the production and development set of tags.

Google Tag Manager - Container add advanced

A bit further down you will find the exclusion settings. The GTM script can be activated and deactivated based on:

  • The current path in the URL (by default, tags are not launched on admin pages).
  • User Roles (A common case of use is disabling analytical scripts for the administrator role).
  • HTTP status code (e.g. 404).
  • Content type.

Google Tag Manager - Container add exclusions

Module configuration

In the settings tab there is a configuration common to all containers. There are several options to improve the performance of your website and make debugging easier.

Google Tag Manager - settings

The first four settings are for the optimisation of the JS script delivery that supports Google Tag Manager. I recommend leaving the recommended values here, and at the same time I would like to warn you against possible errors returned in the website log. During projects in our Drupal agency, we often encountered a situation where the GTM script file was not generated due to the lack of directory permissions.

Hooks and integrations

The google_tag module provides the following hooks:

  • hook_google_tag_insert_alter () - unlocks or blocks a given container if you want to make its operation dependent on factors other than the standard ones (i.e. role, path, content type and HTTP code).
  • hook_google_tag_snippets_alter () - changes the default JS code that supports GTM.

In addition, it is possible to implement plugins providing Conditions for placing the Google Tag Manager script on the website.


In a previous article I discussed in detail the integration of Drupal with Google Analytics. I am sure that use of the above, together with the google_tag module described in this text, will make website analysis even more effective and orderly. The google_tag module has almost become an industry standard over the past few years. I recommend using it and exploring the possibilities that the world of Drupal tags and data layers opens up for us.

Dec 18 2020
Dec 18

Security Kit is a module that helps with eliminating the likelihood of exploiting security vulnerabilities on your website. Thanks to a multitude of features, such as Anti-XSS, Anti-CSRF, Anti-ClickJacking you can get yourself a peace of mind and comprehensively define a security policy for your website.

At our Drupal agency, we value the security of our customers' websites and make every effort to ensure that the solutions we provide are as bug-free as possible, which is why our development team uses tools to achieve this goal optimally. We use modules provided by Drupal's outstanding community, which facilitate this process. For example, when auditing an acquired project, we use the Hacked module, and while implementing the solutions required by your projects, we are always taking advantage of the Security Review. Today I would like to introduce you to another module that will help you secure your website – Security Kit (SecKit).


The first version of the module was released on 26 March 2011. The latest update was released on 28 August 2020. The module is now considered to be feature-complete by its developers – new features are currently not being developed, and the updates focus solely on patches.

Module popularity

The module is used by about 56,000 websites, including 25,000 based on Drupal 7 and 26,000 on Drupal 8.


You can find detailed popularity statistics here.

Module developers

The module was developed by p0deje. It is currently maintained by Acquia and Catalyst IT. The vast majority of commits were provided by p0deje (141), jweowu (26) and mcdruid (24).

As of now, the module has four maintainers: mcdruid, jweowu, badjava, and p0deje.

What does it do?

Security Kit combined with Drupal offers additional options and features that improve security, reducing the risk of exploiting vulnerabilities on your website, by adding Anti-XSS, Anti-CSRF, Anti-ClickJacking, HSTS and CORS implementations. The module enables you to define a multitude of security policies – you can find a description of each configuration option in the "Settings" section.

Let's take a closer look at what it can do for you!


Features that help lower the possibility of exploiting cross-site scripting (XSS) vulnerabilities on your website. XSS is a type of website vulnerability that allows the attacker to execute any JavaScript code directly on the end device. XSS may result in leaking data, such as login and password, credit card details, user account information and much more. There are a number of types of XSS attacks; if you want to learn more, you can start exploring them here.


Cross-Site Request Forgery (CSRF) is an attack type that allows the attacker to trick end users into performing specific actions on a website. A CSRF attack may, for example, result in the end-user losing their funds, changing their email address linked to the website, changing their password and any other action which the user can perform.


Clickjacking is an exploit which enables an attacker to trick end users by displaying a concealed xframe, which the user can unwittingly click to run a given action on another website. Attacks of this kind can be used, for example, to farm likes on the attacker's Facebook page. The latter type of attack now even has its own name – Likejacking.


HTTP Strict Transport Security (HSTS) security policy that minimises the risk of man-in-the-middle attacks, which entail modifying a request before it even reaches the server.


Cross-origin resource sharing (CORS) is a mechanism that allows you to specify a list of trusted domains from which the user can download resources on your website.


The module does not require any external libraries to work correctly. Security Kit can be installed in a standard manner, but – as always – we do recommend using composer:

composer requires drupal/seckit


Cross-site scripting

This section contains settings that boost your website's security performance in terms of XSS-type attacks.


Content security policy

Security policy enables you to identify trusted content sources. Serving content from untrusted sources may lead to security issues, such as data leakage and malware distribution. You can read more about this here.

Send HTTP response header

If you select this option, the CSP policy is enabled.

Enable Upgrade Insecure Requests

If you select this option, all HTTP requests are redirected automatically to HTTPS.

Report only

If this option is selected, all the cases of content security policy breaches will not be blocked, only logged.


This option defines a security policy for all content on the website, such as scripts, styles, images, media, frames, etc. If you do not specify a separate policy for a given content type, the CSP will use the policy specified in this field.

This allows you to provide trusted sources for particular content types, such as script, object, style, img, media, frame, font.


Path used for reporting requests violating your CSP policy.


If you want your CSP policy to be saved in one file, here you can specify a path. If this field is filled, the settings per content type are omitted.

X-XSS-Protection header

Each browser has its own internal safeguards against XSS. X-XSS-Protection header enables you to disable the default anti-XSS protection built into your browser, run the safeguards along with modifying unsecured content to protect users from XSS attacks or run protection mechanisms that will block all dangerous content. If you would like to learn more about the header, take a look here.


This section contains settings that protect your website from cross-site request forgery attacks.


HTTP Origin

If you select this option, you enable the validation of the HTTP request source, thus enabling CORS protection.

Allow request from

A list of accepted requests.


This section contains settings that improve your website's security in response to ClickJacking attacks.


X Frame options

X-Frame-Options configuration

  • Disabled - disables the X-Frame-Options header.
  • SAMEORIGIN – makes it so that the page can display xframes only served from the same domain.
  • DENY – locks all xframes.
  • ALLOW-FROM – allows you to specify a list of domains with xframes enabled.

You can read more about the XFrame header here.

You can also find the header specification here.

JavaScript-based protection

Enables anti-clickjacking protection using JavaScript. This solution will not work for users who block JavaScript using browser plug-ins such as NoScript.

Custom text for disabled JavaScript message

Enables you to provide a message that will be shown to users blocking JavaScript on your website, as well as users whose browsers do not support JavaScript.


A section containing settings improving SSL/TLS security.


HTTP Strict Transport Security

Enables the Strict-Transport-Security (HSTS) header – enabling this option will increase security by reducing the risk of man-in-the-middle attacks such as SSLStrip. You can read up on HSTS here.


Defines the max-age value of the HSTS header. Max age is the number of seconds for which the website is treated as HSTS-enabled by the end-user.

Include Subdomains

Enables HSTS for all subdomains – by default, the HSTS header is only sent from the main domain.


Most popular browsers have HSTS preload lists with sites that are defined as HTTPS-enabled. If you want your domain to be added to the HSTS Preload list, you need to check this option.

Expect CT

Expect-CT header configuration options allow you to enable reporting and enforcing the Certificate Transparency policy. The Certificate Transparency Policy defines the sources, delivery and signing mechanisms of certificates when using TLS connections. You can read more about this here.

Expect CT


Enables Expect-CT header.


Defines the max-age attribute for the Expect-CT header. Max age is the number of seconds after receiving the Expect-CT header during which the user's browser considers your website to be compliant with Expect-CT header.


URI for reporting Expect-CT errors. Errors are reported if the user does not receive correct CT information.


The optional header parameter specifies whether the user should enforce the Certificate Transparency policy or only report in case of an error.

Feature policy

Configuration options for the Feature-Policy header, which determine the API configuration and behaviour, as well as features provided by the browser, for example, it allows you to limit the APIs used for interacting with user's camera or microphone, as well as change the default behaviour of the autoplay attribute on mobile devices. You can find out more about this here.

Feature policy

Feature policy

Checking this option enables the Feature-Policy header.


Defines the Feature-Policy header policy.


Configuration of the remaining module options that do not belong to any particular category.



Enables the From-Origin-Response header. This option specifies websites on which the resources from your website can be embedded. You can find out more about this in the header specification.

Allow loading content to

Enables you to specify a list of domains, where your content can be embedded (if From-Origin is used).


Enables the Referrer-Policy response header.

Select policy

Defines the policy for the Referrer-Policy header. Information about this header and available options can be found in the specification.

Disable autocomplete on login and registration form

Checking this option will disable the ability of the browser to fill in the login and registration forms automatically.


The presented module enables you to configure many options that increase the security level and performance of your website. It also provides you with a number of ways that allow you to define security policies, while the added security mechanisms help protect your website against popular attacks. Our Drupal developers recommends deploying the SecurityKit module.

Dec 17 2020
Dec 17

Google Analytics is, by far the most popular tool to track your web page visits, used by tens of millions of sites around the world. Integration with Google statistics is the most basic and essential function of every CMS, which means it is also available in Drupal – you can enable it with the google_analytics module.

The module has numerous interesting features, which can be easily missed among the many configuration options. In this article, I will showcase some of the most useful options, based on experiences with large Drupal corporate websites.


The google_analytics module has a long and rich history, as the very first development version was released in February 2006 for Drupal 4. The first stable release saw the light of day a year later, in March 2007. The current version – 3.x – was released in early 2019. Unfortunately, dynamic changes in the module have recently slowed down considerably, perhaps as a result of changes in the development team.

Module popularity

The google_analytics module is one of the most popular Drupal add-ons, and the official data report that it is used on 323,000 pages in total. The latest 3.x version is used by more than 27,000 Drupal 8 and 9-based websites. Module authors Currently, developers from two companies are responsible for maintaining the module: IXIS (Mark Byrne, Mike Carter) and Acquia (Jakob Perry). By far the largest number of commits was made by one user – hass, who has been inactive on drupal.org for quite some time now.

Together with the people mentioned above, 66 people in total have been involved in the development of the module since 2006. You can see their contributions at committers website

What does it do?

The google_analytics module, as the name suggests, is used for integrating Google Analytics statistics with Drupal-based websites. Although this integration is very simple and basically boils down to placing a small script provided by Google somewhere in your HTML code, using a dedicated module for this is very much worth it, as it will enable you to tailor your visit tracking to your needs and eliminate unwanted things from your statistics.


You can download the module from https://www.drupal.org/project/google_analytics. After setting it up, all you need to do is to provide the code provided by Google (it starts with UA-). If you forget to enter the code in the settings panel, you will receive a warning when you log in as an administrator.

You can find the module settings in the Configuration → System → Google Analytics menu.

Using the module

The vast majority of users use the module in its default configuration – they only provide the tracking code, and thus all the following features remain active:

  • exclusion of statistics on administrative pages;
  • enabling the tracking of external and mail-to links;
  • recording downloads as events;
  • tracking the usage of pop-up windows provided by the Colorbox module;
  • anonymisation of IP addresses sent to Google.

All of the above features will be described in more detail later in this article.

Multi-domain support

Drupal has extensive support for multiple domains within a single project, and in such case, it is crucial to include an additional column concerning the current domain or subdomain in the statistics. The google_analytics module fully supports multi-domain configurations, which can be further customised with a single checkbox.

ga multidomain

Excluding pages and users

Another very important feature offered by the google_analytics module concerns disabling tracking if certain conditions are met. Just like in the case of block configuration, you can select the pages where your tracking code will be enabled or disabled, which will allow you to eliminate unwanted locations that disrupt your results.

Google Analytics - Wykluczenia stron

You can do the same thing for certain user roles. By excluding administrators, you will make sure that your activity on the website will not be tracked.

Google Analytics - Role użytkowników

Additionally, users can decide for themselves whether they want to be tracked. If you care about their privacy, select the following option:

Google Analytics - Opt-in

Users with the role of "Opt-in or out of tracking" will be given the option to disable tracking in their profile options.

You should pay particular attention to the "Track User ID" option. If it is checked, Google Analytics will start distinguishing users by their Drupal identifier. Using this feature may be very tempting from the point of view of the quality of the data collected, but it entails major changes in privacy policy to ensure compliance with the GDPR.

Given the privacy point of view, the "Anonymize visitors IP address" option, which is also crucial, is hidden in the last tab. It cuts off the last part of the user's IP address sent to Google Analytics, making the tracking less accurate but more anonymous.

Tracking links and downloads

The standard Google Analytics tracking code does not offer features that enable tracking external links and file downloads, which is why you will undoubtedly appreciate the automatic modification of Drupal link behaviour thanks to JavaScript. After clicking on a link, GA receives an event containing the URL. This way, you are able to estimate the popularity of links and files.

Google Analytics - Download

Some of the other options in this tab enable you to:

  • Track events in Colorbox;
  • React to changes in the URL;
  • Use "In-Page Analytics" service – the visual map presenting the popularity of your links – in a more precise manner. I would recommend this feature in particular when the person responsible for marketing can quickly introduce in-depth changes to the website (refer to our article about quick campaigns using landing pages).

Message tracking

Another small yet very significant addition is tracking messages displayed at the top of the page. By using this, you can use a message about successfully placing an order as a separate event, which in turn can be used as one of the Google Analytics tracking objectives.

Google Analytics - Messages

Search and advertising tracking

The "Search and advertising" tab has some more niche functions:

  • "Track Internal Search" tracks searches on the website;
  • "Track AdSense ads" sets up integration with ads running on the website via AdSense and enables advanced effectiveness reports;
  • "Track display features" activates advanced marketing features, including remarketing. This option requires special provisions in the website's privacy policy, as it significantly impacts compliance with the GDPR.

Google Analytics - Search, AdSense, Remarketing

Customised dimensions and metrics

Google Analytics reports offer extensive possibilities of expanding columns and rows in your tables with custom elements, using dimensions and metrics.

The google_analytics module allows you to add up to 20 custom metrics and dimensions, including tokens defined in Drupal. Here are two examples that will make it clearer.

The dimensions describe the page in question. They can be a category or a tag. For example, by adding a non-standard dimension in the form of an article category, you can determine the popularity of a given topic.

Google Analytics - Dimensions

The metrics measure objects. Google Analytics is able to sum up data and carry out operations on them. When you add a metric with a value of 1 when an article is promoted, you can sum up and compare the number of promoted and standard impressions in the report.

Google Analytics - Metrics

Other options

Among the other available options offered by the module, there are:

  • Local caching of Google Analytics code;
  • Aggregating multiple language versions of pages in the statistics;
  • Defining additional parameters to be provided to Analytics;
  • Launching your own scripts before and after executing the GA code;
  • Developer mode.

Hooks and integrations

The module does not offer any hooks. As far as integration is concerned, it works mainly with Colorbox.


The google_analytics module is an extremely powerful tool, which will undoubtedly be appreciated by users who appreciate accurate and effective web analytics. Despite the rather small set of integrations with other modules, it offers in-depth customisation, which allows you to adapt the configuration to your needs.

Projects that are developed at our Drupal agency usually take advantage of Google Analytics. We have already mentioned in our other articles that advanced integration with GA is one of the important advantages of Drupal as a CMS for building large websites.

Dec 09 2020
Dec 09

When working on a project, there are many ways to increase the security of a website. One of them is the use of automated security tests that assist developers in eliminating as many security bugs as possible.

At Droptica, our Drupal developers focus on delivering the safest solutions. The Drupal CMS itself helps us in this, as it is safer than other CMSs. Thanks to the huge community focused on opensource projects, one of which is Drupal, clients, on the one hand, receive effective solutions, and on the other hand, can be sure about their security. At this point, it is worth to mention a special team dedicated to this issue, which is the Drupal Security Team.

In this text, I would like to introduce you to the operation of one of the tools to increase the security of your website – the Security Review module.


The module was released on 4 November 2009, and the most recent update was introduced on 4 October 2019. The module has a version for Drupal 7 and 8

The module’s popularity

According to drupal.org, 30,000 websites are using the module, 28,000 of which are Drupal 7 and 2,000 are Drupal 8.

Module’s creators

The module’s creator is the user named greggles. The module is supported and developed by the Acquia, CARD.com and Google Summer of Code organisations. The most commits were provided by the users coltrane (111), banviktor (58) and greggles (8).

What is the module used for?

The module performs an automatic website audit detailing many attack vectors that can lead to security errors. Here is the list of some of them:

File permissions

Saving files to the server’s root directory is dangerous and may lead to a remote code execution error. An attacker can use this vulnerability to take control of a website. More information on the correct configuration of permissions can be found at this link.

The list of tags accepted by the text formats available in the CMS

Some HTML tags are considered unsafe. This means that they may allow an attacker to take control of a website. Drupal has an HTML filtering engine that removes malicious tags - this test checks if the filtering is set up correctly.

Error reporting

Drupal may disclose information about errors to unauthorized persons. An attacker can use this information to refine an attack or find more vectors.

Unsafe file extensions

Some extensions are considered unsafe. This means that they can cause security errors such as remote code execution. This allows an attacker to take control of a website, and Security Review checks whether Drupal enables the transfer of files with unsafe extensions.

Database errors

Many database errors triggered by a single IP address are a sign that someone is trying to make a SQL injection attack. The module informs if multiple database errors were triggered from the same IP address.

Login panel brute force

Multiple failed login attempts are an indication that someone is trying to get into another user’s account. You are being informed about it.

Trusted hosts (HTTP host header attack)

Correct configuration of Trusted Host protects against HTTP host header attack, a detailed description of the settings is available at this link.

Views access

Security Review recommends that access to Drupal views should have at least minimal ‘access content’ control. This test checks whether the views have at least a minimum level of access control.

Security Review does not introduce any security fixes but only suggests where vectors of attack may be present. These are suggested changes that need to be analysed by a specialist.


The module installation is standard, but we suggest using the Composer:

composer require drupal/security_review


Under the address


you can configure the module by selecting roles that are not trusted. Security Review uses this as a basis for checking whether the users with not trusted roles have permissions to the functionalities that may cause security errors. You can also choose which items from the checklist you want to omit and choose the method of checking the trusted hosts.


Role configuration

The module provides two types of permissions: ‘access security review list’, ‘run security checks’. First, you need to configure the trusted roles that will be able to read reports and run the scan. In order to do this, go to


and configure the permissions for selected roles:


Module’s use

The module has already been configured. To run an audit, just go to


and click “Run checklist”, and Security Review will conduct the audit. You can also use the drush command:

drush secrev


Every test has a summary that you can see by clicking on the “details”. An example for “Errors are written to the screen”:


Moving on to the error logging settings, you can see that Drupal shows all the information, including the backtrace:


In the case of a production version of a website, set this option to “none” in order to minimise the risk of disclosing information that could help an attacker to hijack the website.

Similar information is provided for each of the security errors detected during the audit. All items should be reviewed manually, and appropriate changes should be made – if required.

Alternative modules

The Paranoia module identifies all the areas where a user may be able to trigger the custom PHP code and tries to block them. This reduces the possibility of a remote code execution error occurring. In addition, the module protects the main admin account (account with id 1), preventing its editing and blocking the possibility of uninstalling itself using the standard way (to uninstall the paranoia module, you need to edit the database manually). All the functionalities provided by the Paranoia module are intended to increase the security of a website.


The Security Review module is an extremely important and useful tool. Thanks to the information collected by the module, you gain invaluable knowledge of what should be done in order to improve the security of your website. After analysing the results, you can eliminate some of the attack vectors. Our team recommends using this module when creating a website.

Dec 03 2020
Dec 03

Recurring payments are gaining in popularity and are also increasingly used by well-known brands. You will find this type of a settlement model in Netflix, Spotify, or Apple Music, among others. Undoubtedly, they are convenient for e-business due to the regularity and timeliness of payments, full automation, and security. If you want to implement this method of collecting payments, I encourage you to read this article. You will learn how to do it in Drupal Commerce.

What are recurring payments?

These are payments that are collected from customers between selected periods of time. Most often, these payments are made monthly, but there are also other models. Some systems collect payments once a year, others – once a week. It is also possible to define a quarterly cycle. Other time intervals are less common.

What can you sell using recurring payments?

Netflix and Spotify mentioned in the introduction are systems with a database of files (video, audio). In order to have access to them, one must make recurring payments.

In our Drupal agency, we implemented a similar project – using Drupal, of course. After making a payment, the user gets access to the system and unique PDF files. The client has the option of purchasing a single, specific file, as well as paying for a monthly or annual subscription. The latter option allows them to get access to all files in the system.

A similar system that we developed at Droptica is Training Realm. It is a web application that offers users the ability to log training sessions, create training schedules and adjust the difficulty of training cycles to the user's level. And as you can probably guess, we also used the recurring payment service in this case.

In the examples above, you can see that recurring payments are most often associated with digital products or services. Of course, this solution can be implemented to sell physical products. A perfect example is diet catering. The system automatically charges a monthly fee for the food to be delivered over the course of the next 30 days.

As you can see, the uses are many. Recurring payments are very convenient for businesses, as they provide them with regular income over a predictable period of time.

Installation of the recurring payments module in Drupal Commerce

I will present enabling and configuring the Commerce Recurring module on the basis of the Droopler distribution. We have prepared a starter package for Drupal Commerce there – just enable the d_commerce modules (screenshot below) to get a ready-made Drupal-based Commerce system.

Installing the Droopler system is very simple. Instructions for Composer can be found here.

If you already have the Droopler system, you need to install the Commerce Recurring module.

Download the appropriate Recurring module files and any additional modules needed for this example with the command:

composer require drupal/commerce_recurring drupal/facets_pretty_paths drupal/commerce_paypal

After running these commands in the terminal, you should see this effect:


In the next step in Drupal, go to the module list page (/admin/modules) and enable the following modules:

  • d_commerce 
  • d_commerce_product 
  • d_commerce_products_list
  • Commerce Recurring

For recurring payments, you will also need a payment module that supports recurring payments. In this entry, the example will be based on the Commerce PayPal module.

You can download the module using the command:

composer require drupal/commerce_paypal

The description of how to enable and configure the module can be found on the drupal.org project website.

Configuration of the Commerce Recurring module

After installing the module, we will see two additional pages in the admin panel:

  1. Billing schedules /admin/commerce/config/billing-schedules
  2. Subscriptions /admin/commerce/subscriptions

We will start with the settings on the Billing schedules page. Here you can decide whether the client will pay monthly, weekly, or daily. Or maybe you want to charge every 13 days? Yes, you can configure such a payment period as well.

In addition, you will also set the parameter deciding when the payment is to be collected: whether it should be immediately after the purchase or maybe at the end of the set period (e.g. at the end of the month).

You will also decide whether the payment is always to be collected on the first of the month or if it should be collected on the same day of the next month in which the purchase was made (e.g. purchase on the 13th of the month, so payment will always be on the 13th of every month).

Another parameter is proportionality, e.g. for annual payments: if someone makes a purchase in July, you will define whether they pay the amount for a whole year or only for half a year, and the next payment for a whole year will be in January.

At the end of the form, you will decide what to do if the payment fails (e.g. you can retry the payment in 3 days).

As you can see, the configuration options are many. Everyone will find a configuration that fits their business model.

Recurring monthly payments

Below you will find an example of form settings for recurring monthly payments. Payment will be charged in advance and always made in full per month (calculated from the date of purchase by the client).

In the event of a payment failure, the system will try to process the payment three more times before disabling the subscription.

This is how it looks in the form:



The full description of the settings for this form can be found in the documentation on the Drupal Commerce page.

Adding recurring payments to a product

In this case, you will see what a recurring payment looks like in relation to a product, e.g. the diet mentioned above catering.

It is a common practice to create a separate product variation that allows for a subscription. In general, every product can have a variation that will differ in price, SKU code, and/or other characteristics.

For example, an e-commerce platform dealing with the sale of clothing may have a "T-shirt" product created the variations of which will be different colour versions. In order to create variations, go to

  • '/admin/commerce/config/product-variation-types'

or through the menu

  • Commerce->Configuration->Products->Products variation types and then click "Add product variation type".

In this simple form, enter the name of the variation to be created and select "Allow subscription".


Every created product type allows you to add one variation. So, if you do not want to lose the existing products, you have to create an additional product type, the variations of which will be subscriptions.

To do this, go to '/admin/commerce/config/product-types' and click on "Add product type". Fill out the form from the drop-down list and select the previously created variation ('subscription' in the case of this example).


Then you need an actual product that the end-user can add to the shopping cart. You can add it by going to the page "/product/add". From the list of product types, select the previously created "Subscription product". Fill out the form in accordance with the fields being displayed, and then click "Save and add variations". You will see a table showing all the created variations related to this product. Click "Add variation". In the displayed form, fill out the fields such as SKU and price.

The title field, in this case, is the name of the variation being created. As mentioned earlier, one product can have any number of these, and the name of the variation itself, along with the product name, will be displayed in the order and the cart. In the case of a subscription, you can create variations divided by period, e.g. a month, half a year, a year. For this example, we have created a monthly subscription so that we will name the product variation "monthly" and in the Billing schedule field, we will select the monthly interval that we created earlier.


After clicking the "save" button, you return to the list of variations of a given product, as can be seen on the list, the title of the variation ultimately consists of the product name and the associated variation name created.


In the next step, you can go to the product view, add it to the cart and go through the purchase process. After successfully completing the payment and placing the order, if it contained any product with which a recurring payment is associated, a subscription will be created, which you can manage at '/admin/commerce/subscriptions' or through the 'Commerce->Subscriptions' admin panel.


A more detailed description of the module's operation can be found here.

Creating standalone recurring payments

So far, we have created a subscription as a separate product that the client can add to the cart also with the products that do not necessarily have to be subscriptions. But what if you do not want to create products and variations, e.g. if you want to give users the option of repeated payments?

The Commerce Recurring module also allows you to add recurring payments. This can be done in the same place where the list of subscriptions created on the basis of orders is located, by clicking the "Add subscription" button and selecting the "standalone" option. Then you fill out the form as required. Note that in this situation, it is required to specify the user to whom the subscription will be assigned.


More detailed description can be found here.


Drupal offers a wide range of possibilities to create tailored e-commerce solutions. Learn more about Drupal Commerce from our other blog posts:

If, on the other hand, you need specialist support, check out our Drupal Commerce page.

Dec 02 2020
Dec 02

During a website audit, it is possible to detect whether changes have been made to the Drupal core, modules and contrib themes. How to do that? The most effective way to do this is to use the Hacked! module.


The module was released on 8 October 2009, and the last modification was introduced on 13 February 2020. Hacked! has a version for both Drupal 7 and 8.

Module's popularity

Drupal.org reports that the module is being used by approximately 16,000 pages of which 15,100 are Drupal 7 pages and 900 are Drupal 8 pages. In the case of the Hacked! however, this is not very reliable information, as it is a module that should only be used in development environments for a short time and should be uninstalled after the work is done. So, one could rather say that 16,000 pages have the module installed incorrectly.

Module's creators

The user ivnish is maintaining the Drupal 7 module. Nobody maintains it for Drupal 8 at the moment.

What is the module used for?

The Hacked! module is an indispensable tool in the work of every professional Drupal agency. At Droptica, every new webpage accepted for Drupal support is being scanned with the Hacked! module for changes in modules.

We carry out checks in order to find any manual modifications to the Drupal modules and core. There are several goals for finding such changes:

  1. If possible, the Drupal core and contrib modules should not be changed. Drupal is a very flexible system, and, in most cases, you can achieve the desired results by acting according to good practices. If we find changes introduced by previous teams in the code, we try to transfer them to our modules and implement them in accordance with the Drupal standards.
  2. If the changes cannot be introduced into our own code, we move them to the tracked patches to be able to track them automatically and apply them with every module update.

We follow the above steps to be able to update modules easily and quickly to the latest versions without the risk that we will remove or break any functionality that someone has hidden in a contrib module. At this point, I encourage you to read the article on how to Keep Your Website Safe And Up-To-Date With Drupal Support.

Without the Hacked! Module, we do not have easy insight into changes introduced to a given contrib module, and in the case of an update, tracking down the modifications without using this module will be time-consuming.


In order to install the Hacked! module, go to the project's page at drupal.org or use the Composer we wrote a separate article:

composer require drupal/hacked

After the installation, you can configure the module by going to


The module has one configuration option:


Ignore line endings/include line endings: Depending on the operating system on which the module was modified, line endings are being determined differently. Setting this option to "Ignore line endings" will ensure that all line ending coding differences will be ignored.

In other words: if the developer opens the file in Windows and saves it while "Include line endings" is selected in these settings, then differences in line endings will be listed during the file check.

Generating a change report

After installing the module, go to


or use the drush command:

drush hacked-list-projects 


drush hlp 

The report generation process takes up to several minutes, depending on the number of files to be checked.

Review of changes

The Hacked! module provides a page with the report. We can find it under:


or by going to the "reports" tab in the admin menu, and then using the "hacked" link


In the given example, you can see that the module "Better exposed filters" contains some changes. Let us check them out:


If you have the additional Diff module, you can easily see the exact changes in each file:


Changes can also be observed using drush commands. In order to list the modules containing changes, use the command:

drush hlp


In order to list the names of the files containing changes, type:

drush hacked-details [the module machine name]

or use the alias:

drush hd [the module machine name]



In order to list the modifications in individual files in a given module, use the command:

drush hacked-diffd [the module machine name]

which will return changes between files in the same way that the git diff command does

Changes to the sample file:


Alternative modules

There are several file integrity checking modules, including MD5 Check, File Integrity Check, but they are not widely used. MD5 Check generates a checksum for files and on this basis informs the admin about changes. File Integrity Check, on the other hand, creates a "fingerprint" of the entire page and informs the admin if there are modifications to it.

Extension modules

We recommend installing the Diff module, which allows one to clearly track the changes between the current version of the file and the one downloaded by the Hacked! module.


The Hacked! module solves the problem of searching for modifications in the Drupal core and contrib module files. It provides a functionality which, in combination with the Diff module, allows you to see the differences between the original and modified files clearly.

Nov 27 2020
Nov 27

Drupal is being chosen as a platform for building websites, among other things, due to its flexibility. If you want a system ideally suited to your business model and better than the competition's systems, Drupal will prove to be perfect. One of the areas you can customise in Drupal is the user permissions system. Take a few minutes to learn about the permission management abilities of Drupal.

General information

Drupal allows you to manage access from the admin panel and from the code level. In this post, I will present these two possibilities and the most common examples of their use.

Roles and permissions in the Drupal core

If this is your first time dealing with Drupal and its permission system, you should know that there are three elements used for granting permissions:

  1. User
  2. Role
  3. Permission

When installing Drupal, you create a root administrator account in the system (identifier 1 in the database). It can be compared to the root user in Unix systems. This user has access to all subpages and settings in the system.

You can add more users to the system. These could be, e.g. the editors responsible for creating the content, or the moderators deciding whether to post the added comments.

If you want to assign a permission to a given user, you do it indirectly by assigning a role to them. There is no association between a user and permissions in Drupal. There is a user-role association and a role-permission association.


How to add an editor role and assign the appropriate permissions to it

This is probably the most common issue encountered in Drupal. You need to let users into your system, but you want to limit their rights to the content management only. You do not want to give the rights to change the system configuration or to add new users.

In order to achieve this, follow these steps:

  1. Add a new role on the page "/admin/people/roles/add/".
  2. Assign the selected permissions to the role on the page "/admin/people/permissions/". For the content-related ones, check out the "Node" section. Below you can find more information on the permission list.
  3. Assign the selected user to the new role on the page "/admin/people/".

Then log-in into the account of the selected user and check out whether they have the appropriate permissions. Maybe you need to extend them or take them away. If you are unfamiliar with the Drupal's permission system, such a test with logging-in into the user account is always worth carrying out.

You do not need to know the password to the user account you want to log-in into. You just need to install the module Masquerade. Thanks to it, you can log-in into the account of any user.

Drupal core permissions overview

When entering the page "/admin/people/permissions/" for the first time, one can get a little scared. This is probably the longest configuration page in Drupal.

Let us start with the table header. You will always see the word "PERMISSION" in the first column. In the next cells of the first row, there will be the names of the roles. The more roles you add (you can add them on the page /admin/people/roles/add/), the more of them you will see in this table.

Then, looking at the first column in its entirety, you will see a long list of permissions. The permissions are divided into sections. The sections are the names of modules. The "Node" section mentioned earlier is named so because the permissions in this section are defined in the "node" module (you will find it on your disk in the core/modules/node directory).

Some sections have only one permission, e.g. the "Block" section has the "Administer blocks" permission only. Others have many more of them.

If this is your first time dealing with Drupal permission settings, I suggest that you read the names of all permissions. The names themselves explain what a given permission is for.

Anonymous & Authenticated

There are two system roles in Drupal that cannot be removed:

  1. Anonymous User
  2. Authenticated User

The first of these roles is responsible for all non-logged-in users. For example: if you want to add the ability to view user profiles for all non-logged-in for the "View user information" permission, tick the checkbox in the "Anonymous User" column.

"Authenticated User" is the role assigned to all logged-in users. It is important here to understand the permission inheritance. If you assign a permission to "Authenticated User", then all other roles (except anonymous) will be given this permission immediately.

Example: You have the "Editor" role in the system. You assign the "View user information" permission to the "Authenticated User" role. Everyone with the "Editor" role will also be given the permission because they are also considered to be logged-in users.

Moreover, keep in mind that if you select any permission for the Anonymous role (e.g. "View user information" again), but do not select it for the "Authenticated User", the logged-in users will not be able to access the selected section ("View user information" – they will not have access to user profiles).

Worth remembering

  • In Drupal, you can add an unlimited number of roles.
  • The list of permissions is defined by modules in modulename.permissions.yml files (more on this can be found further in the text). 
  • The "Authenticated" and "Anonymous" roles are separate – if you select something for "Anonymous" only, the logged-in users will not be given this permission.
  • To test permissions, it is good to use the Masquerade module.

Own permissions in the code

Sometimes there is a need to define your own permissions, e.g. to administration pages defined by new modules or to modify access to the pages defined by the Drupal core.

How to define a permission

You just need to add the modulename.permissions.yml file in the new module (or in the existing one, if you already have your own modules created). If you do not know how to create your own modules, I encourage you to visit the website.

The permission file is a file in the YML format. A simple example can be found in the Popup Message module, right here.


Being defined in the file is a unique name for the permission (e.g. "popup message administration"), and then – the names being displayed on the page "/admin/people/permissions/". You can provide a title in the "title" parameter and additionally – a more detailed description in the "description" parameter.

This is enough to define new permissions. After creating the file and clearing the cache, you will see the new permissions on the "/admin/people/permissions/" page.

How to use a permission

Most often, permissions are being used when defining routing. Take a look at the file.

In the "requirements" section, you can add the "permission" parameter. In this way, you can define the users (or rather roles) with what permission can display the page defined in routing.

The second method is to check out the permissions in your code. User object in Drupal has the "hasPermission" method. In this way, you can check out whether a given user has the selected permission.

// Get the current user
$user = \Drupal::currentUser();
// Check for permission
if ($user->hasPermission('display popup message')) {
// Do something.

It is worth to take a look at the hasPermission method here. As you can see, the user ID is being checked there. If the id equals 1, the user gets access without further checking if they have selected roles.

How to check whether the user has a role

Drupal also offers a ready-made method to check whether a given user has a role with a specific name. Provided below is an example of how you can do it in the code.

// Get the current user
$user = \Drupal::currentUser();
// Check for permission
if ($user->hasRole('editor')) {
// Do something.

Additionally, there are also methods related to the Authenticated and Anonymous roles:

  • $user-> isAuthenticated();
  • $user-> isAnonymous();

How to check permissions for operations on an entity

In the application code, you can also check the permissions to operate on selected entities (e.g. Node or User). You can perform certain operations, e.g. depending on whether the user has the right to edit a given entity or to display an entity.

Entities in Drupal have the method access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE). A simple example of use is provided below:

$nid = 545;
$node = \Drupal\node\Entity\Node::load($nid);
$user = \Drupal::currentUser();
if ($node->access('edit', $user)) {
// Do something

Defining content permissions

Drupal allows you to manage access to display and edit at the level of a single entry (node). This topic was thoroughly described in our other blog post. Grzegorz Pietrzak described it in the article Drupal Node grants.

Ready-made modules for Drupal related to permissions

There are already many ready-made modules extending the capabilities of the Drupal core. You should check them out before you start writing your own permission-related modules.

Below is a list of a few selected modules that are worth checking out and testing:

Also, check the page and take a look at other modules. Maybe some of them you will find useful.


Drupal is a very flexible system. Just looking at the possibilities regarding permissions, you can see the multitude of configuration possibilities. If you are building a large website with many editor levels or an internal application (e.g. an intranet system) where the users must have limited permissions, Drupal will do the job very well.

If you need support from Drupal specialists on permissions or other issues, use the services of our Drupal developers.

Nov 13 2020
Nov 13

Theme creation in Drupal is not as easy as it may seem. Therefore, there is space here to make your work easier. Often, however, we take shortcuts for this purpose, but these do not always bring the desired results or contradict Drupal's philosophy and generally accepted best practices.

Probably many of you know that as in any other CMS or framework we work on, in Drupal, we can achieve the same goals by choosing different paths to reach them. In the course of my experience, I have faced common mistakes made by Drupal beginners repeatedly, and I have managed to track many codes created by novice and experienced Drupal developers. I have seen how much different the approaches they use. As part of this article, I would like to introduce 7 tricks I have selected (or just shortcuts) that make it easier to work on creating a theme, which many programmers I have never heard of.

Due to the fact that with each release of the Drupal subversion there are various significant changes, I would like to emphasize the examples discussed here that are compatible with the core 8.9.x version. All presented tricks, although they may be sometimes controversial in use, they are fully consistent with the art and can be used for projects.

1. Use of the #context key in the rendering array

One of the common problems when creating templates is the ability to pass data between them. This usually requires programmers to perform complex operations, e.g. when processing templates. The challenge becomes even more difficult when some hooks have already been cached and data upload was still needed. There may be many ideas for solving the problem, but with the Drupal 8.8 version, the problem is solved by the #context key.

Suppose we have implemented hook_preprocess_node, in which we add some additional element using a dedicated template, but we would like to still have access to the node object in it. This is where the #context key comes in handy.

function my_module_preprocess_node(array &$variables) {
  $node = $variables['node'];

  $variables['my_custom_element'] = [
    '#theme' => 'my_custom_theme',
    '#title' => t('My custom theme title'),
    '#context' => [
      'entity' => $node,

This makes it possible to pass any data from one rendering table to another. You can fit anything in it, e.g. an instance of an object that we will need in further processing:

function my_module_preprocess_my_custom_theme(array &$variables) {
  $node = $variables['#context']['entity'];
  // Do whatever you needed with the node entity in your custom theme...

It's worth mentioning that this variable is also available in hook_theme_suggestion_alter, which can further facilitate making suggestions for additional context-dependent template names.

2. Cache support in twig templates

More and more demanding graphic designs of websites, as well as page optimization (in terms of the amount of HTML code returned), forces us to use some shortcut solutions, e.g. extracting the field value directly in the entity template (node type).

Solutions such as

{{ content.field_my_reference_field.0 }}

displaying only single field instead of the content variable can have disastrous consequences in the form of cache problems. In the rendering arrays, apart from the final HTML code, there are also keys responsible for storing such cache metadata: tag, context and max-age. If you want to be sure that the metadata will be collected correctly by the renderer service, just add one magic line in the template:

{% set rendered = content|render %}

In the example of a node template, it will be the content variable, but it can be any "main" variable of your template. Passing such a main rendering array through the render filters allows you to correctly collect all cache metadata, without having to display the entire content variable. At the same time, the solution does not have any negative impact on the performance of code execution, as long as we use cache mechanisms.

3. Theme suggestion without using hook_theme_suggestion_

Yes, it sounds like something completely crazy. However, this solution is available "out of the box". It is enough to add the suggestion to the values hidden in #theme or theme_hook_original in any rendering array (e.g. in hook_preprocess_HOOK) keeping the template naming convention.

As a result, the variable value set in this way

function my_module_preprocess_paragraph(array &$variables) {
  $paragraph = $variables['paragraph'];

  if ($paragraph->bundle() === 'my_awesome_bundle') {
    $variables['theme_hook_original'] = 'paragraph__my_custom_theme_suggestion';

records a suggestion for a given base template (paragraph), allowing you to create a template file named: paragraph-my-custom-theme-suggestion.html.twig Nevertheless, I would limit this solution to exceptional cases. For general use, I would recommend a hook dedicated for this purpose.

4. Safe filter replacement | raw

This filter is generally considered to be potentially dangerous (increases the possibility of successful XSS attacks) and is used in single cases. But it should be avoided as much as possible. I suggest looking for a better way, especially since one of them is extremely easy to use, as you will see in an example.

Let's assume that we have a field that is to finally display the image, but for some reason we would like to omit all the HTML code generated along the way.

The easiest way to do this is:

{{ content.field_my_image_field|render|striptags('')|trim }}

Experienced Drupal developers know that such a solution, instead of displaying an image on the page, will display the whole as plain text encoded into HTML entities. Yes, you can add a raw filter, but you can do it differently using Drupal's Render API with the #markup key:

{{ {'#markup': content.field_my_image_field|render|striptags('')|trim} }}

The method is perhaps a bit less readable than with the filter, but it is safe. HTML code will still be filtered here and only allowed safe tags will be passed through.

5. Referencing a template file from a different theme/module

If you haven't used Twig mechanisms such as include, embed or extend in your template files, I suggest to take the DRY rule into account in every aspect of programming (or web development in general). Themes are the places that suffer most from duplicate code, both in template files and in style sheets.

Many times I have encountered the entire template file was copied, e.g. from an inherited theme or a module, only to add some surrounding HTML code or modify a single template block. The same effect can be achieved by referring to a parent file using the aliases @module_name @theme_name. Suppose we have a template file (card) in our sample module named custom_card

  {% block card_header %}
  {% endblock %}
  {% block card_content %}

{{ content }}

{% endblock %} {% block card__footer %} {% endblock %}

And now in our theme, we would need to add some additional elements in the header block, e.g. an icon. The most common thing is to copy the entire template code, but this can be done more simply and without repeating the code:

{% extends '@custom_card/card.html.twig' %}

{% block header %}
{% endblock %}

6. View reloading using InvokeCommand

As you know, the Views module allows to create views that use AJAX technology. This is done to dynamically switch between the different pages of the view, but also to display the results of the response to value changes from the provided form. But what to do when the content of the view needs to be refreshed due to performing some action outside it, e.g. after sending a request to the controller from another block? Or to submit a form on the same page? Well, there are two very convenient functionalities available in the Drupal core.

The first one is the default RefreshView event registered on the view, which causes the view to be refreshed using AJAX (I recommend that you enter it in the browser console on your example view and observe the effect).

The second mechanism is InvokeCommand, which allows in the AJAX response to return the jQuery method call, along with the given parameters on the DOM element. Combined, this gives you this example code:

class MyCustomController extends ControllerBase {

   * Perform the update and refresh the view.
   * @return \Drupal\Core\Ajax\AjaxResponse
   *   Ajax response.
  public function doUpdateAndRefresh(): AjaxResponse {
    // Perform some sort of logic needed for your controller.

    // Refresh the view.
    $response = new AjaxResponse();
    $response->addCommand(new InvokeCommand('#my-view-block', 'trigger', ['RefreshView']));

    return $response;


In my example, there were forms for user approval inside the generated view. In response to the entry of such a form, I needed to display an updated list. As you can see, basically one extra line did all the magic without any extra effort.

7. Use of Drupal.debounce

For the very end I want to describe something which is not so much a trick as good practice. The Underscore.js library is bundled with Drupal core, but many developers do not use it at all. It includes a number of functionalities. One of the most common cases where the capabilities of this library are not used is the so-called deboucing, i.e. preventing multiple code execution in response to a given event - most often it is a change in the width of the browser window.

I have come across code many times that resembled:

function onResize(callback) {
  var timer;
  return function (event) {
    if (timer) {
    timer = setTimeout(callback,100, event);

$(window).resize(onResize(function(e) {
  // Resize implementation goes here.

Of course, this is an exemplary and the simplest implementation, and such code will execute correctly. The question is: why reinvent the wheel? Answer: to improve Drupal compatibility in the core of Drupal, and also to increase the convenience of work for developers - there is a debouncer port from the underscore library.

Just add a dependency to your library

- core/drupal.debounce

and add the following implementation in the JS code:

$(window).resize(Drupal.debounce(function () {
  // Resize implementation goes here.
}, 100));

Isn't it easier? And most importantly, we use something that has already been well written once.


Although I have come across a lot of interesting approaches to working with themes in our Drupal agency, it must be emphasized that many things come with experience. Especially novice developers should follow Drupal's philosophy from the very beginning. They should understand why they are doing something in a certain way. This allows us to see Drupal's capabilities more easily and learn to use them to increase the comfort and efficiency of work, without losing the cleanliness of the code.

Oct 28 2020
Oct 28

A Drupal multisite is an installation which allows us to use one codebase to serve multiple websites. In this post, I will explain in detail how Drupal multisite works, what approaches can be taken to set up a multisite installation. I will also explain some of the settings that may be important for a multisite which are not applicable when we build just one website on Drupal.

The basics of a default Drupal multisite

A Drupal website comprises a few major things:

  1. Drupal core
  2. Contrib and custom modules
  3. Theme
  4. Database
  5. Configuration

When a request from the browser is handled by Drupal, one of the first things Drupal does is bootstrapping the database and loading configuration. From the database and configuration the system knows:

  • which from the available modules and themes are enabled,
  • how everything is set up:
    • where are public and private files folders,
    • which blocks are where,
    • what content is available,
    • what is on the front page,
    • which menus are in which regions, what links are in which menus, 
    • pretty much everything else about how the website is configured. 

To connect to the database, Drupal reads the connection information which is held in the settings.php file (which typically sits in /sites/default folder).

Notice the default folder. It is called default because it is a fallback folder when no other folders are found. In a single Drupal install, typically no other folders are set up and most websites are run from the default folder.

In a multisite installation, however, we set up separate folders for separate websites.

For example:

  • /sites/example-one.com
  • /sites/example-two.com

If we create such folders, a new request will examine the base domain (base URL as Drupal calls it) and will try to match it to the correct folder. The order is as follows:

When a request with a base URL of www.example-one.com comes in, Drupal checks if there is:

  1. A folder named /sites/www.example-one.com and looks for settings.php there.
  2. If there is not, Drupal will check a higher-order domain folder - /sites/example-one.com in this case. 
  3. If it does not find settings.php there, it will move to the /sites/default.

We achieved a multisite - many websites on one codebase

If we have 2 folders for 2 different domains, we can have 2 separate settings.php files which connect Drupal to two separate databases, which load separate configurations and use various enabled modules and themes.

In essence, we end up with 2 different websites, which have their own databases, content, files and configurations, even though they sit on one Drupal code.

If we add additional folders, we get additional websites without the need to duplicate code.

Drupal can run hundreds of websites from one installation like this.

Sites.php file helps to map domains for folders

To help with the mappings of base URLs to folders, Drupal offers a sites.php file which can be used to assign base URLs to correct folders.

In the /sites/ folder we are offered a file which is called example.sites.php. Change its name to sites.php and Drupal will use it. The configuration of mappings is quite simple:

$sites['an-old-domain-to-map.coom'] = 'example-one.com;

This file allows us to map several domains to one website if we need to and helps a lot with development because development environments typically have different URLs than production ones.

$sites['localhost.example'] = 'example.com';

Some dev teams use this feature also to keep the sites folder clearer when there are hundreds of websites with various domains sometimes in foreign languages. The dev team can have short clear folder names.

'] = 'brand-x-fr;

This is also sometimes useful if the domain for one of the websites changes.

Which website can use which modules

Typically, we are used to a situation where

  • all modules are placed in the modules directory (or sites/all/modules in Drupal 7 and previous versions),
  • all themes are placed in the themes directory (or sites/all/themes in Drupal 7 and previous versions).

If we have one website on the system, there is no need for any other configuration. We add only the modules we need.

In a multisite installation, however, there might be a need to specify which websites can use which modules or themes. In a large system with hundreds of websites and administrators, such restrictions might be crucial to only allow such functionalities on each website which work well together.

We can control this in 2 ways:

1. Via installation profiles

Each website on Drupal is built on an installation profile. Typically this is the standard or minimal profile which is shipped by Drupal out of the box. You chose between these when you install Drupal and you can see them in the /core/profiles folder. None of these 2 profiles has any modules or themes but a profile can provide these.

Drupal for example ships with a demo_umami profile which is a demo profile and includes both: a demo_umami_content module and an umami theme. If you install a standard installation, you will not have access to the umami theme from the admin panel for example.

If you have to control which websites have access to which themes or modules you place these in your custom installation profiles. Only the websites installed on a particular installation profile will be able to access and use what it provides.

What is cool is that profiles allow for inheritance. You can, for example, create one profile with drupal commerce modules and then 2 additional child profiles which will then be able to access the Drupal commerce modules.

While performing Drupal services for our clients we have implemented various scenarios with different levels of granularity. You could even create a child profile for each website to be able to have very granular control. This might however be a bit of an overkill.

2. Per website modules via the website folder

Modules and themes can be also added to the website folder. In our example, we could put them into:

  • sites/example-one.com/modules
  • sites/example-one.com/themes

Modules and themes placed in these directories will only be available to website example-one.com.

As a rule of thumb, you should probably avoid having too many modules here since it probably goes against the concept of a multisite to have completely different code for each website, but sometimes there is a need to add a few per-website tweaks or create for each a subtheme for a website which overrides a few things in a shared base theme.

Updating code once, running update 100 times

One of the great things about a multisite is reduced maintenance. If you have 100 websites on one system and a new version of Drupal comes out, you only have to update the code once instead of 100 times.

That said, remember that settings and databases are separate for all 100 websites. You do have to run the update.php script for each one separately!


Above I explained in detail how Drupal multisite works under the hood. In essence, it is a very simple and yet a powerful feature of Drupal which allows companies to reduce maintenance and technical debt and keep maintainers sane if they have to maintain many websites.

Oct 23 2020
Oct 23

Nowadays we have social media everywhere, so having the ability to share content on your website is essential.

By default Drupal doesn’t provide social media sharing buttons out of the box. However, when delivering Drupal services, we use modules that can help with this. The most popular solution is the AddToAny module.

AddToAny module provides a huge number of share buttons including the universal (‘+’), Facebook, Twitter, Pinterest, Reddit and many more.

And popular AddToAny features list is also impressive:

  • Floating share bars for mobile, desktop, and various site layouts; 
  • Image share buttons to share your images; 
  • Share counts and share count recovery;
  • Google Analytics integration; 
  • Vector sharing icons made for mobile, Retina and high-PPI displays; 
  • Universal sharing button and smart menu; 
  • Visitor personalization; 
  • International support (i18n/localization); 
  • Accessibility and graceful degradation; 
  • Cross-browser and backward compatibility; 
  • Optimized performance and efficient loading via world-class CDNs; 
  • Complete control for publishers & developers of all sizes


The first version of the module was released on 15 April 2008, the latest update - 15 may 2020.

The module can be installed on:

  • Drupal 7 (7.x-4.16 stable release version); 
  • Drupal 8 (8.x-1.14 stable release version);
  • Since 8.x-1.13+ it supports Drupal 9 as well.

All stable releases for this project are covered by the security advisory policy.

Module popularity

According to the statistical data from the module's page, it is currently used by about 47.000 websites.

Module creators

The module is created and maintained by the only person - micropat (see his profile).

What is the module used for?

It is a highly customizable module, allowing to share content probably to any social media. It has a very friendly and excellent documentation with many examples.


To install AddToAny go to the webpage or do it via composer:

composer require drupal/addtoany

Configure placement

By default, share buttons are disabled and placed in Manage display section of each content type, e.g. Structure > Content types > Blog post > Manage display. Be sure it is enabled before we continue.

add2any placement

Configure AddToAny

To configure AddToAny options, go to Administration > Configuration > Web services > AddToAny.

addtoany config

Let's go through each section briefly.

Buttons section

buttons config

AddToAny uses SVG sharing icons that can be scaled to any size, the default value is 32x32 pixels. You can customize the share buttons by editing the "Service Buttons HTML Code" box. More details can be found in the official documentation, where you will find the additional feature examples, such as:

  • Share event handling & modifying; 
  • Templates & endpoint parameters; 
  • Link tracking & URL shorteners; 
  • Custom color buttons; 
  • Image share buttons; 
  • Share counters; 
  • Share count recovery; 
  • etc. 

Here are a few examples.

Like buttons:

like buttons

Share counts buttons:

counters buttons

Under the universal button section you can also customize the + button or even remove it:

no plus button

Additional Options section

Here you can add some custom JS or CSS code for AddToAny with no need to do it programmatically.

additional options section

As an option, you can for example set a custom color to perfectly match any design's color scheme. Just add the following JS code to your "Additional JavaScript" box on the Configuration page.

 a2a_config.icon_color = "#0166ff"; 

 buttons js adjusment

Entities section

In this section you can toggle the content entities where AddToAny will be available to interact with.

entities config section

Once the AddToAny Share Buttons module is installed and enabled, a few sharing buttons will appear on your page. Let’s check out how they look.

page with buttons

By default we have a “+” icon (called the “Universal Button”), next Facebook share is there, as well as Twitter, and email. Clicking the “Universal Button” you will see all available share buttons for other services.

expanded services

And here is an example of Twitter sharing popup. When a visitor clicks one of the buttons, a pre-populated post pops up.

twitter popup

Let’s dive into the documentation and see if we can adjust the template.

Voila, you can change the default message, by adding the following JavaScript code:

var a2a_config = a2a_config || {};
a2a_config.templates = a2a_config.templates || {};
a2a_config.templates.twitter = {
    text: "Reading: ${title} ${link} by me",
    hashtags: "sharing,social"

Hook & Templates

If you think that standard settings is not enough, you can try extending the addtoany-standard.html.twig template.

The default theme implementation to standard AddToAny buttons includes the following variables:

  • addtoany_html: HTML for AddToAny buttons;
  • button_image: URL for universal button;
  • button_setting: Setting of button;
  • button_size: Size of buttons;
  • universal_button_placement: Value of 'before' or 'after' to place button;
  • link_url: Value of URL to share;
  • link_title: Value of page title to share.

There is also one hook, allowing you to programmatically alter the entity types that the AddToAny pseudo-field is available for:

 * @param array $types
 *   The entity types.
function hook_addtoany_entity_types_alter(&$types) {
  // Add the "taxonomy_term" entity type.
  $types[] = 'taxonomy_term';

Alternative solutions

There are a few other options that you might want to investigate. Here is the list:

Has less settings options and services. According to the description this module delivers the most clean solution without making a lot of external calls, having tracker scripts, or even connecting to ad servers.


Now you have all the necessary information on how to add social links to your Drupal site on the example of the AddToAny module. However, if you want to know more about how to most effectively use this module for your website, please contact our Drupal consultants. Once you have installed this module, you will get a very customizable platform with many fine features, which makes your content easy to share.

Oct 02 2020
Oct 02

The Views Bulk Operations module is used when performing bulk operations on results to tables or other items created with Views. In this example, I will show you how to add your own action that will change the state (Workflows) of selected entries.


The action is performed on all selected entries and automatically performed in Batch queues so as not to overload the system and not to "crash" the page when the process takes too long. If you know what you are doing and you have reasons for it, you can turn off the queuing option in the field configuration.

VBO installation and configuration

The Views Bulk Operations module can be installed by downloading and unpacking the package in the modules/contrib directory or by using the composer command, which will download the latest stable version of the module.

composer require drupal/views_bulk_operations

After installation, the module does not need to be configured in any way, you just add the appropriate field to the page (or block) created by the Views module.

  • Add a new Content view that creates the page.
  • Set the display format to Table. It is not necessary, the checkboxes on the table simply look more natural
  • Add the title field
  • Add the Views bulk operations field


Action configuration for a VBO field

In the field configuration, you can mark which mass actions can be performed on the results. There are over a dozen predefined actions, such as:

  • deleting entries
  • publishing
  • sticking


The above list is compatible when the view displays Content. If you add the view that displays Users, you will notice that the list has different actions.

Adding own action to VBO

The goal is to add your own actions on entries (Content) that will change the state (Workflows) of the selected entries.

Entry states are not available immediately after Drupal installation. In order to do this, you need to enable two additional modules that are directly in Drupal, you do not need to additionally download anything.

Go to the page with modules - admin/modules

Enable the modules: Workflows and Content moderation


Workflows configuration

For the purposes of this post, I will use automatically-defined states for the Editorial type, which is available immediately after enabling the Content moderation module.

All you need to do is enable a given type of state transition for the selected content types.

  • On the page admin/config/workflow/workflows edit the Editorial type
  • Set the Article content type


This operation will add a new field to every add/edit article form.


To the view where the VBO field is, add

  • a field displaying the state of a given entry - Content: Moderation state
  • a filter that will limit the display of entries of the Article type

If added is a filter restricting entries to published only Content: Published (= Yes) then remove it. It will block the display of entries that have a state of e.g. Draftor Archived, which are not being published by definition.

Own action code

Create your own module end enable it. In my case, the module's name is d_workflows

In the module's directory create a directory structuresrc/Plugin/Action

Create in it a new class file for the action to change the state of the entry into Published.

Filename: PublishNodeAction.php

 * Content moderation publish node.
 * @Action(
 *   id = "d_workflows_publish_node_action",
 *   label = @Translation("Publish node (moderation_state)"),
 *   type = "node",
 *   confirm = TRUE
 * )

class PublishNodeAction extends ViewsBulkOperationsActionBase {

Class annotation is important here.

You set in it an id for the action – this can be any unique value. It is worth to include in its name the name of the module and what the given action is doing.

Label is the value that will appear in the VBO field configuration

Type is the type of entity, for which the new action will be available. In this case, it is node, but it can be, for example, user, taxonomy_term, or any other.

This class inherits from ViewsBulkOperationsActionBase

It requires declaring two methods:

  • execute() - what is to be executed for each record
  • access() - who can perform the action

Example of a code for the execute() method

 * {@inheritdoc}
public function execute(ContentEntityInterface $entity = NULL) {
  if (!$state = $entity->get('moderation_state')->getString()) {
    return $this->t(':title  - can\'t change state',
        ':title' => $entity->getTitle(),

  switch ($state) {
    case 'archived':
    case 'draft':
      $entity->set('moderation_state', 'published');

  return $this->t(':title state changed to :state',
      ':title' => $entity->getTitle(),
      ':state' => $entity->get('moderation_state')->getString(),

The first condition checks whether the given entity has the state setting option enabled.

In this case it is only Article. When the action is initiated on entries with no states enabled (empty $entity->get('moderation_state')->getString()) it will be interrupted and an information about it will be displayed.

The condition can be easily extended by e.g. checking the content type for the entity


Further down the code, the current status of the entry is being checked and if the condition is met, the code changes its status into Published.

$entity->set('moderation_state', 'published');

Example of a code for the access() method

   * {@inheritdoc}
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    if ($object instanceof Node) {
      $can_update = $object->access('update', $account, TRUE);
      $can_edit = $object->access('edit', $account, TRUE);

      return $can_edit->andIf($can_update)->isAllowed();

    return FALSE;

In this simple condition, it is being checked whether you are operating on Node type objects and whether the user performing the action has the authorisation to edit and update it. Otherwise, the code will return a FALSE, and the action will not be executed.

The whole PublishNodeAction.php file looks like this:

get('moderation_state')->getString()) {
      return $this->t(':title  - can\'t change state',
          ':title' => $entity->getTitle(),

    switch ($state) {
      case 'archived':
      case 'draft':
        $entity->set('moderation_state', 'published');

    return $this->t(':title state changed to :state',
        ':title' => $entity->getTitle(),
        ':state' => $entity->get('moderation_state')->getString(),

   * {@inheritdoc}
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    if ($object instanceof Node) {
      $can_update = $object->access('update', $account, TRUE);
      $can_edit = $object->access('edit', $account, TRUE);

      return $can_edit->andIf($can_update)->isAllowed();

    return FALSE;

A new action will be available in the VBO field edit



Experienced Drupal developers as well as Drupal consultants ensure that adding new actions to Views Bulk Operations is simple and comes down to creating an additional class with two methods. Based on this simple example, you can build more complex mass actions on entities of various types.

Oct 01 2020
Oct 01

Creating groups of users with access to selected content is one of the frequent requirements set out in specifications for web portals. The Group module allows saving hundreds of programming hours by providing ready-made and easily extensible mechanisms. Check how many useful functions you can find in this module.

Group was created as an alternative to Organic Groups (OG), in which relationship mechanisms are based on fields and content. Created in the group module, on the other hand, were full-fledged entities with their own fields that can be extended and exported. Every group can have its own users or uniquely configured permissions.


The origins of the module date back to the Drupal 7 version, for which the first dev version was released in 2010. The Drupal 8 version of the module was first released in March 2016 and is still being developed today. The latest stable version 1.2. was released on 4 August 2020.

Module's popularity

The Group module is quite popular and is currently used by over 9,000 websites. The vast majority, about 8,200, are projects based on Drupal 8.

Module's creators

The main keeper of the module is Kristiaan Van den Eynde (kristiaanvandeneynde), responsible for almost 900 commits to the module. The module is financially supported by Factorial GmbH and has been supported by other companies and organisations in the past. Of course, the development of the module and its sub-modules is also supported by a large crowd of Drupal developers.

So far, 56 developers have contributed to the development of the module; the full list can be found here: https://www.drupal.org/node/711148/committers

What is the module used for?

The Group module solves a problem that cannot be solved in Drupal with the help of built-in mechanisms. It allows you to divide users into groups within which you can both manage user rights and create content dedicated only to the group members.

It is an extremely complex project from the programming point of view. It has several classes and functions that provide key functionalities like permission support, cache, or integration with Drupal's core modules. There is a gnode sub-module in the module's repository that allows you to create relationships between content and groups. The Group module can also be extended with the functionality of creating subgroups, and this is possible with the use of Subgroup or Subgroup (Graph) modules.

Examples of using it:

  • classroom management at schools, where teachers function as administrators, students are members of a given group, and they all have access to common materials,
  • access to paid content by limiting the accessibility of materials for group members (an example can be found in our article Drupal Commerce - Sell electronic products)
  • portals for organisations/communities with a hierarchical structure (several co-dependent units, but with different members and administrators)
  • organisation and management of conferences (registration for lectures, access to materials, discussions). Group is therefore a great tool when you need to create closed user groups with access to specific content.

The Group is therefore a great tool that we use as part of Drupal services to create closed groups of users with access to specific content.


You can download the module at https://www.drupal.org/project/group

After installation, a new group will appear in the Groups (/admin/group) menu between the Configuration and Users tabs in the main system menu.

Group provides a new type of entity, so in the submenu, you will find links to pages such as group types or list. It also has a configuration page, where it is possible to set an administration skin for group-editing, group users pages, etc.

The Group module does not require any specific configuration to be able to use it.

Module's use

In order to create groups, you must first define at least one group type. To do this, go to "/admin/group/types" and create a new group type. This process is similar to creating a new content type or a vocabulary, but also has additional configuration fields related to the permissions of users in given groups.

create groupe type

After creating the group type, you can configure the group fields, as well as the associated form and group display views.


In order to define the rights, you also have the option of going to the Permissions tab, under which you can define basic permissions broken down into:

  • anonymous users,
  • group members,
  • users not being group members 
  • group members with a defined role in the group

Available is also an advanced configuration of the permissions of a user from outside the group with the use of system roles.


It is possible to define roles for a given group type (similarly to the roles defined in the Drupal's core). It is possible to do it in the Roles tab:


One of the most important tabs is Content, where you can install available extensions for a group, and these include content types, group membership or subgroups (after installing the previously mentioned modules).

content 0

After going through all the forms, creating new groups of as given type becomes very simple. You just go to the group list page (/admin/group) and add the groups you need.


As you can see, there are quite a lot of configuration options, especially regarding module permissions. However, they are necessary for its proper operation and it is easy to appreciate their advantages during the use of the module. You can find a very interesting application of the Group module in the Open Social distribution.

Hooks and integrations

The module has the ability to modify links with entity operations embedded in a block on the group's website using the hook_group_operations_alter hook, which in its arguments accepts a table of links and a group object.

Group provides integration with the following modules:

  • Views, offering plug-ins such as: access, argument, default argument, relationship.
  • Tokens - 21 tokens for group and its contents.


The Group module is very mature and programmatically complex. It adds a mechanism for creating groups and their related content that you cannot find in a clean CMS Drupal installation. It was written with due care for the high quality of the code, while at the same time ensuring its easy extension with new functionalities. If this module fits the needs of your project, our Drupal consultants recommend to use it without hesitation.

Apr 15 2020
Apr 15

Security is very important for every website. At Droptica, we take care of our clients' websites so that they are always up to date. Let us talk about why Drupal core and module updates are so important, and how our Drupal support team helps to achieve full website security.

Why is it so important to update the core and the modules?

A Drupal-based website is made up of the Drupal core and the community-created modules. As for any modern system, patches improving its security are being regularly released for Drupal. 

A special cell has been created in the Drupal community to deal with the security of Drupal and its modules. If it turns out that a module is vulnerable to hacking, the security team helps patch the holes and organises the release of a new version, so that all websites using the module can update it quickly.

Information about new versions is available at drupal.org. You can also subscribe to the mailing list where you receive information about the publication of security patches for the modules being maintained at Drupal.org

It is a good idea to update the website regularly?

Of course, not all updates are critical and not all are security patches. Drupal and the modules grow and improve. Improved versions are being released regularly. It is a good idea to implement these updates on your website. Thanks to them you obtain new improved functionalities, but you are also better prepared for a possible security patch.

Security patches are always released for the latest module version. If you use the old version on our website, you will have to upgrade the module by going through many updates. It often works just fine, but such "big" updates do not always go easily and sometimes require more experience and effort. It is good to update the modules regularly so as not to come across possible surprises and difficulties in the future.

Security updates are the most important of all and must be implemented immediately. What is more, if the update's priority is critical, some of the key functionalities on the website may stop working until the version is upgraded. Some updates are not so important; however, if you do not introduce the suggested changes gradually and regularly, there is a high risk of being exposed to hacker attacks and the occurrence of various problems when upgrading the version after a long break. The consequence of this may be a temporary suspension of the website's operation, which is directly related to financial losses.

We would recommend updating the website as soon as a security patch comes out – and if there are none, you should do it once a month to keep up to date with the changes in all modules.

What are the ways to update modules?

There are several update methods.  

Composer – The first is to use Composer by utilising the appropriate commands. This method is usually preferred. Composer is a package manager with which you can download modules, skins and external libraries. If your website is built based on Composer, this is also the method recommended for you. Read more about tricks to work efficiently with the Composer in Drupal.

Drush – a set of scripts allowing for managing Drupal from the command line. One of them is responsible for updates.
The third, easiest but most tedious method is to manually download and send files to the repository, which is less effective, but sometimes – necessary.

Automatic updates

Ultimately, the Drupal community eagerly awaits the fruits of the "Automatic Updates" initiative, which is to allow automatic updates. Currently, the “Automatic Updates” module does not yet belong to the Drupal's core, but it exists in its initial form https://drupal.org/project/automatic_updates. It is a candidate for a very soon release as a stable version.

How long does implementing changes to modules take?

At Droptica, we implement updates on client's websites within one day, and it usually takes up to several hours to complete the update, depending on the complexity. The time needed for implementation is crucial for websites with high traffic at specific times of the day. We always agree on the implementation time with the client and make sure that the website will work, and the implementation will remain painless and safe.

What can a dedicated Droptica team offer you?

You do not have to hire a full-time developer when you work with us. Our team is constantly watching the changes in Drupal and immediately introduces them, if necessary.

We provide Drupal support for many clients, and we create our own solutions for unsupported modules in relation to business requirements.

How does the process of updating modules by the Drupal Support team look like?

When security patches are released, we check whether the module for which the update was released is enabled on your website. If that is the case, we then ask you for permission to perform and implement the update, also asking for the preferred day and time of implementation.

After receiving permission to carry on, we begin the development and the introduction of changes to the code. Our process involves special steps, such as Code Review (a code check carried out by another developer) and pre-implementation tests confirming that making changes to the website will not cause any problems. We always check the code twice before it "lands" in the production. If you want, we can provide you with a new version of the website in an automated test environment similar to the production environment, so that you can see how the website works after introducing the changes.

When everything is buttoned-up, we are preparing for the implementation, in accordance with the preferred time. Sometimes it happens that the client sets rules in advance for every update – for example, to implement changes always between 7:00 a.m. and 10:00 a.m.

What else can we give you?

In addition to module updates, we also offer other services. We would be happy to expand your application with new functionalities and fix bugs that bother you – the critical ones and those less important. We also often help in upgrading the PHP version and provide consultation on security audits.

Thanks our Drupal support service, you can easily keep the website up to date and not worry about security.

Are you ready to ensure the security of your website?


Apr 03 2020
Apr 03

In a traditional Drupal website, Drupal is the end to end solution for serving users with pages. It is used to create, store and display content to the end-user. In a headless approach adding and storing are still done on Drupal but displaying is not.


Headless Drupal is an approach to building Drupal websites, in which Drupal serves as the backend content repository. The frontend is built in different technologies and communicates with Drupal via an API. 

headless Drupal

In the graph, we can see that Drupal serves as the backend system. The frontend, which the client sees, is separate from Drupal. That is where the headless name comes from - Drupal does not have the top layer anymore (the head ;), but only exposes the APIs which the frontend consumes and uses as content sources.

The frontend can be built in various frameworks and programming languages. Mostly, however, this will be one of the below:

  • Javascript - vast majority of cases - frontends are mostly built on frameworks like React, Angular or Vue, which allow for quick creation of dynamic and interactive interfaces. If there is a requirement (eg for SEO purposes) to pre-render the pages on the server, Nextjs or Gatsby can help.
  • PHP - sometimes the frontend is built on a fast PHP framework like Symfony or Laravel. This would be done mostly when pre-rendering on the server is required. An additional upside is that since Drupal is built on PHP and uses Symfony, often the same team is capable of handling the frontend.
  • Any other - a website in any other technology which can talk to an API can consume content from Drupal. 

Why chose headless Drupal

There are many reasons why companies might choose to use a headless approach to Drupal. Below I will list the most common ones.

More consumers of content

These days brands communicate with their customers not only through their websites but via multiple channels. CMS, therefore, is not used only to send content to web browsers. It pushes content to various other places. You can read more about the changing marketing landscape in a post about Digital Experience Platforms.

Drupal is fantastically positioned to be the source of content for various consumers. Apart from serving content for a frontend website, decoupled Drupal can serve content via an API to be consumed by various other mediums, in which the brand wants to be present:

  • mobile applications
  • IoT
  • kiosk displays
  • etc.

Microsite manager

Sometimes a company needs to create multiple websites which are separate (eg. one for each brand, event, promotion, country), but which will share a lot of content. In such a case, it might be easier to create one content engine (Drupal) which will deliver content to all the microsites. The microsites can be quickly created and closed whenever a need arises and the content can be contained in one content hub.

Need for an elegant UI

Drupal is fantastic for content creation, data storage etc, but it is written in PHP which is a server-side rendering engine. It the particular website or app or website requires a very elaborate UI or simply is interactive it probably has to be built in javascript.

Javascript allows us to create fantastic interactions which are easy to use for visitors and are fast. Libraries like Angular, React or Vue help developers quickly create complicated frontend applications. Progressive Web Applications - a standard published by Google is also gaining momentum and it requires an application to be built in javascript.

If you want to build an interactive web application, marrying drupal with a frontend Javascript framework is a really great option. For a tutorial, you can check out our article about combining drupal and react.

Diversification of teams

Drupal experts are very hard to come by. Some companies, to move quicker, decide to build the backend in Drupal and hand frontend off to a team specialising in a different technology, in which talent is more available or which is simpler to learn.

Another benefit of inviting various teams to work on one project is sharing best practices from various sources. This may results in much better end results than relying on one team to build the backend and frontend.

Reducing technological dependency on one platform

The bigger the system one builds on Drupal, the greater the reliance on it. Abstracting Drupal from serving the frontend, allows companies to be more dynamic in changing the frontend technologies, without having to rebuild or re-architect huge Drupal backends.

Many websites, which have to maintain a fresh, modern look undergo a re-design every few years. If the frontend is separated from the backend it is much easier to rebuild. In such cases, the overall cost of the website might turn out to be lower than if the Drupal website was being rebuilt.

Drupal is great for headless

Drupal is very often chosen when a headless CMS is required. The reason for this is because Drupal out of the box has most of the required functionality. It is one of the most mature CMSes and has fantastic APIs.

Drupal community is working very heavily to allow Drupal to be a great API-driven CMS. In 2016 an “Api First”  initiative was launched. Its aim was to coordinate the development effort to allow Drupal to be a fully headless CMS.

As of writing this, enormous progress has been made in allowing Drupal to serve and receive content via APIs. 

RESTful module

Since Drupal 8.2 there is a RESTful module available in Drupal core which out of the box allows for easy interaction with all standard entities available in Drupal (nodes, users, taxonomies, comments). Accompanied by REST UI module it allows for very fine-grained control of what can be accessed via the REST API and how.

Initially, this module was the standard for building headless Drupal installations. It comes however with a few pain points, what sometimes makes it quite difficult to work with.

  1. Returned data structures are by default derived from drupal arrays, which converted into JSON are not very user-friendly and difficult for frontend developers to navigate.
  2. Getting and liftering lists of entities it a bit troublesome. For each type of list and filter, a view in Drupal with particular fields and exposed filters have to be created. Frontend developers cannot easily ask for custom lists

Despite the downsides, RESTful was a fantastic step in the right direction.

JSON:API module

JSON:API module was shipped with Drupal 8.8. It has massively improved the REST experience with Drupal, making it an incredibly versatile system far superior to practically any CMS on the market.

JSON:API module exposes all entities in Drupal allowing for easy interactions, but it does so in a very elegant fashion:

  1. It is compliant with the JSON:API standard (https://jsonapi.org/) making it easy for anyone wanting to integrate with a Drupal website easy to understand the data structures without the need for a lot of custom documentation
  2. It allows to query for lists and filter by entity properties  and fields also following the JSON:API standard

The core JSON:API functionality is further extended by JSON:API Extras module, which allows for additional configurability of the endpoints.

The above features effectively turn Drupal into a super robust backend for frontend applications, where all data structures can be created using the Drupal UI, whilst the REST endpoints are automatically working out of the box without a need for any programming work.

An in-depth comparison of the two modules can be found here: https://www.drupal.org/docs/8/modules/jsonapi/jsonapi-vs-cores-rest-module

REST in Drupal is baked deep into the system

What is worth mentioning is that in both of the above, modules the REST APIs are not added to Drupal as an afterthought. They are deeply baked into Drupal core. Drupal access control, preprocessing of values, hooks, events etc. All these are automatically taken into account when an access point is queried just as it were when a Drupal node was requested in a more traditional fashion by accessing a URL via the browser. 

This gives Drupal a massive edge over other CMSes. Using REST, you can still extend and alter default behaviour in any way you want!

Headless vs progressively decoupled

In this article, we are discussing headless Drupal, but it is also worth mentioning that it is not the only way to add interactivity to a Drupal website. Another option is to create a progressively (or partly decoupled) Drupal architecture.

Progressive decoupling is an approach closer to a typical Drupal setup, where the initial request to the server is managed by Drupal and the page send back is assembled by Drupal. On the page, however, we embed interactive elements build in javascript, which then fetches data it needs by calling a REST API also provided by Drupal. 

This approach might make sense in the following scenarios:

  • Most of the website is not interactive but there are a few highly interactive elements which require Javascript.
  • The website uses external data sources which should be presented to the user but do not come from Drupal and are not well suited for Drupal (eg. time changing stock quotes) which can be pulled directly from the source by a JS app embedded in Drupal

If you are not sure which solution to choose, there is a great post by Dries Buytaert on how to decouple Drupal in 2019.

Important considerations

Development is more complicated and more expensive

A Headless infrastructure is more complex than a traditional Drupal website. This can cause additional difficulties and can increase costs. Deciding on a headless, you should consider whether the benefits outweigh the costs. 

Managing multiple teams

In a headless Drupal, there are 2 separate components (frontend and backend) and these have to be developed (at least to some extent) in coordination. Quite often, there will be separate developers or teams (backend and frontend) working on the website. Sometimes these are 2 different companies. This requires coordination and much more communication because data models have to be agreed, endpoints created and tested. It is true that in Drupal many of these might be available out of the box, but most probably there will be requirements for some custom ones.

Higher overall development costs

Overall development time will probably be higher since we now build 2 systems, and therefore development cost will also be higher than that of a comparable standard Drupal website, especially taking into account the coordination effort.

Higher subsequent maintenance costs

Maintenance of a decoupled system is more difficult. Tests are more important when you rely on REST APIs because changes to one system might make it not compatible with the other.

Deployments might have to be more orchestrated where changes to multiple both systems are deployed all at once. Alternatively, multiple versions of an API might be maintained, but that also adds to the cost. All of this might increase maintenance costs.

Also, security releases will be required more often since there will be a need to patch not one but at least 2 systems.

SEO (and other metadata consuming engines)

Google becomes better and better in indexing javascript content but still, it is safer and much more effective to be able to provide it all the content on the first request to the main URL. If your website heavily relies on traffic from search engines, a decoupled approach might not be the best solution.

You should also take other services into account. For example for content to be nicely shareable via Facebook and Twitter, each piece of content has to have a separate URL and what is also important, must return the basic data obtainable without javascript. At least for now, Facebook and Twitter when you share a link there, prepare the preview by querying the link without enabling javascript. The title, image and description information should, therefore, be available without the need to enable javascript.


Shareability - returning metadata information on routes

For Facebook and Twitter, it is enough to return a small part of websites content on each route. This can be even done, and sometimes is, by a simple script in a server-side language (in PHP or python etc) which, depending on the route queried, returns different metadata. The server, instead of serving a flat HTML file with a js application, parses a script and returns identical HTML with just the meta tags varying.

SEO  - Server-side rendering

For SEO purposes the above approach can also be used, but typically another way is more efficient. Assembling a complete page with content often requires quite a lot of logic, which then has to also be available in the frontend application. Writing the same page assembling logic both in a server-side language and then in javascript for the front-end does not make sense.

The developer community-created open source javascript frameworks based on React, which allow for the creation of javascript applications which render the page on the server and then enrich it with slick UI in the frontend. There are 2 most commonly used frameworks:

Both of these offer similar functionality and allow building of super-fast websites assembled in the backend and working super smoothly in the frontend. 

From Drupal perspective, development of a headless CMS is identical for a typical single page application.

Loss of some of the Drupal functionality

Drupal out of the box provides a lot of functionality. If Drupal is kept in the backend, a lot of this is no longer available. In particular:

  • Layout management  - drupal provides a highly configurable page layout management with region definition and an ability to place elements in various parts of the page without the need to code them in (eg placing a search window in the header or a menu in the footer). 
  • Account management screens- Drupal provides register, login, password reset functionality out of the box. If we intend to allow users to register, we will have to implement all the forms and connect them to the APIs.
  • Preview - If we create content in Drupal, we as an author can preview it before it is published. In a typical headless setup especially if content is available via many channels, the preview of all is not available. Often editor adds content without seeing the end result. If needed, it has to be separately architected and created to allow editors to preview their creations.


Headless Drupal is an interesting approach to build feature-rich interactive websites or build content hubs which power various content consuming websites and media. It is however not without disadvantages and careful consideration should be made before choosing this path. Hopefully, this article gave you sufficient information to chose. If not, we are always happy to consult your Drupal project.

Give us a shout!

Feb 07 2020
Feb 07

In Drupal 8.4.X and later releases, Drush 9 is the only supported and recommended version. One of the key changes introduced in this version is a new model of writing custom Drush commands. From now on, .inc files are obsolete and you will no longer use them for your commands, which are now classes based on AnnotatedCommand format.

The underlying structure of a module containing your custom Drush command will look as follows:

Module structure with custom Drush 9 command

Drush9_custom_commands.info.yml file

Default information file with basic information for the module.

name: Drush 9 Custom Commands
description: Example of Drush 9 custom command.
core: 8.x
type: module
package: Examples

Drush.services.yml file

Using the standard services.yml file will not work anymore, and it will lead to an error since Drush now expects you to use a separate drush.services.yml file with service definitions for your custom Drush commands.

    class: \Drupal\drush9_custom_commands\Commands\Drush9CustomCommands
      - { name: drush.command }

Drush9CustomCommands.php file

As such, this is the most crucial file, including the entire definition for your commands. 

 FALSE, 'reverse' => FALSE]) {
    if ($options['uppercase']) {
      $text = strtoupper($text);
    if ($options['reverse']) {
      $text = strrev($text);

Your commands class inherits from DrushCommands, and you can use it to include numerous commands, of which all are separate methods using annotations.

Some of the annotations available for use include:
@command – command definition, which needs to follow the module: command structure;
@aliases – aliases for your commands, separated with spaces;
@param – which defines the input parameters for your command;
@option – which defines the options available for your commands, which should be put in an associative array, where the name of the option is the key;
@usage – example showing how the command should be used.

Usage examples for the above command:

Drush d9-message 
Hello world!

drush d9-message --uppercase --reverse drupal8


At our Drupal agency, we are pretty sure that those who wrote their custom Drush commands before Drush 9 was released can notice quite a number of differences here, as we’re seeing a departure from the old way, which was well-known to Drupal 7 developers, towards the new Symphony-based solution. Those who haven’t had a chance to work with Drush commands yet will probably find the above example pretty boring. What can your custom Drush command be used for in practice? For example, recently I had an opportunity to integrate Drupal with an external blogging service. Using cron, the posts are added to Drupal at specified intervals. Thanks to a custom Drush command, I can run such an operation at any time without using UI. What is more, the parameter enables its user to download any number of posts using a numeric value or “all” setting. The above solution proved to be very useful during the initial migration when all the existing posts and entries had to be downloaded. What kind of processes are you going to make easier thanks to custom Drush commands?

Jul 18 2018
Jul 18

Droptica helps clients from all over the world to complete and implement their projects. Each of these clients has already developed their way of working. Everyone is different. In this article, I have collected the most common ways and systems of cooperation between Droptica and our clients.

Why do we work a little differently with every client?

We are Agile. We always want to maximise the results of our work. Our development team always adjusts and adapts their way of working to the client’s needs.
The elements that are adapted and changed the most often include:

  • project implementation methods (SCRUM, Kanban, etc.);
  • number of people in the team;
  • roles in the team (backend developers, frontend developers, QA, UX/UI, etc.);
  • the method of communication; Tools: JIRA, Slack, telephone or video calls, meetings;
  • frequency of communications;
  • communication channels (who, with whom);
  • implementation standards (some clients consider application performance to be the most important, others focus on implementing and providing new functionalities on a regular basis, while another group focuses on aesthetics and want their application to look good).

On the basis of these factors, I have identified several models of cooperation with clients, which are used the most often at Droptica.

Model 1: Product Owner at the client, with the rest of the team at Droptica

This is probably the most popular model employed at Droptica. We use it mainly when the end client comes to us. In most cases, the client already has a web system based on Drupal, Symfony or React and needs developers to develop the system further. Product Owner has a vision of application development and looks for a team that can efficiently perform the envisioned tasks.

In this model, we have a great impact on the development of the system. Our team not only performs assigned programming tasks but also proposes directions of development of the system and suggests improvements. In addition to developing basic functionalities, we also design user interfaces (UX/UI) and often carry out A/B tests that show us the best solutions for the client.

We use this model to develop WydawnictwoWAM.pl website. This is what the client has to say about us and about working in this model: 

"We established cooperation with Droptica around two years ago to develop our online store available at http://www.wydawnictwowam.pl. Both the quality of all the works carried out, as well as our cooperation were stellar. The technical solutions suggested and implemented by Droptica were a great help and often improved the value of our system, often exceeding our initial expectations. Cooperation with Droptica is characterised by very friendly, direct and precise communication on their part. Thanks to that, we were – and constantly are – able to define and detail all the tasks related to the development of our sales platform. We also appreciate their very clear settlement system, which allows us to better plan and allocate funds for development. In other words, we definitely recommend working with Droptica".

Model 2: Product Owner, QA, PM on the client’s side, software developers provided by Droptica

In this model, we provide our customers with solid development support. Most of the project planning and management process is carried out by the client, while our experts carry out specific development tasks.
It is a kind of cooperation that we usually go for with large companies and corporations, expanding their Drupal, PHP and ReactJS teams.
As a rule, in such a model we work on servers and project management systems provided by the client. We adapt to their processes.

Mixed models

Other models are usually combinations of the two models presented above. For example, Droptica provides not only development team but also testers, while the entire project is managed by the client. We also sometimes work on projects where we collaborate with other software developers from the client's company, working not as an independent development team, but a part of a larger team.

We are Agile

We are flexible regarding the form of cooperation with our clients; however, we like the first model the most. In that model, we take on a great deal of responsibility for the project and we are able to influence the direction of development together with the client. This gives us great satisfaction, and we offer numerous ideas for improving the system, which allows our clients to better achieve their business goals.

Would you like to learn more about our work models? Contact us at [email protected] and we'll be happy to talk to you.


Jun 13 2018
Jun 13

The deadline is today. A remote development team have worked for several weeks on your software. You obtain the long-awaited access to the system. You check it and you are not satisfied with the achieved results.

All that was needed to avoid this problem is a team with experience in technology and working using SCRUM.

What is SCRUM

Wikipedia defines SCRUM as an agile framework for managing work. It is an approach used in many companies to develop software. The full definition can be found here https://en.wikipedia.org/wiki/Scrum

SCRUM solves most of the problems arising during software development

This is my opinion and many people agree with it. I have been developing commercial projects since 2008. I started as a programmer. Currently, I am supervising projects.

In Droptica, Drupal developers work in teams delivering complex projects. Introduction of the SCRUM method in Droptica solved most of the problems. Which ones exactly?
Here are the most important of them:

  • The client was not regularly informed about the progress of works – the client was not satisfied. Sprints, review, backlog refinement – all this compels a constant contact with the client
  • The tasks were not thought through before starting them, therefore they took a long time to finish – the client was not satisfied. Backlog refinement and planning – these events ensure that the team has to really ponder on completing each task.

SCRUM saves money

You can ask yourself: how is that possible if you do not know the exact duration and cost of the project at its beginning? The answer can be found in the previous paragraph:

  • Regular meetings with the client (Product Owner) force them to think about which tasks are actually needed and which can be rejected.
  • Analysis of tasks by the team together with the PO, often allows to come up with better ways to implement or reject them.

SCRUM is often called the art of maximising work not done. You maximise the rejection of the tasks that are unnecessary from the point of view of your business. You do only the things that bring particular value to the system. Everything else goes straight to the waste bin.

Why so many meetings?

Planning the sprint, daily scrum, retro, review, backlog refinement. The list of meetings is long. There is no doubt that they take time. The client often expects to pay for programming, not for conversations and meetings.

I used to think the same way. However, after a test implementation of SCRUM in one of the projects, I have changed my mind. Now I want to develop all our projects – for clients and internal – using SCRUM. I see that it saves great amount of time and money. The same can be confirmed by the clients with whom we now work using SCRUM, while we did not have a specific way of working before.

Abraham Lincoln once said, "If I had eight hours to chop down a tree, I'd spend six sharpening my ax."

The meetings guarantee a good rethinking of tasks, sticking to a common direction and pursuing the same business goals. It is definitely worth it.

How long will it take and how much will it cost?

Every client asks this question at the beginning. It is not easy to answer it. The pace of each programmer is different, there are different working conditions, holidays, leaves, the requirements change (from the client, legal requirements, etc.). A longer project also means a frequently changing specification. Such changes change the cost and time.

Story Points is a solution to the problem. It is a very good tool for estimating the number of tasks that can be performed in a sprint (stage). After just 2-4 sprints you can see the team's average pace. After such a time the team knows the project well, knows the client well and plans for the future. The team can very accurately estimate the tasks waiting in the Backlog. Product Owner, knowing the pace of the team can count the number of sprints and the total cost.

Compared to creating a detailed specification at the beginning of the project, such an approach gives better estimation results.

SCRUM is not enough if the team does not have the experience with the technology

If the team will work using SCRUM, but will not be familiar with the technology, it will not be able to provide good quality software within a reasonable time. Only the combination of SCRUM and the team experienced in using the given technology ensures significant effects. The customer will definitely be satisfied with such a combination.

Why a remote team is better?

What is the difference between a remote team and a local team? Actually – just their location. If you can have a local team, it is worth choosing this option. It will be more convenient.

However, in today's IT market it is difficult to complete a team of 2, 3 or more specialists in a short time for a larger project. That is why you should think about a remote SCRUM team. A team that already has the experience in working with a remote client. By expanding the options to the whole world, you have more choices.

How can I monitor what a team thousands of miles away is doing? 

SCRUM has a way to do it: Sprint Burndown Chart. It is a chart that is updated daily. It shows the regular peace of project development. It shows whether the team implements the sprint plan. It is the best tool for monitoring the progress of works. Using Waterfall, you usually find out about delays at the end of a larger stage. With SCRUM, the client can check every day what progress the team has made. They can be sure that the team works and delivers consecutive parts of the software.

How to communicate with the team?

At Droptica we have 3 ways to do that:
- Jira - it is the main communication system; here we have all User Stories and tasks
- Slack - for short text questions, used practically every day
- Skype/Google Hangouts/Zoom - for video calls with screen sharing

These three forms of communication in 100% ensure very good communication between the team and the Product Owner.

If possible, once in a while, the development team meets with the Product Owner at our office or in the client's office. Our offices are located close to the airport, we eagerly invite our clients to visit them.

How can I check if a remote SCRUM team will work in my case?

If you have a project for a minimum of 2-3 people for a few sprints, a well-conducted SCRUM will provide you with very good results.

If you are not sure if SCRUM will work for you, test it. Order 2-3 sprints and see what results you will get. It is a small cost within the scale of projects taking several months, and such an approach will provide an unambiguous answer to the question of whether it is worth using SCRUM.

If you still have doubts about a remote SCRUM team, I will be happy to answer your questions and share my experiences. Contact me at [email protected] or write your question in the comment.

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