Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough
Oct 19 2021
Oct 19

Website reconnaissance is one of the elements of a security audit. This task can be automated to some extent by choosing one of the free, open-source programs available on the web. One of such tools is Droopescan.

What is Droopescan?

Droopescan is a script allowing speeding up the initial reconnaissance of the audited website if it uses one of the CMSs listed below. The script enables defining your own plugins, which can allow even greater automation of the initial review process. You can find more about creating own plugins, that extend the functionality of the script, in README.md on the previously linked tool’s page on Github.

Drupal scanner features

Droopescan capabilities vary depending on the content management system.

In Drupal, these are the functions that allow identifying:

  • installed plugins,
  • installed themes,
  • paths of interest to a potential attacker (such as the login panel or the changelog file),
  • Drupal version used.

In Joomla and WordPress, you can identify the paths of interest to an attacker, and the used version of these systems. In another CMS, Moodle, the Droopescan tool can recognize the installed plugins and themes, and the version of the content management system in use.

In the Silverstripe system, we'll identify:

  • installed plugins,
  • installed themes,
  • paths of interest to an attacker,
  • Silverstripe version used.

Methods of installing the script

The developers have prepared several methods of installing the script. We can choose the most appropriate way, depending on our preferences.

Using pip

This is the installation method recommended by the creators:

apt-get install python-pip pip install droopescan

Manual installation

To install the script manually, run the following commands:

git clone https://github.com/droope/droopescan.git cd droopescan pip install -r requirements.txt ./droopescan scan --help

On the BlackArch distribution

For installation on the BlackArch distribution, the creators recommend using pacman:

sudo pacman -S droopescan


Droopescan can also be installed as a Docker container:

git clone https://github.com/droope/droopescan.git cd droopescan docker build -t droope/droopescan . # display help docker run --rm droope/droopescan # example scanning a drupal site docker run --rm droope/droopescan scan drupal -u https://drupal.example.com


The Droopescan script is very flexible and allows configuring the scan as you wish. Thanks to the settings, we can change the type of scan, choosing one of the available frameworks, provide an address or a list of addresses to be scanned, and much, much more. Here's a complete list of the configurable options.


droopescan scan --help

Opens a list of the available commands.

droopescan scan


Runs the scripts responsible for scanning the website that uses the selected CMS.

droopescan scan --debug

Runs the debug output.

droopescan scan --quiet

Enables silent mode that doesn't show the information about the scan while it's running.

droopescan scan -u {URL} and droopescan scan --url {URL}

They allow defining the target of the scan.

droopescan scan -U {URL_FILE} and droopescan scan --url-file {URL_FILE}

They allow defining the file path where the target scan websites are located. The file structure should look like this:

> cat example.txt http://localhost/drupal/8.9.0/ http://localhost/drupal/8.7.1/ http://localhost/drupal/8.9.13/ http://example.com

droopescan scan -e {a, t, p, v, i} and droopescan scan --enumerate {a, t, p, v, i}

They allow defining what the script should scan:

  • p - plugins,
  • t - themes,
  • v - version,
  • i - useful links,
  • a (default) - all.

droopescan scan --method {not_found, forbidden, ok}

It allows specifying what type of error is treated as an indicator and whether a given path exists. For some servers, it's 403, for others – 404. By default, the script tries to deduce this itself.

droopescan scan --verb {head, get}

It allows specifying the type of request that the script will use. The default option is head.

droopescan scan --number {NUMBER} droopescan scan -n {NUMBER}

Specifies the number of words to be checked from the plugins or themes dictionary. It's one thousand by default. To use all available, you should type all.

droopescan scan --plugins-base-url {PLUGINS_BASE_URL}

Allows specifying the path where plugins are stored in the CMS. Without providing this parameter, the script checks the default path for a given system.

droopescan scan --themes-base-url {THEMES_BASE_URL}

Allows specifying the path where themes are stored in the CMS. Without providing this parameter, the script checks the default path for a given system.

droopescan scan --timeout {TIMEOUT}

Specifies how long the script should wait for an HTTP response in seconds.

droopescan scan --no-follow-redirects

Enabling this flag prevents redirects from being followed.

droopescan scan --host {HOST}

Overwrites the host query header with the provided value.

droopescan scan --user-agent {USER_AGENT}

Overwrites the User Agent header of the query.

droopescan scan --massscan-override

Using this flag replaces the default values with those convenient for mass scanning of hosts.

droopescan scan --threads {THREADS} and droopescan scan -t {THREADS}

A number of threads used for scanning. It’s 4 by default.

droopescan scan --threads-identify {THREADS_IDENTIFY}

A number of threads used for CMS identification.

droopescan scan --threads-scan {THREADS_SCAN}

A number of threads used for mass scanning of hosts.

droopescan scan --threads-enumerate {THREADS_ENUMERATE}

A number of threads used for plugins identification.

droopescan scan --output {standard, json} and droopescan scan -o {standard, json}

Allows specifying the format of the output returned by the script.

droopescan scan --hide-progressbar

Enabling this flag allows turning off the progress bar.

droopescan scan --debug-requests

Enabling this flag enters into the console the contents of all HTTP requests made by the script, together with the response received from the server. Enabling this flag disables scan threading and progress bars.

droopescan scan --error-log {ERROR_LOG}

Allows defining the file that all scan errors will be logged to.

droopescan scan --resume

Returns the scan to the stage where it was last completed. It's a useful option when using mass scanning.

Example of using Droopescan

Our test page uses Drupal 8.9.15 and contains a list of many popular modules. It uses a custom theme, and logging into the admin panel is carried out with the default path.

To start the scan, we'll use the command:

droopescan scan drupal -u example.com

You can see the result of the scan below.

➜  droopescan git:(master) docker run --rm droope/droopescan scan drupal -u example.com
modules [ ===                                                ] 224/4000 (5%)[+]  Got an HTTP 500 response.
modules [ ====                                               ] 287/4000 (7%)[+]  Got an HTTP 500 response.
modules [ ====                                               ] 288/4000 (7%)[+]  Got an HTTP 500 response.
modules [ ========                                           ] 626/4000 (15%)[+]  Got an HTTP 500 response.
modules [ ==============                                     ] 1053/4000 (26%)[+]  Got an HTTP 500 response.
modules [ ==============                                     ] 1056/4000 (26%)[+]  Got an HTTP 500 response.
modules [ ================                                   ] 1272/4000 (31%)[+]  Got an HTTP 500 response.
modules [ ============================                       ] 2227/4000 (55%)[+]  Got an HTTP 500 response.
modules [ ================================                   ] 2509/4000 (62%)[+]  Got an HTTP 500 response.
modules [ ===============================================    ] 3746/4000 (93%)[+]  Got an HTTP 500 response.
[+] Accepted redirect to https://www.example.com/
[+] Plugins found:
    image_widget_crop https://www.example.com/sites/all/modules/image_widget_crop/
    flexslider_views_slideshow https://www.example.com/sites/all/modules/flexslider_views_slideshow/
    service_links https://www.example.com/sites/all/modules/service_links/
    compact_forms https://www.example.com/sites/all/modules/compact_forms/
    strongarm https://www.example.com/sites/default/modules/strongarm/
    video_embed_field https://www.example.com/sites/default/modules/video_embed_field/
    tablefield https://www.example.com/sites/default/modules/tablefield/
    ctools https://www.example.com/modules/contrib/ctools/
    token https://www.example.com/modules/contrib/token/
    pathauto https://www.example.com/modules/contrib/pathauto/
    metatag https://www.example.com/modules/contrib/metatag/
    field_group https://www.example.com/modules/contrib/field_group/
    google_analytics https://www.example.com/modules/contrib/google_analytics/
    redirect https://www.example.com/modules/contrib/redirect/
    colorbox https://www.example.com/modules/contrib/colorbox/
    features https://www.example.com/modules/contrib/features/
    devel https://www.example.com/modules/contrib/devel/
    admin_toolbar https://www.example.com/modules/contrib/admin_toolbar/
    better_exposed_filters https://www.example.com/modules/contrib/better_exposed_filters/
    paragraphs https://www.example.com/modules/contrib/paragraphs/
    smtp https://www.example.com/modules/contrib/smtp/
    search_api https://www.example.com/modules/contrib/search_api/
    entity_reference_revisions https://www.example.com/modules/contrib/entity_reference_revisions/
    linkit https://www.example.com/modules/contrib/linkit/
    eu_cookie_compliance https://www.example.com/modules/contrib/eu_cookie_compliance/
    scheduler https://www.example.com/modules/contrib/scheduler/
    simple_sitemap https://www.example.com/modules/contrib/simple_sitemap/
    google_tag https://www.example.com/modules/contrib/google_tag/
    addtoany https://www.example.com/modules/contrib/addtoany/
    advagg https://www.example.com/modules/contrib/advagg/
    config_update https://www.example.com/modules/contrib/config_update/
    robotstxt https://www.example.com/modules/contrib/robotstxt/
    config_filter https://www.example.com/modules/contrib/config_filter/
    menu_link_attributes https://www.example.com/modules/contrib/menu_link_attributes/
    migrate_plus https://www.example.com/modules/contrib/migrate_plus/
    checklistapi https://www.example.com/modules/contrib/checklistapi/
    config_split https://www.example.com/modules/contrib/config_split/
    migrate_tools https://www.example.com/modules/contrib/migrate_tools/
    config_ignore https://www.example.com/modules/contrib/config_ignore/
    schema_metatag https://www.example.com/modules/contrib/schema_metatag/
    tvi https://www.example.com/modules/contrib/tvi/
    svg_image https://www.example.com/modules/contrib/svg_image/
    link_attributes https://www.example.com/modules/contrib/link_attributes/
    facets https://www.example.com/modules/contrib/facets/
    yoast_seo https://www.example.com/modules/contrib/yoast_seo/
    panels_everywhere https://www.example.com/modules/contrib/panels_everywhere/
    stage_file_proxy https://www.example.com/modules/contrib/stage_file_proxy/
    entity_reference_display https://www.example.com/modules/contrib/entity_reference_display/
    we_megamenu https://www.example.com/modules/contrib/we_megamenu/
    ckeditor_codemirror https://www.example.com/modules/ckeditor_codemirror/

[+] No themes found.

[+] Possible version(s):

[+] Possible interesting urls found:
    Default admin - https://www.example.com/user/login
    Default changelog file - https://www.example.com/CHANGELOG.txt

[+] Scan finished (0:16:25.708460 elapsed)

CMS scanning - results analysis

The Droopescan tool helped to identify many of the modules used on the website and provided links to the files that made this identification possible. The script identified the Drupal version used as one with a minor update from 8.9.6 to 8.9.17 and detected the path to the login panel and the CHANGELOG.txt file. Unfortunately, in the case of the audited website, it wasn't possible to identify the theme used.

Droopescan - summary

The Droopescan script speeds up the initial reconnaissance of the audited website. It's a fast, stable, constantly updated solution that allows threading the scanning of multiple websites simultaneously and requires only Python. The scanning result is presented in a user-friendly way. It's possible to save the results in the JSON format, which can then be freely processed in order to, for example – using an application specially designed for this – to view the results in an even more friendly way or to use the results in the next stages of the audit. If you are interested in the topic of controlling application security, our Drupal support team can help you with their expert knowledge.

Oct 07 2021
Oct 07

When creating content for a website, it is sometimes necessary to plan its publication later down the line. However, taking care of it manually can be both time-consuming and inconvenient. This is when Scheduler comes in handy – a Drupal module that will help you automate this process. Using it will allow us, among other things, to schedule the publication of content for a specific date and time.

Scheduler module - dates

The module was released on 23 July 2006, and its latest update was pushed on 19 July 2021. Scheduler has versions for Drupal 7 and 8. What is more, the latest update is compatible with Drupal 9 as well.

Module popularity

The module is currently used on more than 85 thousand websites. About 44 thousand of them are running Drupal 7, and more than 37 thousand are on Drupal 8.

The usage statistics of the Scheduler module aimed for scheduling publication on a Drupal website

Source: Drupal.org

Module developers

Scheduler was originally published by Eric Schaefer. However, the list of people working on its development to date is very long and impossible to establish – we don’t know all the users who contributed to its development.

Drupal Scheduler module – what does it do?

As I pointed out in the introduction, the module is used to plan content publication in advance. It also offers you a way to plan unpublishing. If needed – for example, in the case of events, where news will be made obsolete after the end, you can task the module with publishing your content and schedule its removal from your website at a specific day and time.

Scheduler provides three new permissions, allowing only the selected roles to have access to scheduled publishing. The list of possibilities also includes the so-called Lightweight cron, the configuration of which optimizes resource consumption. Lightweight cron is the developers' solution to make the cron responsible for publishing and removing content available to be run separately, without the need to initiate all other tasks, as is usually the case in Drupal.


Installation is standard. I recommend using Composer.

composer require drupal/scheduler
Scheduler composer



Go to


– there, you will find a list of permissions that the module provides:

Permissions available in the Drupal Scheduler module


Administer scheduler

This setting enables you to configure the Scheduler module, available at


(see the next section for the description of all the features).

Scheduler content publication

Granting this permission allows a role to set scheduled publication, as well as to plan unpublishing.

View scheduled content list

Scheduler provides a view, which is available at


Granting this permission allows you to access this view.


Go to


to find all the global settings for the module. What is more, Scheduler can be configured per content type. Below, you can find a break down the global options.

Global settings of the Scheduler module


Allow users to enter only a date and provide a default time

Allows users who have permission to configure scheduled content publishing to specify only the publication date. When this option is selected, the time will be predefined and configurable in the Default time field.

Defining the publication date of the user-selected content in the Scheduler module.


Hide the second

Checking this option disables the ability to set seconds when scheduling content publishing.

Lightweight cron

As I pointed out earlier, by default, Drupal runs all cron jobs every once in a while. Checking which content needs to be published and unpublished relies on a cron job, which should be run every 1-5 minutes. Configuring Drupal to run all cron jobs every minute is hardly a very good idea, considering its performance, which is why the developers enabled the users to run a single cron job at a suitable interval. To do this, you need to add a new cron job run at a given time. Here is an example of a cron job that is run every minute: 

* * * * * wget -q -O /dev/null "https://tesd9.lndo.site/scheduler/cron/{access-key}

Go to


to find the lightweight cron settings. There, you can enable logging of cron job activation and completion, change access-key and run cron manually.

Content type

I’ll illustrate this option with the default content type - Article - available in Drupal default profile. Go to


There, you will notice a new Scheduler tab. This is where you’ll find all the module's configuration options, which you can set for each entity.

In the Scheduler tab, related to the types of content, you will find all configuration options for the entity


Enable scheduled publishing/unpublishing for this content type

Enables or disables the ability to set scheduled publication and/or unpublishing.

Change content creation time to match the scheduled publish time

Changes the date in the creation time field to the date selected as the planned publication date.

Require scheduled publishing/unpublishing

Checking this option makes setting scheduled publication and/or unpublishing required.

Create a new revision on publishing/unpublishing

Creates a new revision during scheduled publication and/or unpublishing.

Action to be taken for publication dates in the past

This setting enables you to specify what will happen when the editor selects a publication date earlier than the current date. You can choose one of three options here:

  • Display an error message about choosing a date earlier than the current one – in this case, the content won’t be published.
  • Publish content immediately after saving.
  • Schedule your content to be published on the next cron job run.

Display scheduling options as

Changes the way Scheduler module options are displayed when creating and editing content. There are two options to choose from – Vertical tab and Separate fieldset.

Vertical tab

The vertical tab is one of the possibilities for displaying the Scheduler module options


Separate fieldset

Separate fieldset is one of the ways to display Scheduler options


Expand fieldset or vertical tab

Allows you to specify whether the field provided by the Scheduler should be expanded when creating and editing content.

Show message

Checking this option displays information about planned publication and unpublishing after saving the content.

Scheduled publication notification from the Scheduler module

Module usage

Let's assume that our article needs to go live on 1 September 2021 at 9:30 a.m. and won't have to be unpublished.

When writing the article, choose Publish on and set it to 01.09.2021 at 9:30 a.m., and then leave Unpublish on empty. In this case, the Require scheduled unpublishing option must be disabled for the Article entity.

Options for scheduling a publication for a specific date

Now imagine that our article needs to go live on 1 September 2021 at 9:30 a.m. and has to be unpublished a week later at the same time.

Let's start with doing the same thing as we did in the previous example, but this time also set Unpublish on to 08.09.2021 at 9:30 a.m.

Setting the time of publication of the article and unpublishing in the Drupal Scheduler module

You may be also interested in: How to Make Content Editing Easier in Drupal - Review of the Simplify Module


Scheduler offers integrations with several Drupal modules.

  • If you’re using the Content Moderation module, you must enable the Content Moderation Integration sub-module.
  • Scheduler provides additional conditions, actions, and events for the Rules module.
  • It is also integrated with the automatic generation of test content provided by the Devel Generate module. Scheduler can automatically add the planned publication and unpublishing dates.
  • It also creates new tokens for the Token module, containing the planned publication and unpublishing dates.

The future of the module

The developers responsible for the Scheduler have announced that they are working on releasing version 2.0 of the module, supporting entities other than nodes, for example, Media, Commerce Products, and more. They also announced that events triggered by the Scheduler module and its integration with the Rules module will from now on be triggered after an entity is saved, rather than before, as was the case until now. The development progress can be followed on the module page.

Drupal Scheduler module – summary

Scheduler is a tool that greatly facilitates the scheduling publication of content on your website. Using it allows you to automate the process and makes it possible to do all the steps required to publish content at any time – thus making sure that you won't have to worry about it when the time comes. At Droptica, we also use Scheduler to schedule publications in advance. This module is extremely popular among Drupal users, and as such, it is constantly developed – with version 2.0 in the works right now. Our team of Drupal developers recommends using the Scheduler module to schedule publications in advance or to publish content for a specific time.

Sep 24 2021
Sep 24

The security of the solutions we provide is a very important factor for us. Due to this and the fact that Drupal is the safest CMS, in this article, we'll present the list of recommendations that'll take the security of your Drupal website to an even higher level.

Drupal security. Why is it good to stay up to date?

Your application is less susceptible to exploiting known vulnerabilities. That's it. But it means so much more.

As I've mentioned before – updating modules and libraries is one of the simpler methods of improving the security of our application. The Drupal community supported by the special Drupal Security Team constantly monitors the user reports on potential security bugs and offers to help the modules' authors solve them. The result of these actions are module updates that introduce security patches.

Configuration of the login panel

An incorrectly configured login panel may provide information about the existence in the database of a user using the login provided in the form. If the information that the panel returns in the case in which the attacker provided an incorrect login is different than when the login is correct, we're dealing with a brute force attack vector. This way, the attacker may obtain the logins first and then deal with brute-forcing the passwords.

Drupal modules increasing website security

Drupal has several modules that may improve security. Their configuration doesn't require extensive technical knowledge and doesn't take as much time as other methods of securing a website. We present below some tools of this type.

Drupal Password Policy

The Password Policy module allows for enforcing restrictions on the users' passwords by defining password policies. It can be defined by a set of requirements that must be met before a user password change is accepted. Every restriction has a parameter that specifies the minimum number of important conditions that must be fulfilled to meet the requirement.

Let's suppose we're limited to uppercase letters (with parameter 2), as well as limited to numbers (with parameter 4). This means that a user password must contain at least two uppercase letters and at least four numbers to be accepted.

The module also implements the "expiring password" function. The user is forced to change their password and is optionally blocked when their old password expires.

Drupal Password Policy allows administrators to force specific users or entire roles to change their password the next time they log in. The request to change the password, along with the appropriate form, appears as a popup instead of redirecting the user to the typical user/{user_id}/edit page.

Drupal Security Review

The Security Review module automates the testing of many easy-to-make mistakes that cause the website to be unsafe. This Drupal module is intuitive and very easy to use. The quickly-prepared report is legible and clearly indicates what needs to be improved. The module doesn't automatically introduce changes to your page. The results of the report should be analyzed, and – in selected cases – appropriate corrections should be made. Not all recommendations will be acceptable. It all depends on the unique factors of your website.

Drupal Security Kit

The Security Kit module provides a variety of security-enhancing options to help reduce the risk of various vulnerabilities in your application being exploited. The module reduces the likelihood of using many types of attacks, including:

  • cross-site scripting,
  • cross-site request forgery,
  • clickjacking.

The full description of the functionalities can be found in the article linked above.

Security Kit is one of the Drupal modules that help increasing website security

Source: Drupal.org

Drupal Paranoia

The Paranoia module identifies most places where the user can execute the PHP code using the Drupal interface and then blocks them. This reduces the potential threat resulting from the attacker gaining high-level authorization in Drupal.

What does the module do?

  • Blocks the grant of the use of PHP for block visibility permission.
  • Blocks the ability to create text formats that use the PHP filter.
  • Blocks the ability to edit the user account with uid 1.
  • Blocks granting the permissions that may reduce the website security.
  • Blocks disabling this module. To disable it, you need to edit the database.

In order to take full advantage of this module, you need to identify all the entities, fields, and blocks that use the Drupal PHP filter and change them so that they work without it, and then remove the standard PHP filter available in admin/config/content/formats.

How to create a secure code in Drupal?

Drupal uses the solutions that are assumed to be secure when used according to the standards. There are many rules you need to follow when creating a secure code. We present the most important of them below.

Use Twig

The Twig engine "auto-escapes" all variables by default. This means that all the strings rendered by the Twig templates (e.g., everything between {{ }}) are automatically cleared of the elements that may compromise the security of your application.

When rendering the attributes be sure to embed them between quotation marks " or apostrophes '. For example, class=”{{foo}}”, not class={{foo}}.

Use placeholders

Translation API also cleans up strings. Use it for the strings you want to translate and later, for example, render on the frontend side.

In Drupal, there are three types of placeholders in the Translation API:


We use it when we want to substitute a string or an object of the MarkupInterface class for a placeholder.


We use it when we want to embed a value between the variable tags.


We use it when the value we want to substitute is the URL we want to embed in the href attribute.

You can find more about placeholders at Drupal.org.

Learn the API and use it

Drupal provides many features for cleaning up strings. Among them are:

t(), Drupal::translation()->formatPlural()

Used along with the placeholders described above, it allows for creating secure strings ready to be translated.


Used to clean up plain text.


Use it when you want to clean up the text entered by an admin who should be able to use most of the HTML tags and attributes.

UrlHelper::stripDangerousProtocols(), UrlHelper::filterBadProtocol()

Useful for URL checking, can be used together with SafeMarkup::format().

The strings that have passed through the functions t(), Html::escape(), Xss::filter() or Xss::filterAdmin() are automatically considered safe, as are the strings produced by the render array from the Renderer class.

Filter text also in JavaScript

Server-side text filtering is considered to be one of the best practices. However, there are cases where filtering will also take place on the client side to provide additional temporary filtering capability. It's useful, for example, when rendering the elements that are updated as the user types the text (that is, there are changes to the DOM tree being introduced). To filter text in Drupal by using JavaScript, you should use the Drupal.checkPlain() function. This feature cleans up the text by removing the harmful elements and protects against, for example, some clickjacking attack methods.

Use an abstraction layer when working with a database

We recommend never using pure values in the queries. You should use placeholders instead.


\Database::getConnection()->query('SELECT foo FROM {table} t WHERE t.name = ‘ . $_GET['user']);


\Database::getConnection()->query('SELECT foo FROM {table} t WHERE t.name = :name', [':name' => $_GET['user']]);

In the second case, instead of using the value from the user parameter directly, we provide it as the :name placeholder substitute. This way, before putting this value in the final query, Drupal will first clean it from the elements that could cause SQL Injection.

Security audit

The process of "hardening" a site should end with a comprehensive security audit that will catch even more potential threats on your page.

A security audit should include:

Modules and libraries review. This means checking the versions of the installed Drupal modules, reviewing the patches, PHP libraries, and JavaScript.

Configuration review. As part of this activity, we carry out authorization audits for the roles, views, routing.yml files in custom modules, text formats, error logging and forms.

Repository review. We check the custom modules and themes, including routing, custom forms, SQL queries, filtering mechanisms and file permissions.

Repository contents identification. We audit the contents of the settings.php and .env files. We also conduct an audit of deeply hidden elements. It's based on checking the repository for, for example, SSL private keys or database copies or dumps.

You can find the full description of many of the elements presented in the above list in the linked articles.

Drupal security modules - summary

Depending on the level of advancement and knowledge of Drupal, you can introduce appropriate corrections to the application to make it more secure. The examples presented in this article will definitely reduce the number of attack vectors and the likelihood of using them. We recommend analyzing the available options and possibly introducing the changes or new elements that'll reduce the risk of an attack on your application. If you need help with such activities, our Drupal support team can conduct an audit of your website security.

Sep 16 2021
Sep 16

The Drupal system can be classified as one of the safest CMSs on the market. It has a refined structure and a wide range of functions. In this text, we'll take a look at Drupal 8 first. We'll remind you when it was released and what changes it brought when compared to the previous versions. Next, we'll take a closer look at Drupal 9 and then compare both versions.

Drupal releases

Drupal 8 was released on 19 November 2015. Compared to the previous version, that is – Drupal 7, there were as many as 200 new built-in functions, the multilingualism of the platform was improved and, for example, the new page editor and the version for mobile pages were introduced (as a built-in function – no additional domain for the mobile version is required). In terms of differences from the previous version, we can also add the fact that Drupal 8 uses object-oriented programming, instead of the procedural approach used in the previous version. The new version of Drupal uses a different theme engine – Twig, which is based on PHP. This makes it easier for programmers creating new themes because of the simpler syntax.

Another additional feature in Drupal 8 is the ability to edit the content directly from the site's user interface. It's also worth mentioning that the newer version of Drupal has access to the views directly from several administration screens. There's no need to spend additional time on it anymore, as was the case with Drupal 7. Looking from the perspective of a person viewing the page, we can also notice that the page loading speed has significantly increased thanks to entity caching. In addition, the previously viewed content doesn't need to be reloaded because it remains in the system cache. Also, the JavaScript code isn't loaded until it's necessary. After updating Drupal to version 8, you should also pay attention to the new types of fields that can significantly simplify the work for programmers.

What's the difference between Drupal 8 and Drupal 9?

Drupal 9 was released on 3 June 2020. It was built on version 8, so the changelog is shorter and the update from version 8 to 9 is simpler. The most important differences are the removal of almost all deprecated functions. In version 9, they've been replaced by other ones, and those that remained will be removed in the next installment of Drupal. A list of deprecated functions is available at Drupal.org.

Also new in version 9 is the next version of Symfony. Drupal 8 used version 3, but now it's version 4. Additionally, the Twig theme engine version has been updated – has been changed from version 1 to 2. Another difference between Drupal 8 vs 9 is the fact that most of the jQuery UI library dependencies have been removed. In the case of performing tests, in the new version, we rely on the PHPUnit solution (previously, the SimpleTest framework could be used).

The next thing that was almost completely removed in Drupal 9 is the Simple Annotation Parser from Doctrine. However, the required elements were incorporated into the Drupal 9 core. We also need to pay attention to the Apache version, because in the case of Drupal 8 version 2.x was enough, but currently, Drupal 9 requires a min. version of 2.4.7. The situation is similar with PHP – this time a min. version of 7.3 is required, but version 7.4 and 8.0 are also supported (applies to Drupal 9.1.0). In terms of the database and the use of MySQL/Percona, Drupal 9 requires a min. version of 5.7.8; Drupal 8 worked with version 5.5.3. The same goes for using MariaDB and SQLite. These need to be min. versions of 10.3.7 and 3.26 respectively. The previous version of Drupal used version 5.5.20 for MariaDB and 3.6.8+ for SQLite.


According to the above description of the differences between Drupal 8 vs 9, we can certainly say that the newer CMS release is much better in terms of speed. Using a min. PHP version of 7.3 improved the page loading speed. We can see an example on the PHP Benchmarks page, where all PHP versions are listed – from 5.6 to 8.0. At the very first glance, we can already see that between Drupal 8 and 9 there was an increase in performance of over 10%. This is the perfect reason to consider an upgrade, as each new version of PHP causes an even bigger leap in performance.

The situation is similar with Symfony. Version 3 has been used so far, but Drupal 9 needs the newer, fourth version of the framework. Thanks to it, we can significantly reduce the working time the developers need to create a new module or improve an existing one. The results of comparing Symfony versions from 2 to 5 can be checked on the already mentioned PHP Benchmarks page.

Comparison of the Symfony versions on the PHP Benchmarks website


Another point that we can refer to in the context of the performance comparison is the Twig version used. In the case of Drupal 9, the theme engine is about 15% faster than the one used in Drupal 8.

Performance comparison of the different versions of the Twig template engine used in Drupal


You may also be interested in: Why Drupal Is The Best Headless CMS?

Drupal 8 to Drupal 9 – upgrade

Upgrading Drupal 8 to Drupal 9 is much simpler and less time-consuming compared to the transition from version 7 to version 8. First, we need to verify that we are using the latest version of Drupal 8. It should also be noted that soon (November 2021) support for the older, eighth version of the described CMS will end, so soon we should carefully think over the update process and prepare for updating Drupal.

Once we are sure that we have the latest version of Drupal 8, we can start by updating all modules and skins. In this case, we also need to have their latest versions. At this step, we'll see that most of the modules already support Drupal 9. Next, it's worth using the tool provided by the authors of this CMS to prepare a checklist of things that need to be prepared, so that the update goes smoothly and without complications.

One of the last steps will be to check whether the server on which we plan to install Drupal 9 meets the requirements for PHP, Apache, and database engine versions. We've described the required versions in the previous paragraphs. At this point, we're one step away from using Drupal 9. It only takes a few clicks and some time to go through the entire update process.

Drupal 8 vs Drupal 9 – summary

Due to the upcoming end of support for Drupal 8, the significant increase in system performance, and the relatively simple means of updating to the latest version, we recommend that you complete this process as soon as possible. Thanks to this, you'll avoid any problems after support has ended and complications in the event of updating "real quick" in an environment that's not adapted to this. It's worth planning this process from start to finish and enjoy the much greater transparency of the code and the new possibilities offered by Drupal 9.

If you don't know how to properly update to the latest version, our experienced Drupal support team will be happy to help you.

Sep 09 2021
Sep 09

In the previous parts, we focused on Drupal configuration and the overview of modules and libraries. In the third part of the series on conducting a security audit, we'll focus on the overview of custom modules and themes. We'll perform an audit of the project repository, identify and analyze the elements worth paying attention to during the auditing process.

Overview of custom Drupal themes and modules

In custom Drupal themes and modules, attack vectors are most likely to appear. There's code there that isn't being widely used, unlike the code for contrib modules and themes. Therefore, it's not so well-tested in terms of security. In this article, I'll discuss a basic checklist used for auditing custom Drupal code. This list can be used as the basis for an audit of custom modules and themes.


We’ll start with the analysis of the parameters received from the user. Let's check out what is their type and how are they filtered. Drupal allows for using parameters in routings. These are dynamic values, incorrect processing of which may create attack vectors. If a query is created on the basis of a parameter and not filtered, this may cause a vector for SQL Injection attack, for example.

Next, we should look at the routing access configuration, specifically – the permissions that the user must have to get access. When declaring the routing, we need to define the requirements that the user must meet to gain access to the routing. We have to analyze the required permissions for every routing specified in our custom Drupal code and consider whether their level is appropriate. Specifying too low or incorrect level of required permissions will result in users having access to pages that they shouldn’t have access to. These can be both the pages listing the articles on your page and the pages listing all users along with all the data assigned to a given account. For this reason, the permissions audit is so important.


First, we'll analyze the correctness of the element types and check out if the correct type for a given field has been used. During the analysis of the types of fields used in the form, we may come across a field whose name and description suggest that it should be filled out with data of a specific type. However, the field's definition may allow the field to be filled out with other types of data. We should make sure that the definition of the type of elements corresponds with their purpose.

The next step will be to analyze the used methods of validating the field values in the form. Drupal allows for defining custom methods that validate the correctness of the entered data. We should test the correctness of the custom validation methods and make sure that only the valid data passes the validation.

The last thing will be to verify the presence and correct use of Form API provided by Drupal. We should analyze the way of using Form API, preferably using the documentation, and make sure that the forms are being created as directed.

The documentation specifies:

  • the cases where the use of a given field type is correct,
  • how to create the methods of validation,
  • how to use hook_form_alter,
  • how to create forms to be intuitive for the user.

SQL queries

Let's start with verifying the presence and correct use of the Database API provided by Drupal. It's equipped with methods providing security against attacks on the database. The correct use of API largely protects against attacks. We should particularly pay attention to whether input data filtering methods are used in the SQL queries. Drupal recommends using placeholders if there's a need to use input data, e.g., from a variable the value of which has been specified by the user in the form. Here's an example:

$foo = $this->getFormData(); $query = \Database::getConnection()->query(‘SELECT foo FROM {bar} b WHERE b.name = ‘ . $foo[‘name’]);

In the code above, we can see that the value 'name' from the $foo array is being assigned to the query without filtering. In such cases, I recommend using placeholders.

$foo = $this->getFormData(); $query = \Database::getConnection()->query(‘SELECT foo FROM {bar} b WHERE b.name = :name’, [‘:name’ => $foo[‘name’]]);

By creating queries in this way, we subject the variable $foo ['name'] to filtering, which will protect the query against SQL Injection attacks.

Filtering mechanisms

This means verifying the presence and correctness of the filtering data received from the user. We need to check that only TWIG is being used to render the variables in the templates, which by default filters the content of the variables and makes sure that they're safe. In the case of working with variables that are then used in translatable strings, we need to make sure that those variables are substituted for the appropriate placeholders. The plain text coming from the user should be filtered using the Html::escape() method if the user shouldn't be able to provide HTML tags in the text and the Xss::filterAdmin() function if they should be able to do so. If the user provides links, they should also be filtered.

Used for this purpose are the functions UrlHelper::stripDangerousProtocols() and UrlHelper::filterBadProtocol(). Filtering mechanisms are also applicable on the client's side. To clean up text in JavaScript, we should use the Drupal.checkPlain() function.

Sensitive data

We should check whether the code doesn't contain credentials or API keys. In some cases, we may come across the credentials left in the code of custom modules. Identifying them doesn't require much work.

Repository review

It's worth taking a look at the repository to search for sensitive information that may be stored in the files. The first step is to analyse the settings.php file and ensure that there are no credentials in it that would provide access to the database or other Drupal website components. Next, let's go over the environment variables' files and make sure there aren't any credentials in them. The credentials required by the environment shouldn't be part of the repository.

The next step is to check if there are no deeply hidden confidential files, for example – with SSL private keys or database copies or dumps. Sometimes the files that should never be in the repository get there by mistake. Some of them are, for example, database dumps or private keys. Identifying and removing them is recommended.

Analysis of the Drupal code – summary

In the third part of the series on performing a Drupal security audit, we've learned the ways of checking the code of custom modules and themes, we've audited the project's repository in order to make sure that no sensitive data was publicly available, and we've analyzed the elements that are worth paying attention to during the audit process.

Applying the tips I've posted in this article will make your application more secure. A code audit is a key element leading to better page security. It requires more time and knowledge than the update we covered in the first part and the correct configuration of Drupal we covered in the second part of the series, but the benefits of doing it are much more valuable than the time spent on it.

In the next part of this series of articles, we'll learn about external tools for automating the auditing process. It's the next step performed in a comprehensive security audit. Do you need help in performing such a task? Our Drupal support team has extensive experience in conducting audits.

Sep 02 2021
Sep 02

The world of technology is constantly evolving and strives to create new solutions, as well as to improve the old ones. Consequently, the life cycle of every software sooner or later reaches its inevitable end. Such a fate awaits the distinguished and still popular Drupal 7 with the end of its official support by the developers. This is a great moment to recall the novelties it brought in relation to the previous versions and to shed some light on what's next.

General information

Released on 5 January 2011, Drupal 7 was the successor to Drupal 6, obviously, and brought many awaited and – above all – necessary changes. Here are some of the most important ones.

  • The concept of entity was introduced, known from many other solutions. Hereafter, entities can be anything – from a user profile and a node, to things like a comment or a taxonomy term.
  • Support for multisite appeared.
  • Content Construction Kit (CCK) became a module in the Drupal 7 core.

In addition, there were many smaller, but no less important improvements, such as: improvement of performance and security, changes in hooks and API, reduction of system requirements, ability to create shortcuts, scheduling tasks using cron, and many, many more.

Drupal 7 end of life - change of date

Originally, Drupal 7 end of support was planned for November 2021. However, this date has been changed to 28 November 2022. Where did this change come from? As we may learn from the official information on this topic, the main reason for postponing it is COVID-19 and the impact it has had on the international market – especially on companies and their budgets. In practice, this means an additional year of support covering the security and development of patches for Drupal 7 websites. It also means extra time to move your projects to newer and dynamically supported and developed versions of Drupal.

End of support for Drupal 7

From the end of November 2022, no further official patches will be published. Therefore, if we don't update our pages to a higher Drupal version, we'll be left on our own and at the mercy of hackers, to whose attacks our page may become vulnerable. Of course, this isn't the only reason why you should jump to version 8 or 9, which I'll try to convince you of in the next paragraph.

Drupal 7 vs Drupal 8

The introduction of Drupal 8 meant a very big and significant change towards the development of the system. Let's take a look at some of the most important changes and improvements when compared to the previous version.

  • Drupal has been rewritten using the Symfony framework. For those unfamiliar with the topic, Symfony is one of the most popular PHP frameworks. Therefore, from the very beginning Drupal could boast that it gets a lot of support from the community and creators associated with Symfony. This change is actually so big, because the earlier Drupal versions weren’t based on any such powerful frameworks.
  • A new engine for creating templates has been introduced - the well-known and popular Twig (this is the result of switching to Symfony, where this engine is also used). This streamlines the work when creating templates, and brings the way of implementing them closer to modern standards, abandoning the previous themes and PHP templates.
  • The lack of a sensible text editor in Drupal 7 has been solved in version 8 with CKEditor - an extremely powerful and multifunctional tool for working with content.
  • The Views module has become a part of the system's core.
  • Drupal 8 brought almost 200 changes and patches that you can read about on Drupal.org.

You may also be interested in: 10 tricks to work efficiently with the Composer in Drupal 8

Then is the change from version 7 to version 8 or even version 9 (which you'll read about further down) a good idea? To put it simply: YES! From the very beginning, switching to Drupal 8 seemed like a necessary move. The number of novelties and possibilities introduced at that time by version 8 was stunning, and the obsolete solutions known from Drupal 7 were starting to be a drag in combination with the raging development and progress in the field of web development.

Then what is the cause of such a large number (about 560 thousand active installations - as of July 2021) of websites still operating on Drupal 7 and of the many years of support from the developers provided for such an old version of software (we'd like to remind you that Drupal 9 released in June 2020 is currently the default version)? It's all the result of how great a revolution Drupal 8 was and what great changes have been made to the very logic that underlies the entire system. The introduction of Symfony as the base framework for Drupal was a double-edged sword. Although it actually brought only good changes, it led to practically no compatibility with the previous versions. Upgrading from Drupal 7 to 8 couldn’t be done automatically, and sometimes even required rewriting the entire page from scratch. As you can imagine, this could be very problematic for systems maintained over the years, not to mention the cost that such a change could generate.

Today, however, we are already richer with years of experience. Upgrading from 7 to 8 doesn't have to be as titanic a job as it initially was. There are many tools on the market that can help us with the migration and make it easier.

Drupal 8 EOL - What’s next?

Let another fact be evidence for the popularity of Drupal 7: the official support for Drupal 8, its older brother, ends on 2 November 2021 – a year earlier. The reason for this decision is primarily that updating Drupal 8 to 9 is much simpler and often doesn't require any additional work from us. Hence, moving our website from version 7 to 8 is the first step to updating to the latest version that's being currently developed. Drupal 9 in relation to 8 is simply an evolution, not a revolution of the ideas behind the premiere of Drupal 8. For more information on this topic, you can visit the official page of version 9 and our post on the transition to Drupal 9.

End of life of Drupal 7 will be in November 2022, and of Drupal 8 in November 2021


Drupal 7 EOL - professional help

As we've already established that the transition to the latest version of Drupal is actually a necessity, and with the transfer of the planned Drupal 7 support end date, we've gained some additional time, I'll introduce you to this process. I'll try to distinguish two possible paths here: for those less knowledgeable on the subject and for the advanced users who want to learn about our methodology.

Transition from Drupal 7 to 8 for beginners

As already mentioned, the updating process isn't automatic here and requires at least basic technical knowledge and experience in carrying out similar migrations. If you don't feel up to it, we recommend that you contact the professional Drupal support team for help. Using the services of specialists experienced in this type of migration can significantly shorten the entire process, as well as dispel any doubts related to it.

Transition from Drupal 7 to 8 for advanced

Now we'll show you, based on our experience, how to handle such a process. First of all, it'll be easier for us to migrate the page to version 8, and after that – to version 9. We should avoid large jumps (i.e. from Drupal 7 to 9), because they may cause more needless chaos than necessary.

  1. Let's start by reviewing the available modules and making sure that all the ones we have we’re actually using. It's also important to first make sure that we understand the functionalities of the page in order to be able to fully translate them into the new Drupal version.
  2. Changing the version is a good time to clean up and redesign the layout of our page, which may be outdated.
  3. Custom modules need to be rewritten. There is no other option here but to simply rewrite the modules, following the new method of implementing them.
  4. As is the case with modules, rewriting the custom themes is also necessary. The introduction to the Twig template engine is a big change, and translating the old templates into this solution is fully obligatory.
  5. Drupal 8 has changed the way data is stored in the database, as well as its structure, so data migration is a must. Such modules as Migrate, Migrate Drupal, Migrate Upgrade and Migrate Plus will help us with this.
  6. THE MOST IMPORTANT POINT: backup, backup, backup! Before making any changes (let alone as crucial as this one), it's necessary to create a backup. It'll save you trouble in the event of an unforeseen failure during the migration. It seems trivial, but this issue is often underestimated.
  7. It's worth ensuring that our Drupal is updated to the latest possible version of Drupal 7. This should minimize any difficulties in transferring the configuration.

If we manage to migrate the website to Drupal 8, upgrading it to version 9 itself shouldn't cause any major problems. First of all, we need to replace the obsolete methods in our code with new code or just get rid of them. Drupal-check is one of the tools that can help us find such a code.

Aug 20 2021
Aug 20

Creating a website is a very labour-consuming process. It requires quite a lot of time and resources. However, the people involved in building webpages and applications noticed that some elements repeat at times. In order not to reinvent the wheel, they began to isolate the repeating elements as components. In this text, I'll present how the components can be used based on the example of the Drupal distribution Droopler and the Bootstrap library.

What are components?

Components are elements that are reusable in different parts of the website. They allow for fairly quick creation and easy maintenance of pages and applications. The additional advantage of components is that if a change is required, you don't have to modify every element of the page, you only need to make the correction in one place. The change will automatically appear in other parts of the site that contain this component.

Bootstrap library

Bootstrap is a set of tools and components that simplify the creation of websites and applications. Using this library may speed up your site building as Bootstrap includes ready-made solutions for creating adaptive templates, forms, tables, navigations, etc.

This library mainly contains the CSS and JavaScript files that implement various ready-to-use components. After connecting the library, by using specific CSS classes you can quickly and easily modify the elements on a page.

There are several ways to use the Bootstrap library in Drupal. One of them is to use a base theme on which you can build your own. The most popular base themes are Bootstrap – which is based on the third version of the library, and Barrio – which was built on the basis of Bootstrap 4/5.

Bootstrap components in Droopler

Droopler is a Drupal distribution designed to quickly build webpages. It differs from other distributions in that it provides a ready-made website out of the box. You just need to add your own content to it.

Droopler is built on the basis of the Barrio theme, so it has all the benefits of Bootstrap. There are several ways to use the components of this library in Droopler. The first and easiest is adding the necessary elements to the content of the blocks.

When adding a new block, you should place the HTML code with the classes specified by the Bootstrap documentation in the section for entering the content. In order for the entered code to be recognised by Drupal as HTML, before entering the content you must activate the "Source" mode using the button in the field panel. After adding the HTML code, you need to turn off the given mode.

Adding the HTML code with the classes defined in the Bootstrap documentation


In this case, after saving the block, we get two buttons. The shape of the given buttons was determined using the "btn" class, while the background and text colours were assigned using the "btn-primary" and "btn-secondary" classes.

The buttons that are created after saving blocks with a new HTML code in Droopler


The second way to use Bootstrap components in Droopler is more difficult. It consists of adding your own theme based on the Droopler theme and modifying the source code. To do this, you need to use one of the starter kits found in the Droopler base theme directory, and then you can create your own solutions using the Bootstrap components.

I've shown you how to add basic buttons using the Bootstrap library. Now I'll present a few more examples of advanced components.

Dropdown menu

A dropdown menu is a very useful component for a website. It allows you to store and display information and links in a fairly compact block, which makes it possible to efficiently use the web page's space and allows you to include more information. This component consists of two parts: a block with elements, which is hidden by default, and a button, which – when pressed – makes a particular block appear.

A dropdown menu - a Bootstrap component in Droopler


In the block itself, you can put headers, links, which in turn can be active or disabled. These parameters can be set using CSS classes provided by the Bootstrap library.

Progress bar

A progress bar is another useful element of a website. It allows the user to immediately see the progress of the performed activity, which improves the user experience.

A progress bar, a Bootstrap element that shows a progress of some activity


As with other components, you can modify the style, colour and other parameters of a progress bar.


Bookmarks are one of the menu types used on a website. They are useful for switching between the contents of pages, allowing the user to see more information in a smaller space.

The tabs are a Bootstrap component which allows switching between content on a page


The bookmarks created with the Bootstrap library may contain active and disabled links, as well as the already mentioned dropdown menu.

Bootstrap Components - summary

Using the Bootstrap library components to build a webpage is a very effective approach, because it allows you to easily build and maintain the pages. I've shown a few examples of using components in Droopler, a Drupal CMS distribution. You can find more information about the available components in the documentation on the Droopler demo page.

Aug 10 2021
Aug 10

In the first part of the series on Drupal security audits, we described how to review modules and libraries. However, modules and dependencies will be useless if any user will be able to see our custom routing where we display all the client information. Therefore, in this article we'll look at the configuration of our website. Correct configuration is one of the key elements affecting security.

Checking the Drupal configuration

For this part, our list will include checking the role permissions, access to the Drupal views and routings, among other things. We'll also verify the correctness of the text formats configuration and perform other checks to find the largest number of potential vectors of attack on our application.

Role permissions audit

By going to /admin/people/roles, we’ll see the list of all available roles.

The list of all available roles on our Drupal website, visible on the Roles page


In the list on the right (the OPERATIONS column), after clicking we can select the edit permissions option, which will redirect us to the page /admin/people/permissions/[machine_name_of_the_role] (example for the Anonymous role: /admin/people/permissions/anonymous). After going to the permissions edit, Drupal will list all the possible permissions that have been granted for the selected role.

After going to the permissions edit, we can see all permissions assigned to a particular role on a Drupal website


To verify the permissions, we should first consider what task is assigned to the role. We need to ask ourselves whether role X should have permission for action Y, for example: should the content editor role be able to edit all views? If the answer is no, the permissions should be restricted.

Full knowledge of the project is required for a permissions audit. If we find a permission that we believe a given role shouldn't have, we should only inform in the audit report about the possibility of the role having optional permissions. We'll provide more information on how to create a good report in one of the next articles in the Drupal security audit series.

View permissions audit

After auditing the roles, it's time to take a look at the views. They're all listed under /admin/structure/views.

A list of views available for a particular user, located on the Views page in Drupal


Our first task, in this case, will be to enter into the edit of each view that provides routing. We need to find the PAGE SETTINGS section, and more specifically – the Access option, which should only intentionally be set to "Unrestricted".

The Access option in the Page Settings section which is worth checking at the beginning of the views permissions audit


As is the case with the roles, when auditing the view permissions, we should ask ourselves: what restrictions should be put on the X view? If the view should be accessible to everyone, it's good practice to use a restriction which requires having permission to access the published content. If any of the views have no restrictions or we find them to be too moderate, we should inform about it in the report.

Audit of the routing.yml files in custom modules

When it comes to the routings created in custom modules, the audit looks similar. We should review every *.routing.yml file to ensure that every routing has the appropriate level of security. Here is an example of a new routing declaration

A new routing declaration can look this way


In this case, every user with the access content permission is permitted to access the /machine_name/transliterate page. It's also a good practice in this case to define a minimum access level for every access content routing.

Text formats audit

The path /admin/config/content/formats contains all the text formats available on the page. In this case, the audit will consist of checking, for example, whether it isn’t possible to insert JavaScript code using a given text format or whether it isn't possible to link an image that will be downloaded from another page. It's also important for the list of possible file extensions not to allow uploading files with unsafe extensions if it isn't necessary. Of course, we report the configuration errors – the risk level depends on the type of error.

Error logging audit

There is the Error messages to display configuration option on the /admin/config/development/logging page. It's used to set the error display level. This option should be set to None on the production page. If this option is set to a variant other than None in the production environment, we report it as a low-level threat.

The Error messages to display option in Drupal should be set to None


Basic login audit

There are two ways for the login panel to inform if the user trying to log in provided incorrect data. It may give a brief answer such as "data is incorrect", or give one piece of information when the login is incorrect, and another when the password is incorrect. In the last case, we're dealing with a vector for a brute force attack. The attacker may first storm the logins and then the passwords – thus gaining access to the user accounts.

Another aspect worth checking out is the password policy. It's a controversial topic, since some propose to force a password change periodically, and others say that the password should contain at least one uppercase character, one lowercase character, one digit and one special character. Some people combine both these rules, and users end up creating passwords like July2021! which meet all the requirements. My personal recommendation in this case rules out the necessity to change the password from time to time. Determining the complexity of the password is recommended, but the most important thing is its length - the longer the password is, the more time it'll take to crack it. The password policy is an issue that depends on the type of project and must be analyzed individually. In the case of a weak password policy, you should report it as a threat with a level depending on how bad the policy is.

Forms audit

The forms should be protected against spam. They should be created using the Drupal API where possible. Check if the forms are protected against spam and if their validation doesn't allow entering incorrect or dangerous data. If you find an incorrectness in the form's configuration, you should be reported – the risk level depends on the situation. There'll be a different level of risk for a potential SQLi, and for the possibility of entering incorrect data – for example in the select list.

Additional recommendations

There are Drupal modules that increase the security of our application. One such module is Security Kit. Thanks to it you'll reduce the likelihood of using the website's security gaps. This module offers Anti-XSS, Anti-CSRF, Anti-ClickJacking, and other security measures. We recommend reading the linked post and considering the installation.

Security Review is a module that can help with a Drupal security audit. It uses automated security tests that help with performing the audit.

This module:

  • checks the file permissions,
  • performs a file formats audit,
  • performs an audit of the options responsible for reporting errors,
  • performs an options audit, in which we determine which file extensions can be uploaded (e.g. to be downloaded in a blog post),
  • monitors database errors in order to detect a potential attack,
  • monitors the login panel for the same purpose,
  • checks the configuration of the trusted hosts file,
  • checks the view permissions.

Security Review is recommended as it can speed up the process of auditing the page.

Drupal configuration checked - what's next?

In this part of the series on performing a Drupal security audit, we've learned the ways of checking the Drupal configuration. We are familiar with the configuration options that can open attack vectors and we know what the recommendations are for closing these vectors.

Acquiring the knowledge provided in this post has allowed you to better understand that a correct Drupal configuration is as important as keeping it up-to-date. A configuration audit is another of the activities that we perform during a security audit - our Drupal support team recommends a comprehensive configuration check during a security audit.

In the next part of this series of articles, we'll deal with the code and learn about the basic ways to audit it. We'll present the ways of analyzing modules and themes. We'll take a look at what's in the repository. Are there any passwords, keys in it? Or maybe the entire database dump?

Aug 04 2021
Aug 04

It isn’t enough for the architecture of our web page to be well-designed – the appearance is also important! Drupal comes to our aid when it comes to building websites quickly. Can we count on similar help when creating a modern look? We'll tell you a bit about the extensive library called Bootstrap, which offers a wide range of ready-made components.


The year was 2011, when a group of Twitter programmers, headed by Mark Otto and Jacob Thornton, introduced the world to an extraordinary tool that was to revolutionize in the future the process of creating a graphical interface – not only for websites but also for applications. They named it Bootstrap and decided to release it under one of the most liberal open source licenses – MIT. Currently, the latest version of Bootstrap is 5.1.

Bootstrap is an open-source tool that provides developers with a wide range of ready-made components

Source: Bootstrap

Bootstrap is a library of cascading style sheets (CSS), which uses ready-made HTML and JavaScript solutions. It provides predefined styles for the commonly used elements on web pages, such as text, headings, buttons, navigations, tables, links, and more. It also ensures that the elements look good in the mobile version. Everything is based on a grid structure made of up to 12 columns. The thing that makes Bootstrap so popular – in addition to the obvious benefit of having hundreds of predefined classes, so we don't have to worry about spacing and struggle with the composition of our divs – is its documentation. It's impossible to get lost in it. In terms of topics, it covers styling support and its variants for all elements.

Drupal and Bootstrap - best friends

The Drupal community didn't pass by indifferently such a widely used tool and created two themes that allow integrating the Bootstrap library with Drupal.

Bootstrap theme

The basic theme that allows you to use the power of Bootstrap in Drupal can be downloaded from the Drupal.org page. It's worth mentioning, however, that it currently supports the library version 3, but is compatible with all Drupal versions from 7 and up.

Installing the theme can be done using the command line in composer:

require 'drupal/bootstrap:^3.23'

or the admin panel under the path /admin/theme/install.

Installation of the Bootstrap theme in the admin panel in Drupal


The next step is enabling the theme in the Appearance section of the admin panel or using the drush command.

theme:enable bootstrap

 (if we just want to enable the theme)

config-set system.theme default bootstrap

(if we want to enable the theme and set it as default)

Enabling Bootstrap skin in the Appearance section


This ready-made theme has many options for global configuration of individual components that make up our page – both static (forms, tables, containers) and dynamic (modal windows and pop-ups). You just need to go deeper into the settings under /admin/appearance/settings/bootstrap. We can already notice a significant difference in the appearance of our page.

Below you'll find the comparison of my test homepage. If you use the Bartik theme, you'll get the impression that suddenly the page components are mixed up and the whole thing looks "broken", but don't worry. In most cases you just need to slightly adjust the styling of the existing elements. Go to Structure -> Block layout and assign the correct regions to the blocks. Here I present the look of the Bartik theme after it's been adjusted accordingly.

The default Bartik skin in Drupal before and after enabling the Bootstrap skin


Barrio theme

The process of installing and enabling the Barrio theme is the same as before. The main difference between Barrio and Bootstrap is the version of the library they use. For Barrio it's Bootstrap 4 or even 5 (for those who'd like to test version 5.0.2 of Bootstrap). The command to download Barrio via Composer looks like this:

require drupal/bootstrap_barrio

What we get in both cases are more ready-made templates that require further configuration and styling according to our needs, rather than a full, styled solution. They should be treated as the base themes which we'll inherit from in our sub-theme. This is also important in terms of future updates.

Creating own theme

Creating our own theme, which'll be based on the Bootstrap library version 3, 4 or 5, can be carried out in two ways:

  1. by using the starter kit available for both themes – under themes/Bootstrap/starterkits and themes/bootstrap_barrio/subtheme (the fastest and easiest option) respectively.
  2. using the starter kit available with both themes, but without using CDN (Content Delivery Network) (advanced option, requires a CSS preprocessor, e.g. SASS, to compile styles, and the Bootstrap library must be downloaded locally).

The first option only requires us to copy a ready set of files to a new folder in the themes path and rename the files from THEMENAME or bootstrap_barrio_subtheme to the machine name of our theme. You should also check the .theme, info.yml, schema.yml, color/color.inc and js/global.js files and make similar changes within them as well. Thanks to CDN, the Bootstrap library doesn't have to be downloaded locally.

From now on, we can start working on the appearance of our page, define the typography or colour scheme. In the theme settings, you'll find many options to modify the original configuration without having to modify the css or sass files. However, in most cases it turns out to be not enough and it's necessary to overwrite files and create templates in the .twig format.

Droopler – a high-end Bootstrap template

As a free Drupal distribution, Droopler was created with the idea of fast and comprehensive website creation in mind. Therefore, it contains a set of ready-made components and functionalities that most pages use and – thanks to its modular structure – has a highly configurable SCSS preprocessor. To perform the rest of our activities, you can install Droopler in the way described on the linked page.

Ready style files for all components and page structure elements in the SCSS folder

Bootstrap is an integral part of Droopler. The Droopler theme uses Barrio – but unlike Barrio it provides a ready-made theme with styles, not just a template. In the scss folder, we can find ready-made style files for all components (mainly the available paragraph types, forms, etc.) and page structure elements (headers, footer, etc.).

Droopler subtheme – how to use it?

The Droopler theme also has a starter kit for creating your own sub-theme named STARTERKIT_CSS and STARTERKIT_SCSS, where we can easily modify the predefined variables. Let's check what it looks like when you want to use SCSS:

Droopler's sub-theme file structure with _base_theme_overrides.scss and _bootstrap_overrides.scss files


The style.css file combines the entire SCSS code from the main droopler_theme and our theme (files located in scss/config). Print.scss also combines the entire SCSS code for printing both themes. In the libraries subfolder, we can put our additional SCSS files, which we then have to add via @import in the style.scss file. When adding them, it's worth keeping the division into components and layout – as in the base theme.

You can make any changes to the settings of the Bootstrap library itself or the droopler_bootstrap base theme in the configuration files:

  • _base_theme_overrides.scss
  • _bootstrap_overrides.scss.

In the case of both files, we have at our disposal a quick guide covering the available variable modification options in the form of an extensive comment. All we need to do is uncomment the selected variable and substitute it with our value. The complete list of variables used in Bootstrap that we can overwrite can be found in the library's _variables.scss file. As it's downloaded automatically by defining the repository in the droopler_theme theme's package.json file, it can be found in the node_modules/bootstrap folder.

Suppose we want to change the colour of the submenu border that appears under the $dropdown-border-color variable in Bootstrap. In the base_theme_overrides file, we define a new colour, for example $color-example-1. Then, in the bootstrap_overrides file, we uncomment line 34, where the value for the border colour is defined. We substitute it with our newly created variable there.

Changing the color of the sub-menu border


You must run the compiler for the changes to become visible. In the case of Droopler, the developers also took care of it. There is a ready-made gulpfile.js file in the theme package. We just need to run the gulp watch command in the theme's directory (both droopler_theme and droopler_subtheme), so that any changes we make to scss, js or other source files are included and compiled automatically. The effect? Let's find out!

New color of the sub-menu border in Droopler


Our border is now pink. We can do the same for all variables.


Bootstrap is a powerful tool connecting graphic designers and developers. On the one hand, it allows designers to familiarize themselves with the website's architecture and the specialized terminology (e.g. a 2 column-wide sidebar instead of a narrow window that is glued to the edge of the page), on the other – it saves time of the developers who only need to use the correct class to transform a regular link into a button.

Integrating Drupal with Bootstrap may seem relatively complicated, but remember that the available Bootstrap and Barrio themes are only templates, and in the end we'll still have to assign appropriate classes for all types of links we use. In Droopler, this part is already taken care of – we only need to change the block layout or modify the existing Twig templates. We can create and implement a new colour scheme in a few moments by editing a single file – the effect is guaranteed.

Jul 22 2021
Jul 22

A security audit is the process of identifying security threats that can lead to unauthorised access to content, data leaks, bypassing the security, and other dangers. In the first part of the series on conducting a security audit, we'll focus on the overview of the Drupal module versions that we use at Droptica for this purpose, as well as on PHP and JavaScript libraries.

Drupal security audit

At Droptica, we make every effort to ensure that the solutions we provide are as safe as possible. We use the tools provided by the Drupal community, such as the Security Review module, to optimize the process of detecting the most popular security errors. We also use the Security Kit to make the project we're working on more resistant to attacks. You can learn more about the functionality of these modules in the linked posts, and the information on their operation will be useful in the following parts, in which we'll talk about the Drupal configuration review and code analysis.

Checking the versions of the installed Drupal modules

Updating modules and libraries is the simplest activity that we can perform to improve the security of our application. Drupal provides a view listing all the modules, which additionally indicates whether a given module is up-to-date, and if it isn’t – whether the update contains security fixes.

To check if the modules are up-to-date, go to /admin/modules/update

Checking the versions of Drupal modules as part of security audit

In the screenshot above, you can see that some of the modules need updating. Of course, in such cases we always recommend that you update all possible modules. If any of the modules contain a security fix, the update is required to ensure a high level of security for the application.

In the case of Drupal, the information about whether a given module has a security flaw is made available to the public when the author of the module releases its patched version. Module authors usually try to hide which code has been changed to patch a security flaw, but this always means that the attacker just needs more time to find a way to cause the bug and exploit it. Time is important, so you should keep track of security updates regularly, not only during a Drupal security audit. As we mentioned earlier, this is one of the simplest steps we can take to ensure a higher level of security for our application.

Patches review

When updating the Drupal modules, you should also check if a patch has been applied to a given module. If so, we proceed as follows:

  1. We check whether the patch was created by the community and if it concerns a specific issue on drupal.org. If so, we look for the issue that the patch is from. It's possible that the patch has been applied to one of the newer versions of the module. In such a case, we recommend updating the module and removing the patch with the information that the code that fixes the bug or adds a given functionality has been applied to the official, newer version of the module. If the patch hasn’t yet been applied to the newer version of the module, we still recommend updating and testing if the latest version of the patch serves its purpose.
  2. If the patch wasn’t created by the Drupal community, but is the result of working on the project, we still recommend updating the module. In this case, however, ensuring the correct operation of the patch lies with the people responsible for the custom code of the project. After updating, you should check whether the patch works as intended. If not, we recommend introducing appropriate fixes to the patch which will ensure its correct operation on the latest version of the module.

PHP libraries review

The next step will be reviewing the used PHP libraries. To list them, we can use the composer show command or the local-php-security-checker package. We recommend the latter solution because it significantly speeds up the process.

Result of the composer show command during the review of the used PHP libraries

Result of the composer show command.

If you choose to install the local-php-security-checker package, follow the guidelines in the README.md file.

Result of the scan using local-php-security-checker during a Drupal security audit

Result of the scan using local-php-security-checker.

There's also the little-known Drupal Composer Security Checker module that uses the security-checker package. Currently, this module doesn't fulfill its task and the security-checker package itself isn't actively developed (since January 2021), therefore we'll focus on the local-php-security-checker package itself. If you find a security risk, our recommendation will be to update the library, of course – as in any case. An audit of the PHP libraries should be carried out regularly, the same as in the case of the Drupal modules.

JavaScript libraries review

The next step will be to check if the used JavaScript libraries are up-to-date and if they contain security fixes. To do this, you should review the library directory and the used package.json files.

In the case of the library directory, you need to check the version manually. In the case of package.json, we use the npm-audit command.

Result of the npm-audit command checking the package.json during the JavaScript libraries review

Result of the npm-audit command

The npm-audit command will list all known vulnerabilities, determine the threat level, package, dependencies, package path, and show a link with information about the vulnerability.

The npm-audit command shows all vulnerabilities in the JavaScript libraries

If you find a vulnerability, as always we recommend the update. JS library scans should be performed routinely, more often than a comprehensive security audit.

Improving the Drupal security - further steps

In this part of the Drupal security audit cycle, we've learned how to check whether the used versions of the modules and libraries are up-to-date and don't contain known security bugs. We also understand how to proceed if there is a patch available for a module – both when the patch comes from the Drupal community and when it was prepared by the developer working on the application.

Acquiring the knowledge provided in this post is the easiest way to improve the security of your application. Checking the versions of the used solutions is the first step that we perform during a security audit - our Drupal support team recommends periodic checking for updates. In the event that an update containing security fixes is released, we recommend that you perform an update as soon as possible.

In the next part of this series of articles, we'll get to learn more about the Drupal configuration aimed at increasing the security of our application. We'll also learn how to reduce the number of attack vectors and we'll find out more about the modules that'll help us with this.

Jul 16 2021
Jul 16

Many people probably wonder why system creators recommend regular updating to the latest version and why we are informed at every step by pop-ups that the latest patch or other fix has been released, sometimes changing only a few lines of code in the software. Using Drupal as an example, I'll try to explain why it's so crucial. Although the system works properly, it can contain many errors and surprise you with unstable work.

Why should you update your systems?

The first and most important reason why you should carry out regular updates (including the ones related to Drupal) is the security of the system itself. If the authors or the community discover a software flaw, with an update they can immediately fix it and protect users from threats (such as hacker attacks) that lurk at every step.

In the case of Drupal, new versions of the software not only protect you against dangerous attacks, but may also provide new functionalities. Usually options of this type appear in the "major" versions, such as 8.2, 8.3. You can check the update plan at any time on the roadmap on the Drupal website.

System personalization is important for every user and thanks to an update you can gain new modules or additional options that'll make your work easier. It's also worth keeping in mind that regular updates protect you from unnecessary programming work in the future, because the older your Drupal version is, the more difficult it is to install the latest update. Another advantage is the continuity of the webpage's operation, because you avoid time-consuming failures and minimise the risk of unstable system operation.

When is it worth performing an update?

As we've already mentioned, it's best to perform updates on a regular basis. As soon as you receive a notification about a new version or find out about it from another source, you should plan that update in the near future.

In the case of Drupal, updates are released approximately twice a month. You should also remember that monitoring the date until which support for a given version of Drupal is provided is sometimes a matter of several years. Therefore, you should bear in mind that every version has its "end of life" planned, and usually a migration to the newer version should be performed when updating. If you want to protect your system from hacker attacks and downtime, as well as keep the website running smoothly, you should remember to always use the latest version (or the one that is supported).

In addition, there are also updates of the modules themselves (depending on which ones are currently installed) and the PHP itself. In the case of modules, you don't always have to act so quickly, because when they are released, the information about what exactly has been fixed and who is at risk is provided. If the given problem doesn't concern you, you can do it at a time that's more convenient for you. You should pay attention in the case of PHP - it's worth acting quickly in this case, especially if the new release fixes security holes from the previous version.

To sum up, when you don't have time to install the latest update (such situations, unfortunately, sometimes happen), try to use a version that's currently supported. In the case of modules, you can take care of the ones you use most often first. This will ensure stress-free work and the certainty that you'll always be able to count on quick help in the event of unexpected errors.

Drupal update - upgrading to a higher version

A Drupal update within the same major version usually runs smoothly and doesn't cause many bugs. However, if you change major versions of Drupal, updating may be much more difficult.

Upgrading from Drupal 7 to 8

The update from version 7 to 8 can't be performed automatically, unfortunately. In most cases, you need to write the page from scratch. Drupal 8 has significantly changed the way content and configuration are stored in the database. Therefore, the database and other files must be transferred to the new page based on version 8. The configuration data include content types, user roles, and field definitions. You must also remember that not all modules have automatic update paths. Manual code tampering or custom migration will sometimes be required.

The structure of the themes has changed compared to version 7. This is another thing that needs to be rebuilt for the content to display properly in version 8. To facilitate this task, it's best to obtain the appropriate tools from the official Drupal website:

Another thing that'll help you migrate is an analysis of the Drupal modules. You need to determine which modules are most important to you (preferably in the form of a list), and whether their installation on Drupal 8 is really necessary. Also, remember to update Drupal 7 to the latest version. This'll make it easier to transfer the configuration and content data. The last step before the migration is to back up your current page, based on version 7. If anything goes in the wrong direction, you'll have a guarantee that you won’t lose the page and data.

Upgrading Drupal 7 to 8 is a complicated operation, but it brings many benefits.

  1. Lots of new features and modules have been added to the Drupal 8 core, e.g. Media and Layout Builder.
  2. Drupal 8 has access to more modern technologies - it uses more modern tools that facilitate an editor's work. Thanks to this, the configuration is easier and better adapted to people who are just starting their adventure with this CMS.
  3. In Drupal 8, part of the core is the Views module, which easily presents the added content to you in many different ways. In addition, the main page itself is a separate view, therefore you can easily manage individual elements.
  4. The core also includes the modules that provide new field types (such as phone, e-mail, link, meta tags, entity reference and contact forms).

In addition, Drupal 8 is much better suited for larger pages than Drupal 7, because it can be optimized (it has a much more advanced cache system, controlled by tags and contexts), which makes it smooth and fast to work with. It's based on the components of the Symfony framework, which is considered in the world of PHP development to be the best solution for creating complex applications.

Upgrading from Drupal 8 to 9

Drupal 9 doesn't differ significantly from version 8. One important piece of information is the upgrade to Symfony 4, which ensures compliance with the latest standards - thanks to this you can program in accordance with the latest specifications. Besides, Drupal 9 is an improved variant of the previous version. Some of the old code has been removed, Symfony and Twig have been updated, so you can be sure that the system will always work effectively and without any problems. The quick and easy update between releases (i.e. switching from 8 to 9) has also been kept. Also, the modules' updates will not require many additional changes. You should also keep in mind that Drupal 9 uses PHP 7.3 or higher versions.

The migration to the latest version will certainly require you to verify the application's code. You should remove the items marked as "deprecated" from it. You can use the drupal-check tool for this, which will automatically track down the obsolete code fragments. Then you can proceed with an automated process, the execution time of which depends on the page, and which will provide you with the latest version of the software.

How to test the system after the update?

One of the most important steps you should take after any software update is to test the introduced changes or the entire application or system. There are situations when an update is associated with data loss, system crash or unexpected errors. In the case of Drupal, you can, for example, use smoke tests. They allow you to check whether all subpages are displayed without critical errors. Another option is any visual tests that compare the previous look of the page to the new one. It would also be necessary to verify the operation of individual forms and modules and check whether the data entered on the pages is assigned to the correct fields.

To sum up, you should check the website both visually and functionally. Technically the page should work fine. You can correct minor changes to its appearance later.


Software, whether it is for a web page (as in the case of Drupal) or an operating system or other application, should be updated regularly. This ensures the support of the producer or creators and may protect you from any external attacks. In addition, you often have at your disposal new functions, modules or improvements that can significantly change your comfort of working with a particular system.

If you aren't sure how to update your CMS's version, find out how we can help you with Drupal support.

Jul 08 2021
Jul 08

Together with the contact page, the services page is one of the key parts of a website. It's also one of the basic elements of an effective business website. Presenting the scope of services is usually the main purpose of its existence. We'll show you step by step how to create a services page in Droopler - a Drupal distribution.

Pages created using ready-made components

Droopler is a website builder based on predefined components. Thanks to a set of ready-made parts, it's good for building company websites for organisations of all sizes. We can easily create with it a home page and each subpage. Depending on the needs and preferences, we can use photo and text components, a gallery, a contact form, emphasise some significant numbers or direct the users to other subpages with more detailed information, such as the offered services.

Building a services page from scratch

We'll start building a services page by creating a new subpage. To do this, after logging in, select Add content from the Content menu and then Content page.

Creating a services page from scratch in Droopler, a Drupal distribution

In the displayed view, we enter the title of the page. It'll be Services in our case. We also add "Teaser Image" and "Teaser text". In the options on the right, we select Provide a menu link, which will make the link to the new subpage appear in the top menu. We also enter the text that should appear as a link in the menu. It'll also be Services in our case. After filling in these fields, we deselect the Published checkbox so that our subpage isn't visible to visitors for this moment. We'll only publish it when it's finished.

Adding a title, teaser image, and teaser text for a new website in Droopler

Finally, we click Save and see this:

A view after creating a new services page in Droopler


Sidebar Image

Now we can start adding components. To access the library of available items, we click the "+" in a circle button. We'll see a menu with the available options. The first item we choose will be Sidebar Image.

The library of components available in Droopler


We select this paragraph and start filling in the fields. First, we enter the header (this will be the title of our subpage) and choose its type - H1.

Filling in the fields of the new paragraph Sidebar Image in Droopler


We add a photo and enter the text describing the subpage.

Adding a photo to a new services pageAdding a text describing a new services page


In the options found in the right tab, we choose which side the picture will be on. We select Right and click Save. The first component (section) of our services page is ready!

In the paragraph settings, we select where our image should be displayed on our services pageThe look of the ready Sidebar Image component


The next section will consist of links to individual services. To add this section, we'll start by selecting the Group of text blocks component.

Selecting the Group of text blocks component in Droopler


As in the case of the previous component, we enter the title and select the header type (this time it'll be H2).

Filing in the title and selecting the header type for the Group of text blocks


Below, we also enter the text that describes the given section:

The text describing a particular section of the Group of text blocks component in Droopler


The next step is adding the 4 tiles which are the links to individual subcategories of the subpage. In order to create them, we select the second Items tab and click Add single block text.

Adding the tiles which will serve as the links to the specific subcategories of the page


We enter the title of the tile and select the photo which will be its background.

Filing in the title of a tile which will be in the Group of text blocks paragraphChoosing a background for the tile from the Group of text blocks paragraph in Droopler


In the Call To Action subsection we enter the subpage which the tile should link to (in the format "/" plus "subpage name", e.g. /boats), as well as the link's text.

Filing in the URL address of a subpage to which a new tile has to link to, and a text which will be displayed on a link


We prepare the other 3 tiles in a similar way. When it's ready, we click Save and we see this:

The ready tiles in the Group of text blocks component in Droopler


Now it's time to embellish this section. Therefore we go to the paragraph's settings by clicking on the pencil button:

After clicking on the pencil button, we'll go to the Edit paragraph page


In the settings, we change a few fields:

Embellishing the Group of text blocks component


In the options for each of the tiles, we select:

Selecting the options for each of the tiles


We click Save and we have a ready section with subcategories for the services we offer.

The ready section with subcategories of an offer on a website built in Droopler


Group of counters

We move on to the next section of the page, that is a counter with interesting figures regarding the company. We'll use the Group of counters component.

Adding the Group of counters paragraph to the services page


Similarly to the previous sections, we choose the title, header type and background photo.

Setting the title, header type and the background photo for the Group of counters paragraph


In the Items tab, we add individual values by clicking Add single counter and entering a digit and a text. We create 4 such elements and click Save.

Adding individual values to the Group of counters component in Droopler


The finished section should look like this:

The ready section Group of counters on the services page


Text page

The last element that we'll add to the services page will be a call to action. We add this simple section using the Text page component.

Adding the Text page component to the website in Droopler


As in the case of the previous steps, we select the header, "long text" and define the button.

Defining the details of the button that will be in the Text page paragraph


A ready services page in Droopler

The services page is finished. We only have to select Published in the selection field in the main options of the subpage. Now everything is ready and available online for the visitors of our website.

Publishing of a new services page

The whole Services subpage should look like this:

The ready services page in Droopler


You can see the created subpage in the Droopler demo. We build other subpages in a similar way. We encourage you to experiment with the options and different components. The multitude of available possibilities allows for personalising the page in a simple and quick way, without the need for coding.

Jun 24 2021
Jun 24

Droopler offers the ability of building a professional webpage using ready-made visual components. This website builder can also be customized to your individual needs. In the text below, we’ll present some examples of pages created with Droopler.

Meet Droopler - a Drupal distribution

Droopler is a Drupal distribution – the version of this content management system extended with add-ons that are configured in such a way as to meet the business objectives of the web page right after installation. Thanks to utilising modules such as Paragraphs and Geysir, it can be used as a page factory, e.g. for landing pages promoting products or for various language versions of a company website. Other advantages are the built-in SEO support and the appearance of the pages adapted to mobile phones and tablets.

What are the benefits of choosing the right distribution? There are many of them, but the most important ones are the following:

  • you don’t have to browse, select and install every module separately, which shortens the time needed to build a page, and it also starts to earn money faster;
  • its further development or modifications are possible to perform; you can do some changes by yourself, whereas Drupal developers can help you implement individual solutions.

In the case of Droopler, another advantage is the ability to use a wide range of paragraphs (because that is another name for components). You can learn more about them in the documentation of this tool. Below, we present the use of these elements on examples of specific pages.

Portamet - photos catch the eye

The website of Portamet, a company operating in the carbon steel and glass products industry, uses many of Droopler's visual components. When browsing this site, it's impossible to ignore the paragraphs devoted to individual projects, business solutions and realizations. The page’s author used the Tiles Paragraph component, thanks to which you can put text on one side of the screen and photos on the other. Such a solution catches the eye. Moreover, when you hover the mouse cursor over a graphic element, its title is highlighted, and when you press it, a larger view opens. Then if you want to present your portfolio in an attractive way, it’s worth taking a look at the Portamet website and see the solutions used there.

On the Portamet website, we can see the Tiles Paragraph component from Droopler

Source: Portamet

EKO-HOME - products’ showcasing

Still on the subject of presenting one's own offer, the author of the page of EKO-HOME - a manufacturer of external roller shutters and gates - in addition to the already mentioned Tiles Paragraph, used several other components. The Sidebar Image Paragraph deserves particular attention. It highlights a single photo, next to which there's a space for a description.

The element Sidebar Image Paragraph visible on the EKO-HOME website built with Droopler

Source: EKO-HOME

At the bottom of the page, you can see logos of the company's partners, presented in an interesting way. Instead of a static list, there's a dynamic presentation within which the graphic elements move automatically. You can also scroll through them by pressing the arrows. Such an effect can be achieved using the Carousel Paragraph.

An interesting usage of the Carousel Paragraph in the section with partners' logos on the EKO-HOME website

Niewczas Strawberry Plant Nursery - customized use of Droopler

We’ve already mentioned photos, now let's start with a movie. The strawberryplant.eu website, belonging to a company dealing with professional strawberry cultivation, uses the Sidebar Embed Paragraph with a video in the About us section. To upload a video from YouTube or Dailymotion, you just need to copy the iframe code to Droopler.

The website of Niewczas Strawberry Plant Nursery uses the  Sidebar Embed Paragraph with a video

Source: Niewczas Szkółka Sadzonek Truskawek

Another ready-made Droopler solution used on this page is the Counters Paragraph. It's an attractive form of presenting numbers that are meaningful for the company. The most important thing is that they appear dynamically.

The Counters Paragraph component from Droopler used on the strawberryplant.eu website

The Side By Side Paragraph also looks very nice. This component allows you to achieve the effect of several alternating blocks of text and graphic elements.

The Side By Side Paragraph component from Droopler is perfect for the alternating blocks of graphic elements and text


This highly attractive website is also an example of extending Droopler's capabilities with the help of a developer. The next paragraphs appear as you scroll down the site while browsing the home page. On the other hand, the subpage with the offer, besides of the blocks with graphic elements, attracts attention with the filtering option. The result is a narrower display of these blocks. There's also the Blog section with a very clear content layout and visible extracts of articles.

We encourage you to spend some time on this page, because it can be a unique inspiration for creating your own site.

Be Happy Music Club - video as the most important part of the page

In the previous example, we started with a movie, now we'll do that again, but a bit differently. That's because a video fills the entire Banner Paragraph on the home page of Be Happy Music Club - an organisation whose mission is to improve the well-being of disabled children and to promote social integration through music programmes. Probably due to the noble objectives of the site, the video was put at the beginning, and the slow-motion playback successfully strengthens the effect and attracts attention.

The video in the Banner Paragraph plays a main role on the Be Happy Music Club website, built with Droopler, a Drupal distribution

Source: Be Happy Music Club

We haven't yet covered the Gallery Paragraph, which appears below. Of course, the number of photos in this component is unrestricted, and in the case of this page the authors also added a button. We mention it because, depending on individual needs, it's sometimes worth including such a call to action under the presentation of graphic elements.

The Gallery Paragraph component with three photos, texts and a call to action button

At the bottom of the page, we can see the Counter Paragraph we already know, although in a narrowed version (yes, you can define the number of individual counters).

The Counter Paragraph on the Be Happy Music Club website created in Droopler, a Drupal distribution

We'd also like to highlight the Our People section and go back to the subject of photos. Not only the Gallery Paragraph, but also, for example, Text Blocks can be used as a component for team presentation (and not only). The upside is the ability to put text under the selected photo.

The Our people section on the Be Happy Music Club website, based on the Text Blocks component from Droopler

A similar procedure has been applied on the Be Happy Music Club website in the Supporters tab.

The usage of the Text Blocks paragraph on the Be Happy Music Club website


9/11 DAY - emphasised movie about good deeds

Finally, we'll look at the 911day.org website, run by a foundation that encourages doing good deeds as a tribute to those killed and injured on 11 September 2001. On the home page, the video is even bigger than in the previous example. It even overlaps the menu, which is separated by a thin line, which delimits two zones, gives the impression of order, and the whole thing is visually attractive. Thanks to the two visible buttons, the user can go from this place to the subpages they are interested in.

A big section with a video on the 911day.org website, built in Droopler

Source: 911day.org

Also worth noting is the custom search engine for volunteer work options, which can be searched by keywords and location.

The search engine for discovering volunteer work options on the 911day.org website. You can search using keywords or location.


Of course, it's also integrated with a payment gateway.

Integration with a payment gateway on the website created in Droopler


911day.org is an interesting example of a website built on Droopler that only gets traffic during certain periods of time. If you are interested in how to set up a website so that it works properly in such conditions, we encourage you to read the article on how to prepare your site for the occasional spikes in traffic.


Droopler is a Drupal distribution that - as you can see in the examples above - is flexible and non-limited. With its help, you can create your site based on the existing paragraphs, and additionally use Drupal modules that meet specific needs. Did you like the examples of pages in this article? If so… #MeetDroopler.

Jun 04 2021
Jun 04

Creating a dynamic PDF file is one of the most important points of a project. The crucial thing is to find the right solution that meets your expectations and requirements. In this article, we’ll show you one of the most popular PDF generation modules for Drupal that will be helpful for you to generate, view or download reports, articles, and invoices in PDF.


The first version of the module was released on 22 January 2015, the latest update - 18 June 2020.

The module can be installed on:

  • Drupal 7 (7.x-1.5 stable release version),
  • Drupal 8 and 9 (8.x-2.2 stable release version).

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

Module’s popularity

According to the usage statistics from the module's page, it’s currently used by around 12 thousand websites.

Module’s creators

The module is created and maintained by benjy.

What is the module used for?

Entity Print allows you to print (save) any Drupal entity (Drupal 7 and 8) or View (Drupal 8+ only) to a PDF file. It uses the PDF engines based on popular PHP libraries like Dompdf, Phpwkhtmltopdf and TCPDF.


  1. To install Entity Print, go to its webpage or do it via composer: 
    composer require "drupal/entity_print 2.x"
  2. Install Dompdf by running composer require
    composer require "dompdf/dompdf:0.8.0" 
  3. Additionally you can install Wkhtmltopdf and TCPDF engines.
    composer require "mikehaertl/phpwkhtmltopdf ~2.1" 
    composer require "tecnickcom/tcpdf ~6" 
  4. Enable the Entity Print module.
  5. Grant permissions for non-admin users to download the PDFs.
  6. Optionally, enable the Entity Print Views module.
The installation settings of the Entity Print Drupal module


Configure Entity Print

Let’s check what this module allows us to configure.

  • Enable Default CSS - provide some very basic styles.
  • Force Download - force the browser to download the PDF file.
  • PDF - select the default PDF engine for printing.
  • Paper Size - change page size to print the PDF to.
  • Paper Orientation - change orientation to Landscape or Portrait.
  • Enable HTML5 Parser - Dompdf doesn't work without this option enabled.
  • Disable Log - disable Dompdf logging to log.html in Drupal's temporary directory.
  • Enable Remote URLs - must be enabled for CSS and Images to work unless you manipulate the source manually.
  • SSL CONFIGURATION - may be needed for development only, in production you shouldn’t change it.
  • HTTP AUTHENTICATION - if your website is behind HTTP Authentication, you can set the username/password.
  • EPub - select the default EPub engine for printing (currently not supported, you can follow the opened issue).
  • Word Document - select the default Word Document engine for printing (currently not supported, follow the opened issue).
The Entity Print module's configuration


The preferable PDF engine is Dompdf, which is (mostly) a CSS 2.1 compliant HTML layout and rendering engine written in PHP. It’s a style-driven renderer so it’ll download and read external stylesheets, inline style tags, and the style attributes of individual HTML elements. It also supports most presentational HTML attributes.

Module’s use

After the module is configured properly and all permissions are set, we can start exporting entities and views to a PDF file.

Exporting entities

Entity Print adds a disabled field to the view modes of each content type. The field has a default label value of "View PDF". To make this field visible on any content type, enable it on the Manage Display page


Enabling the View PDF field on the Manage Display page of the Entity Print module

From now, we’ll have a view PDF button added to our content type. The URL button is:


(i.e. https://example.com/print/pdf/node/1)

View PDF option visible in a PDF file


Here is the PDF we want to save or print:

An example of a PDF file to save or print in the Entity Print Drupal module


Exporting Views

With the Entity Print Views module enabled, a "Print" Global option can be added to the View's header or footer.

The URL button looks like:


Adding a Print Global option to the View's header in the Entity Print module



For easy and quick debugging, Entity Print provides us a HTML version of the entities sent to the PDF engine. The URL looks pretty much the same as above only with /debug appended.

E.g. https://example.com/print/pdf/[entity_type]/[entity_id]/debug.

How to hide the View PDF link in the exported file

By default, the "View PDF" link is also added to the PDF. To remove it, go to the Manage Display page for the specific content type. On the Custom Display Settings section you need to enable the PDF view mode.

Custom display settings in the Entity Print module


Now you can disable the Entity Print field on that view mode. Next time you export the PDF, you won’t have the "View PDF" link included.

By default, the PDF view mode is installed for Nodes only. In case you have any custom entities, you must first create a PDF view mode for the specific entity type via "admin/structure/display-modes/view". You can name it whatever you like but remember that a machine name should be "pdf", as it will be automatically prefixed with the entity name.

Styling the PDF from your theme

The following examples show how to register entity_print CSS files from your_theme_name.info.yml file. You can do it for any entity type or even view.

#Add css library to all nodes:

    all: 'YOUR_THEME_NAME/print-styling' 

#Add css library to the Node entities but only article bundles:

    article: 'YOUR_THEME_NAME/print-styling' 

#Add css library to all views:

    all: 'YOUR_THEME_NAME/print-styling' 

Don’t forget to define a CSS library in your YOUR_THEME_NAME.libraries.yml:

print-styling: version: VERSION css: theme: css/print-style.css: { } 


Modifying templates

All the normal ways to override templates are available. Using theme hook suggestions, you can create a Twig template and modify the content of any specific entity (e.g. node--blog-post--pdf.html.twig). In this template, you can modify the markup as you normally do by using {{ content.field_example }} or {{ node.field_example }}.

You can modify the HTML output of the entire Entity Print template. Just copy the entity-print.html.twig file from its base location into your theme folder. Using theme hook suggestions, you can also create entity-print--node--[content-type].html.twig file.

   {{ title }}
   {{ entity_print_css }}

{{ content }}

Make sure the {{ entity_print_css }} is always included inside the tag tag head in your custom Twig template file. Otherwise your custom CSS libraries won’t work.

Custom PDF Engines

It’s worth mentioning that the Entity Print PDF engines are pluggable. It means you can easily implement your own engines. To do so, you need to create a class in your_module_name/src/Plugin/EntityPrint/NewPdfEngine.php that implements Drupal\entity_print\Plugin\PrintEngineInterface with its all required methods. After that, your plugin will be available in the engines select list on the configuration page.

Alternative solutions

There are a few other options for making a PDF of an entity in Drupal that you might want to investigate.

PrintFriendly & PDF is a plugin for Drupal 7, 8 and 9. Below you can see its features list:

  • It’s fully customizable.
  • With the On-Page-Lightbox option, the PDF file opens in a Lightbox.
  • It lets you print or get a PDF.
  • You can edit the page before printing or getting a PDF, for example by removing the images and paragraphs you don't need.

Printer and PDF versions for Drupal 8+ is a module that also works for Drupal 9. It allows you to generate the following printer-friendly versions of any node:

  • webpage printer-friendly version (at /node/[node_id]/printable/print),
  • PDF version (at /node/[node_id]/printable/pdf).

Supported libraries:

  • mPDF,
  • TCPDF,
  • wkhtmltopdf,
  • dompdf.


The Entity Print module provides multiple methods of exporting entities to PDFs via different PDF engines. It is a very flexible and customizable module which will help you in dynamic generation of your articles, invoices or other content related to your Drupal website. The module has full test coverage and is ready to be used in production for Drupal 7, 8 and 9.

Jun 03 2021
Jun 03

Modern websites have become more and more extensive. At some point, a user may feel confused due to a large amount of content. At the same time, the website itself starts to be hard to use. Then the need to create a convenient, easy to develop, and maintain navigation appears. The solution which will work great in this case is a mega menu.

What is a mega menu?

A mega menu is a type of navigation consisting of several levels, used on websites. The first level looks like a standard list of links, but after hovering over one of its elements, additional options are shown. These options consist not only of a list of links in the second level of navigation but often have a third or even fourth level. Sometimes there are also visible photos or even videos. A menu built in this way is visually appealing to the user and allows them to easily find their way around large websites.

Below you can see the example of how the mega menu works on the webpage built in Droopler.

Mega menu in Drupal on the example of a website created in Droopler, a website builder


Mega menu in Drupal

In the Drupal CMS, creating a mega menu is quite a difficult task. That’s why the modules that simplify building advanced navigation were made. One of them is Mega Menu. Not only will it save you countless time creating and customizing complex navigation, but at the same time make your website amazingly impress your users.

Here’s how the Mega Menu module works: based on the default Drupal menus, the configurable mega menus are created. We can add to them submenu or even the whole blocks, using a friendly configuration interface. The additional option is the possibility to add a few columns in the submenu, setting styles, and animations.

Creating an extensive menu in Drupal, using a Mega Menu module

Source: Drupal.org

However, it’s important to mention the downsides of Mega Menu. One of them is that the module uses a separate Bootstrap library. This not only increases the size of the CSS and JS files, but also conflicts with the Bootstrap library used on the websites. The second disadvantage is that the navigation built with the Mega Menu module is poorly optimized for mobile devices.

In Droopler, a Drupal distribution, we rewrote the frontend part of the module from scratch. This way, we eliminated the most significant downsides of the default Mega Menu module. On the example of Droopler, we’ll show you how you can create with this module an extensive menu for your website.

Creating an extensive menu in Droopler

Droopler is a Drupal-based distribution dedicated to building corporate websites. It contains ready-to-use elements and tools enabling quick creation of the websites.

Main menu configuration

We can find the main menu settings in the Drupal administration menu in Structure. Next, in Drupal 8 Mega Menu, we look for the Main navigation element and from this element's menu, we go to Edit links.

Configuration of main menu in the Drupal administration menu

After going to the edit page, the working structure of the main menu appears, which we can freely edit using the "drag and drop" method. To add more levels to the menu, we need to move the secondary element to the right to create an "indentation".

Adding new blocks

To add a block to the menu, we must first add a new content block. We go to Structure -> Block Layout -> Add custom block and select the content block.

Adding a new content block to the menu

The system takes us to a form, where we add a new block. We fill out the title and the content of interest. In this case, it’ll be the title and a few links. Next, we add another block with the content and photo.

Editing a custom block in Droopler


After adding two blocks, we need to add them to the region on the page and - at the same time – disable the display of these blocks in the region. In the Block Layout of the header section, we click Place Block, and then select from the popup window the block we want to add and click Place block. In the next step, we uncheck the show title option and save.

Adding new blocks to the region on the page


When the blocks are added to the region, we should disable them. To do this, we click Disable in the block's action menu.

Disabling display of new blocks in the region


After completing this step, we can start adding blocks to the menu. To do this, we go to Structure, Drupal 8 Mega Menu, and then click config next to the main navigation.

We are taken to the menu edit. In our case, we’ll add blocks to the "products" element. After clicking "products", a configuration panel appears on the right. We check the Submenu in it as active.

Activating the Submenu in the configuration panel of the mega menu in Drupal


Now a workspace appears under "products", where we’ll add our blocks in a moment. After clicking on this element under "products", another configuration panel appears, but this time it concerns our workspace.

The configuration panel of the workspace


In this panel, we use the plus and minus buttons to set the number of columns in our mega menu. In the Grid field, we set the column’s width, while the Blocks field is used to select the previously added blocks.

After setting the appropriate options, we click Save and our menu should look similar to the one below.

The ready mega menu built with Droopler, a Drupal distribution, and the Mega Menu module



A mega menu is a good option for presenting to the user an advanced website’s structure or a web application. With the Droopler distribution and the Mega Menu module, we can easily build the advanced pages with a user-friendly navigation which allows us to clearly show the structure of a large website.

May 27 2021
May 27

Virtual business card, flyer, minisite – all these terms perfectly reflect the nature and essence of landing pages. They consist of several horizontal segments in which advertising content is presented, encouraging you to continue exploring a given topic on other dedicated and full-sized webpages. Let's check the possibilities Drupal gives us when creating these specific websites.

A page made of blocks

To create a one-page website composed of horizontal segments – clearly separated from each other, yet forming a consistent whole – we can use several tools or modules available in Drupal's core. The first option that comes to mind is using blocks. In Drupal, blocks work just like Lego bricks, elements containing any content. They can be displayed in different regions of the page, one above the other. Sounds like something we need!

While the idea of using simple blocks, mainly containing text, will work great in this case, achieving visual requirements or the desire to include slightly more complicated content (e.g. counters, multimedia, combination of text and multimedia, carousel, etc.) seems to be time- and labour-consuming. A high level of block personalization will require us to create several block types and/or content types and additional fields from scratch, along with additional classes for a purpose of a correct display.

For the proponents of clean code - Twig

One of the available solutions is also the option to create a twig collection, where – using the HTML and PHP code – we are able to create a landing page with any level of complexity, using the available or new fields. This option, however, requires us to spend many hours in front of the screen, countless lines of code, not to mention the subsequent maintenance and content management. To implement this solution, one definitely needs a person with technical knowledge – also at the stage of introducing the content.

Creating a Drupal landing page - modules

As we mentioned earlier, a landing page in Drupal can also be built using modules. Let's check out which of them we can use and how.

Layout Builder module

A very useful tool that has been recently added to Drupal's core is the Layout Builder module, which allows you to create templates for the structure of displaying elements on a page. The user has the ability to define their own "regions" for different types of content, using a very helpful drag and drop interface. In simple terms, it replaces the default display management function, which defines how and which fields are to be displayed, and additionally gives the opportunity to put blocks in place. When creating a template, you can feel like a graphic designer juggling the elements, while all the tools they need (in our case – the options for editing blocks and sections) are at hand in the form of an edit bar. To use this module, you need to launch it manually, as it isn’t enabled by default when installing Drupal.

When creating a new content type or wanting to use Layout Builder for an existing one, go to the display management tab. An additional "Layout options" section will appear below the list of fields, where we select the "use Layout Builder" option. Instead of a list of fields, a "manage display" button will be added, which will redirect us to the Layout Builder interface. We can freely manage the order of elements, add blocks that may contain fields from any entity, forms, plain text, links, views, and even an entire menu. Blocks are added within sections. Each section can be arranged into any number of columns between 1 and 4. The order of sections can't be changed or "dragged", so be careful when adding them.

Creating a Drupal landing page with the Layout Builder module


Unfortunately, Layout Builder won’t do everything for us. We need to put more effort into styling all the elements. There is, however, an additional module – Layout Builder Styles – dedicated to creating new classes for Layout Builder blocks and sections, with the ability to define restrictions concerning which blocks a given class will be assignable to. A beta version is currently available, and our Drupal installation can’t be older than version 8.7.7. However, to take full advantage of the style management capabilities, without having to interfere with the code, we need to install one more module - Asset Injector, where we'll define all the parameters of the previously created classes. Then, when editing every block or section, we'll be able to assign one class available on the list.

Styling the elements of the landing page using the Layout Builder Styles and Asset Injector Drupal modules


Paragraphs module

The second most frequently chosen option when creating a Drupal landing page is the use of the Paragraphs module along with Entity Reference Revisions. Paragraphs allows you to create templates that will later be sections (aka paragraphs of a page). One paragraph may consist of many fields of any type. Such a collection will constitute the type of paragraph to be used by any selected content type. For example, let's create a new content type named "Landing page". At this stage, in addition to the default "body" field, we add a few other fields that are important to us. This time, we only need one field of the paragraph type.

Adding a paragraph field to a content type during creation of a landing page using the Paragraphs module

Now we'll create two new types of paragraphs: “banner” and “image + text”. Under Structure -> Paragraph types -> Add paragraphs type, we create new types of paragraphs and manage the fields to be included in them. For a banner, it'll mean an image field. For the “image + text” type, it'll also mean an image field and formatted text. As is the case when creating content types, with paragraph types we can manage the display of fields and their formatters. You'll surely notice in the list that you can add a field of the paragraph type, this way we can create nested paragraphs and use the already existing ones.

Creating new types of paragraphs with the Paragraphs and Entity Reference Revisions Drupal modules

Having the types of paragraphs, let's check out what the landing page creation will look like. It's worth mentioning that without defining in the content type settings what specific paragraph is to be its content, we are presented with a list of all available paragraph types, which we can add multiple times thanks to setting “unlimited” when creating a paragraph field.

Creating a Drupal landing page with the Paragraphs module


Paragraphs is a powerful tool that allows you to maintain a high degree of flexibility when creating landing pages. The pitfall when using this module is managing the content later, especially if we create a complex structure with multiple nested fields. The person editing the content on the page may then feel lost and overwhelmed by the enormity of tabs and settings.

Tuned-up paragraphs. Creating a landing page in Droopler

If you like the option of using paragraphs the most, you'll surely find what Droopler has to offer for creating one-page websites to be even better! Droopler is our free Drupal distribution for creating webpages. It contains many ready-made templates and components.

For this tool, we used the idea of creating paragraphs and nested paragraphs to "assemble" a webpage. In the default version, along with the Droopler installation we get a number of predefined types of paragraphs at our disposal. These are the most commonly used kinds of paragraphs when creating webpages.

Types of paragraphs in Droopler, a free Drupal distribution

Types of paragraphs in Droopler

Then why should we use Droopler and how does it really differ from the previously presented possibilities offered by the Paragraphs module, apart from saving time when creating the most popular types of paragraphs?


Already at first glance, we can see one fundamental difference – the added paragraphs look professional and, if we are satisfied with the used colour scheme, we don't have to do anything else with them! However, if we decide to change it, overwriting the default skin won't be a problem. You can find more information on this topic here.

Editing directly on the created page

I mentioned earlier that it can be confusing to navigate around editing a content type that consists of paragraphs. This problem has been solved in Droopler thanks to using the Geysir module and the possibility of editing paragraphs directly on the created page, in the form of modal windows. The interface also allows you to “cut” and “paste” paragraphs, that is, to reorder and remove them without having to go to a content type edit page. This way everything remains clear and we immediately see the effects of our changes.

Possibility of editing paragraphs directly on the created page in Droopler


Additional options

The Paragraphs module is field-based, allows you to choose the formatter and manage the display, but there is no room anywhere for additional options related to styling or quick reorganisation of the content within a single paragraph. If we want to have a paragraph with an image gallery, we need separate types for putting 4 or 8 thumbnails. The same happens when using different types of media – a separate type is needed for images and videos.

Droopler is highly flexible in this aspect. The banner paragraph type accepts both an image and a video file. What's more, for every type of paragraph in the "settings" tab in the adding paragraph window, it's possible to configure margins and padding, as well as to define additional classes that we determine in our skin, and there's even the option of choosing a predefined colour scheme.

While editing a paragraph in Droopler, you can configure margins and padding, as well as define additional classes


If we want to create a paragraph composed of tiles, we can choose which of them should be highlighted by increasing their size in relation to the rest, achieving the effect of a "masonry" gallery.

Do you have a prepared block that you'd like to use and place among the paragraphs? In Droopler, paragraphs can also consist of blocks, in the tab we can choose from among all those that currently exist on our page. The block with icons and links to social media - ready. A quick contact form? This has also already been done for us.


Landing pages or one-page websites are a very specific type of content that we can find around the web. It should be simple, transparent, look modern and encourage us to go to the further, target pages. It's a huge tool in the hands of marketing teams, so Drupal was also designed to give users, including non-programmers, the option to quickly create these kinds of pages. Some of the methods presented in the post show a low degree of difficulty and can be implemented by a layman (Layout Builder, Paragraphs). However, they have their limitations and at some point the "architecture" created with them becomes too complicated and difficult to maintain. Additionally, the intention to create something non-standard will require the help of a developer, especially for styling. By choosing Droopler, we can be sure that the landing page creation process will be simple and pleasant, as well as visually effective, without having to tamper with the code. Anyone, without exception, will be able to learn to manage paragraphs with ease, and in less time than expected.

May 21 2021
May 21

The homepage is the most important element of a website. The first impression of the user depends on it – whether they'll stay on the website, whether they'll be interested in the company's offer and the company itself. In just a few simple steps, we'll show you how to create a homepage that will help you keep your visitors' attention.


What elements should a homepage contain?

A prospect enters the homepage. You have a few seconds to interest them and make them continue to check out your offer. How can you do that? You need to correctly convey the most important information that will immediately answer the customer's questions.

Banner with a call to action

First of all, you need to briefly describe what your company does. This type of information is often displayed in a banner at the top of the page. In this section, you can add a CTA (Call to Action). It's a link which when clicked redirects the user the destination area, e.g. to the next section of a page or to a contact form.

Blocks with content

You should also put blocks that contain information about what your company can offer to a potential customer and why they should choose your offer. Various types of representing information are suitable for these purposes: from simple text blocks to advanced interactive carousels that allow you to put more content into a fairly tight framework of one block.

Once you know what elements to put on the home page, the matter of creating the page in a fairly quick and easy way arises. Website builders – one of which is Droopler – are suitable for solving such a problem.


Create a homepage in Droopler

Droopler is an open source website builder based on CMS/CMF Drupal. It contains ready-made components and tools that allow you to quickly create modern webpages. Droopler is simple to edit and easy to expand. Let's try to create the most important elements of a homepage with its help.

Banner paragraph

As we've already mentioned, one of the most important elements of a homepage is a banner with brief information about the company at the top of the page. In order to add a block of this type, press the “Paragraph overlay” button on the top right of the page.

The Paragraph overlay button is located on the top right of the page in Droopler


Next, you have the option to add a new block in the selected area. After pressing the "Add" button, select the "Banner" component in the pop-up window.

Adding a new block on the homepageIn the pop-up window, select the Banner component to add it to the homepage


In the next window, you need to add a banner background. Additionally, you can add a title, subtitle, icon that appears at the top of the block and some brief text. It’s also possible to add the already mentioned Call to Action button and configure its main attributes.

Configuring a new paragraph for a homepage in Droopler


In the "Settings" tab, you can choose the shape of the block: placing the text in the central part of the banner or on the left side with a translucent background. It’s also possible to set different colour versions of a paragraph and define your own colours to ensure good readability of the text. Additional options include configuring the margins and padding, as well as adding additional classes for the block.

In the Settings tab, we can configure more settings for a particular paragraph


After pressing the "Save" button, the first block of the main page will be put in the lower right corner of the window:

The block with a banner on a homepage in Droopler


Carousel paragraph

A carousel is a type of block that contains a looped slideshow that can be controlled by the user. In order to create such a block in Droopler, select "Carousel" in the component list window.

Selecting a Carousel component to add it to the homepage


As in the case of a banner, you can add a title, icon, description and CTA. In the "Settings" tab, it’s also possible to set the margins. In addition, you can define the number of columns - how many elements should be displayed in this block.

Configuring the settings for a Carousel paragraph


The carousel items are added in the "Items" tab. You can choose your own title, image, description and link for each of them. The same as for the entire paragraph, for every element, you can set separate graphic themes - change the colour of the background or text. The next picture shows a finished carousel.

A finished carousel with graphic and text elements in Droopler


About Us section

You can create a block with information about the company using the "Text page" paragraph type. It's a simple section where you can enter a title, subtitle, add an icon, text and link. The available settings are the same as for a banner and carousel. After all the fields are filled in, the section will look like this:

The About Us section on the homepage, created using Text page paragraph



In this article, we explained how to create the most important elements of a homepage in a fairly easy and quick way. We used Droopler – a modern website builder, which not only allows you to build websites without coding, but also facilitates Drupal development.

May 21 2021
May 21

The homepage is the most important element of a website. The first impression of the user depends on it – whether they'll stay on the website, whether they'll be interested in the company's offer and the company itself. In just a few simple steps, we'll show you how to create a homepage that will help you keep your visitors' attention.


What elements should a homepage contain?

A prospect enters the homepage. You have a few seconds to interest them and make them continue to check out your offer. How can you do that? You need to correctly convey the most important information that will immediately answer the customer's questions.

Banner with a call to action

First of all, you need to briefly describe what your company does. This type of information is often displayed in a banner at the top of the page. In this section, you can add a CTA (Call to Action). It's a link which when clicked redirects the user the destination area, e.g. to the next section of a page or to a contact form.

Blocks with content

You should also put blocks that contain information about what your company can offer to a potential customer and why they should choose your offer. Various types of representing information are suitable for these purposes: from simple text blocks to advanced interactive carousels that allow you to put more content into a fairly tight framework of one block.

Once you know what elements to put on the home page, the matter of creating the page in a fairly quick and easy way arises. Website builders – one of which is Droopler – are suitable for solving such a problem.


Create a homepage in Droopler

Droopler is an open source website builder based on CMS/CMF Drupal. It contains ready-made components and tools that allow you to quickly create modern webpages. Droopler is simple to edit and easy to expand. Let's try to create the most important elements of a homepage with its help.

Banner paragraph

As we've already mentioned, one of the most important elements of a homepage is a banner with brief information about the company at the top of the page. In order to add a block of this type, press the “Paragraph overlay” button on the top right of the page.

The Paragraph overlay button is located on the top right of the page in Droopler


Next, you have the option to add a new block in the selected area. After pressing the "Add" button, select the "Banner" component in the pop-up window.

Adding a new block on the homepageIn the pop-up window, select the Banner component to add it to the homepage


In the next window, you need to add a banner background. Additionally, you can add a title, subtitle, icon that appears at the top of the block and some brief text. It’s also possible to add the already mentioned Call to Action button and configure its main attributes.

Configuring a new paragraph for a homepage in Droopler


In the "Settings" tab, you can choose the shape of the block: placing the text in the central part of the banner or on the left side with a translucent background. It’s also possible to set different colour versions of a paragraph and define your own colours to ensure good readability of the text. Additional options include configuring the margins and padding, as well as adding additional classes for the block.

In the Settings tab, we can configure more settings for a particular paragraph


After pressing the "Save" button, the first block of the main page will be put in the lower right corner of the window:

The block with a banner on a homepage in Droopler


Carousel paragraph

A carousel is a type of block that contains a looped slideshow that can be controlled by the user. In order to create such a block in Droopler, select "Carousel" in the component list window.

Selecting a Carousel component to add it to the homepage


As in the case of a banner, you can add a title, icon, description and CTA. In the "Settings" tab, it’s also possible to set the margins. In addition, you can define the number of columns - how many elements should be displayed in this block.

Configuring the settings for a Carousel paragraph


The carousel items are added in the "Items" tab. You can choose your own title, image, description and link for each of them. The same as for the entire paragraph, for every element, you can set separate graphic themes - change the colour of the background or text. The next picture shows a finished carousel.

A finished carousel with graphic and text elements in Droopler


About Us section

You can create a block with information about the company using the "Text page" paragraph type. It's a simple section where you can enter a title, subtitle, add an icon, text and link. The available settings are the same as for a banner and carousel. After all the fields are filled in, the section will look like this:

The About Us section on the homepage, created using Text page paragraph



In this article, we explained how to create the most important elements of a homepage in a fairly easy and quick way. We used Droopler – a modern website builder, which not only allows you to build websites without coding, but also facilitates Drupal development.

May 05 2021
May 05

The N1ED module works as a bridge between Drupal 8 and 9 versions, and the N1ED library – which is a multi-plugin for CKEditor, the basic text editor in this system. The library itself is built based on Bootstrap and its classes. In this text, we'll take a look at it and at the module itself.

N1ED library

The N1ED library is available in free and paid versions. The former has limited functionalities, but you can use options such as:

  • full screen text input,
  • widgets which introduce new buttons to the editor, such as Font Awesome icons, easy table insertion and HTML code insertion,
  • easy addition of headings and paragraphs, which allows you to better control the entered text.
Full screen version of the free editor version

Full screen version of the free editor version

Apart from the free version of the library, there are three different paid plans that provide additional functionalities. The most interesting of them is Bootstrap Editor, thanks to which you can easily design what the website will look like in the desktop or mobile version.

N1ED module

Before the installation, you can see and feel for yourself how the N1ED module works and only then decide if it's worth starting to use it on your own website.


It's a relatively young module. It appeared on Drupal.org in early 2019, but it's already a stable version monitored by the Drupal Security Team. The first release of the N1ED library was earlier – on 18 December 2018.

Popularity of the module and the library

According to the official statistics, the module is being used by more than 150 websites. The library itself can be used in any system that uses CKEditor or TinyMCE, for example in Symfony, Laravel or Magento.

Configuration and use

Download the N1ED module from Drupal.org. The module is installed in the typical way:

composer: composer require drupal/n1ed

drush: drush dl n1ed

drupal console: drupal mod n1ed

After executing the command you need to enable N1ED on the page with modules using Drush or Drupal Console. Support for a new plugin in CKEditor is automatically enabled for the Full HTML filter.

Support for N1ED plugin in CKEditor

N1ED can be enabled for any text format. Just set the switch to the desired position in the text format edit options.

In the same place, you can set your own API key which is required for the plugin to work. After the installation, you use the default key provided with the module which gives basic free functionality.

Setting your own API key for the N1ED module



Although the free version of the library is very limited in terms of available functionalities, it provides a new look and feel for adding content in Drupal. In addition, it helps you to control the text and elements you enter. We use both the library and the N1ED module as part of our Drupal development services.

Apr 28 2021
Apr 28

Bluehost is among the 20 largest hosting companies in the world, handling over 2 million domains. The company's offer includes a wide range of services. We will show you how to install Droopler, the Drupal distribution, using the basic shared hosting offer (Basic Web Hosting).


Step 1. Server preparation

First, you need to configure the database and PHP. This stage is necessary because, without it, it won't be possible to install Droopler. But before you start, you need to get familiar with the requirements for the system on which you want to run Droopler.

To configure your hosting, after logging in to the account using the login form, go to the "Advanced" tab, where you'll find all the necessary functions:

The Advanced tab in Bluehost, where you'll find all the necessary functions for the hosting configuration



1. Database configuration

First, you need to create a new database. To do this, click on the "MySQL Database Wizard" in the "Databases" section.

The Databases section in Bluehost


You'll be redirected to the database wizard page. In the first step, you need to define the database name. It can be any name but in our example, we’ll use the most intuitive one - droopler. The full database name will consist of a prefix (usually associated with the account id) and a second part/name defined by you.

Defining the database name in MySQL Database Wizard


In the next step, you need to define the database users (at least one) and their passwords. You can generate the password using the Password Generator located in the form.

Defining the database users in MySQL Database Wizard


In the third step, you need to assign the user permissions to your database. For the Droopler installation to work correctly, it's safest to assign all permissions by selecting the "ALL PRIVILEGES'' option.

Assigning all database privileges to a user to make the Droopler installation work properly


2. PHP configuration

Setting the appropriate version of the PHP language and adjusting its configuration is crucial and can significantly affect the installation process. To make the necessary changes, go to the "Software" section in the "Advanced" tab.

The Software section in the Advanced tab in Bluehost


To set a specific PHP version, click on "MultiPHP Manager". In our installation, we'll use the proven PHP 7.3 version.

Selecting a specific PHP version in MultiPHP Manager


To change the environmental settings, click on "MultiPHP INI Editor".

With MultiPHP INI Editor, we can change the environmental settings


In the first step, you need to select the domain for which you want to make the necessary changes.

Selecting the domain for which you want to make the changes in MultiPHP INI Editor


Then you need to adjust the configuration for the needs of the Droopler installer and for the smooth operation of the website. We increase the maximum script execution time (max_execution_time) to 180 and the memory limit to 512 MB.

Adjusting PHP configuration for the needs of the Droopler installer and the smooth operation of the website


We leave the other values in accordance with the default settings.


Step 2. Downloading Droopler

The Droopler distribution can be downloaded from the official website of the project.

1. Download the latest version of Droopler as a zip archive.

A place on the Drupal distribution's page from where you can download the Droopler


2. Go to the File Manager located in the "Files" section in the "Advanced" tab.

The Files section in the Advanced tab in Bluehost


3. After opening the file manager, click on the "Settings" button in the upper right corner to unlock the option to display hidden files.

After coming to the Settings section, we can unlock the option to display hidden files


4. In the file explorer located in the left column, click on the public_html directory.

The public_html directory in File Manager in Bluehost


5. Click on the "Upload" button in the top menu in order to upload the file from the archive downloaded in the first step.

The Upload button in File Manager


6. Drag and drop or select the file using the system file explorer.

Adding the Droopler file to File Manager in Bluehost


7. After loading the file, right-click on it and select the "Extract" option.

Selecting the Extract option for the Droopler file


8. Set the target directory for the extraction to /public_html.

Setting the target director for the extraction of the Droopler file


9. After the extraction is complete, go to the newly created directory with Droopler (in our example, it'll be the directory named droopler-8.x-2.1) and select all files.

The newly created directory with Droopler in File Manager in Bluehost


10. Move the selected files and subdirectories directly to the /public_html directory using the move button available in the top menu or after right-clicking.

Moving the selected files to the public_html directory


11. Leave only /public_html in the name of the path to which you'll move all the contents of the directory.

Defining the path to which you'll move all the contents from the directory with Droopler


12. After moving the files, go back to the /public_html directory and remove the uploaded .zip archive (droopler-8.x-2.1-core.zip) and the directory created during the unpacking (droopler-8.x-2.1).

Removing .zip archive and the Droopler directory from the public_hml directory


Step 3. Droopler installation

Everything is ready now. To start the installation process, all you need to do is to go to the website by entering your domain address in the browser bar.

The Droopler installer


The Bluehost web hostings don't offer PHP OPcache, so you'll see a warning when verifying your requirements. You can ignore it and proceed with the installation by clicking on the "continue anyway" link at the bottom of the page.

The warnings during the requirements verification in the Droopler installer


The last important step is database configuration. Here we enter the data that we previously set in the Bluehost panel, i.e., the database name, the database user's name and their password. The host and port number remain as in the attached screenshot.

Database configuration in the Droopler installer


After clicking on "Save and continue", you have nothing else to do other than to take a short break for coffee or tea, during which the rest of the Droopler installation will be performed.

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.

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();
// Load user entity.
$user_entity = \Drupal\user\Entity\User::load($user->id());
// Check for permission
if ($user_entity->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.


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