Useful Drupal modules

Click on the module name for notes, comments, patches.
Recommendations (for and against) are my personal opinion only and may be out of date. Feel free to email with corrections/suggestions.

Why doesn't the table mention Drupal 9 or 10?

1. Nowadays, I try and use Drupal as little as possible. Specifically I do not recommend it for a new website. I'd also strongly caution you against choosing Drupal if you're at the beginning of your career and trying to learn web development (front / back / full stack) or just want to manage/maintain a website. More details why by email on request.

2. By February 2022 I'd updated all the sites I look after to Drupal 9 (experience: mixed). As of March 2023, a year later, none of them were fully ready for Drupal 10 (waiting on support for various modules). By 13 Nov 2023 (a week or two after D9 lost support) I had updated a couple of them.

Q: What's the Drupal 9 to 10 upgrade experience like? A: it's what I'd describe as "just bearable", slightly better than D8 to D9, though with plenty of things to still trip you up. There is still deprecated code that needs fixing in D10 modules, and policy changes mean odd things will break (be prepared to turn off Aggregate CSS/JS files if your themes stop working, and note that Drush launcher doesn't work with Drush 12...)

Admittedly the upgrade_status module is the best solution they could have come up with for tracking compatibility. Also watch out for a nasty session headers bug with redirect_after_login.

What about sites still running Drupal 7? In short I still recommend leaving them on Drupal 7 or moving to another platform entirely. My prediction was that Drupal will extend D7 support year after year (note that drupal.org itself is still running D7). It's now been confirmed as 5 Jan 2025. There will have to be some sort of third-party long term support, because of the sheer volume of sites that are not being upgraded.

Your decision is really what specifically you think you will gain from Drupal 8/9/10 - often the answer will be not enough, and one of the main hassles - apart from converting each content type one at a time, and setting up a new theme, will be recreating all your views by hand, as views can't be automatically upgraded.

(134 modules in list)
Module name or machine name
Any text in the notes
Name Sort ascending D8 Personally Tested Last Updated
Webform Views Integration (webform_views)

d.o. page

"Essential"

This module lets you add fields from submissions to view, and sort/filter the view on them, in the same way you would standard fields from the Field API.

It's still alpha and not as polished/robust as the webform module itself - but it's certainly OK to use in production provided you test things first - check every combination of exposed filters works, and double check you aren't seeing duplicate rows (right now I've locked it to a recent commit on the dev-5.x branch, which doesn't need any patches).

Webform (webform)

d.o. page

"Essential"

One of the best maintained contrib modules.  Main benefits: nicely presented forms with powerful conditional logic, YAML configuration, flexible user permissions, very clean data storage, secure.  Codebase is also very much written "the Drupal way".

I'm currently using this patch to avoid AJAX errors - it's only necessary where you've both enabled Automatically save as draft when paging, previewing, and when there are validation errors, and are using a confirmation type like inline, that still uses AJAX to submit the form when there are no validation errors.

Troubleshooting install of webform external libraries: (Jan 2020)

Follow these instructions: https://www.drupal.org/node/3003140

If you get a composer SSL error, follow these instructions.

(specifically, you need to set openssl.cafile in php.ini)

Web Profiler (webprofiler)

d.o. page

"Essential"

Install the devel module first.  The profile is a toolbar at the bottom of the screen. Features:

  • useful shortcuts (e.g. clear cache)
  • view info about current user, their role and permissions
  • server HTTP response
  • cache, DB and DOM loading performance
  • memory use
  • which blocks and views have been loaded

Tip: there are further reports ("collectors") you can turn on in the module preferences, and there's a shortcut to these from the menu in the first icon (Drupal logo). The toolbar is only a summary, all icons are clickable to view a full report. Each report is saved in the DB for later reading.

This module was ported from Symfony

Warden (warden)

d.o. page

A fork of the System Status module, but with a Symfony app for you to install to act as a server, rather than using a paid third-party service.  Monitor core/module update status of multiple Drupal sites.  If you're familiar with Nagios and NRPE, it's a little bit like that, but for Drupal modules, and more lightweight.  Note the server uses MongoDB, so you need to install that, plus the PHP extension, and it communicates with a public key-pair, though it should set that up itself.  

Views taxonomy term name into ID (views_taxonomy_term_name_into_id)

d.o. page

Allows you to use /my-view/foo instead of /my-view/123 when adding a contextual filter based on taxonomy terms

Views Secondary Row (views_secondary_row)

d.o. page

"Essential"

For Views that use Table format. Adds a row underneath each record - you change the format from 'table' to the 'secondary row' option, you get an extra select dropdown in the table *settings*, and you can also specify colspan.  This does mean the label will be missing by default (you won't have a column header any more) - so you need to edit the field and tick rewrite output, and then specify your desired label, followed by the field value in Twig.
 

Views PHP (views_php)

d.o. page

Allows you to insert a Global PHP field in a view in D7, so you can have conditionals etc.

Note there's a bug in 7.x-1.1 (Jan 2022) - you need this patch.

(Not available in D8, you should use Twig instead).

Views infinite scroll (views_infinite_scroll)

d.o. page

  • supports both a 'Load more' button and automated load
  • need to turn AJAX on for the view
  • patch needed to support back button (adds a preserve history option to settings, which then needs to be turned on)
Views exposed form layout (vefl)

d.o. page

Not recommended

Layouts for exposed filters - i.e. you can move each filter into a region (supports Panels and Display Suite).

When I tried this (Summer 2018) the D8 branch wasn't really there yet - you could only rearrange the basic filter components in D8 (like search term, submit button, reset button), not all the extra ones you've added.   I went with using CSS (e.g. clear: both) instead.

Views Contextual Filters OR (views_contextual_filters_or)

d.o. page

"Essential"

By default if you add multiple contextual filters to a view, they must all pass (AND).
This gives you a checkbox in Advanced > Query Settings for the view which switches it to OR.

Views Aggregator Plus (views_aggregator)

d.o. page

Provides extra options for aggregating data in tables - e.g. grouping sets of rows together and summing the values of particular fields.

Has a hook - hook_views_aggregation_functions_info() - which lets you add your own options to the table aggregation settings - e.g.  supposing you have a limit for something (number of tickets, nights of accommodation) and want to decrement it - you can write a method to sum the matching rows and then do a calculation on the total.

Also supports 'add column function' - adds a grand total (or other summary field) at the very bottom of the table.

Caution - this module breaks hook_views_pre_render() - you can write your own pre_render method to remove or shuffle entire rows, but any chances to values will be overwritten (discovered this by looking through the source and looking for the use of that hook).  The workaround is to try and do what you need to by using hook_views_aggregation_functions_info() instead.

View Migration (view_migration)

d.o. page

Not recommended

Migrate views from D7 to D8.
Once installed on D7 - you need to go to /admin/config/view-migration 
It outputs multiple YML files and you're specifying a directory to put them in, which you need to create first.

My experience of the YAML output has been:

- incomplete (e.g. multiple missing displays in a complex view, views without a machine name)
- invalid UTF8 due to the next and previous arrows in pager.options.tags being encoded wrong
- the dependencies section at the top of the file not being set out correctly

It doesn't look like there's much current development activity (likewise migrate_views, which is the other plugin people usually mention).

Username policy (username_policy)

d.o. page

This gives you a single box where you can enter tokens to form the default username.

It seems to work, but in D7 the patterns section ("Only use the below pattern elements") was empty. This is supposedly because there's a dependency on the 'profile' module, except profile doesn't exist in D7 (I tried profile2 instead but it made no difference) and profile2 doesn't exist in D8.

auto_username displays tokens OK and is more powerful / has more settings including customise at what point names are truncated, etc.

User restrictions (user_restrictions)

d.o. page

"Essential"

Block registrations (wildcards on email address and username)

Useful if you're getting persistent spam registrations from certain domains.

Tested with D7.  This used to be in core in D6.​​​​​​​

Upgrade Status (for Drupal 9) (upgrade_status)

d.o. page

"Essential"

Very useful module for scanning installed modules (including your own custom code) for compatibility issues - gives a detailed report of necessary fixes.

NB: scanning using the UI (rather than Drush) won't work on a dev server without a valid SSL certificate.

Unique field ajax (unique_field_ajax)

d.o. page

"Essential"

Gives you a checkbox for 'Unique' when editing fields - can have it checked during form entry (via AJAX) and specify a custom error message per field.  Seems to have bug where field you're checking is sometimes refocused (even if no errors) if you've already tabbed away from it and continued typing.

Two Factor Authentication (tfa)

d.o. page

"Essential"

install tfa and ga_login (TFA is just a framework, it doesn't come with it's own login plugins.)

Use this patch I wrote - it adds display of validation skip times and an admin reset button for users who are got locked out.

My installation instructions:

Next you need to generate an encryption profile.
First you need to generate a key - key type needs to be Encryption (not Authentication).
A 128bit key = 128/8 bytes = 16 characters - so generate a random 16 character string.

Set key provider to File rather than Configuration, this means the key won't end up in your version control.

Tick the 'strip trailing line breaks' box to avoid the "The selected key size does not match the actual size of the key." error

Key path should be relative to Drupal so the config will work on multiple sites
e.g. if you have created a file called /app/tfa.key on a lando container, set the key path to ../tfa.key
I'm actually creating mine in a keys directory.

Remember to save the key somewhere in your password manager, or your ansible variables, in case you lose the files later.
Remember to add /keys to your .gitignore file, so it won't get stored in version control.
Remember to copy it manually onto your production server.

In the TFA settings (/admin/config/people/tfa) you probably want to increase the number of times a user can skip validation.

Note that TFA has a separate 'Tfa user login' block (replacing the ordinary 'User login') 

Twig Xdebug (twig_xdebug)

d.o. page

Use Xdebug breakpoints in Twig templates - {{ breakpoint() }}

Twig VarDumper (twig_vardumper)

d.o. page

"Essential"

Much faster than using kint, with colour coding, and still works nicely within narrow DOM elements.
Make sure you install using composer, as it has symfony dependencies.

Enabling twig debugging in the first place:

Also make sure you've activated twig debugging properly (including enabling the settings.local.php file in settings.php, and adding the debug setting to development.services.yml)
Potential gotcha - settings.local.php needs to be in /sites/default (or whichever), not just /sites/
If Twig debugging isn't enabled, the symptom is you don't see any output for the dump() commands.

Usage Tip:

- Hover over the keys and you get a tooltip that says 'Public method','Protected property' etc.

Twig Tweak (twig_tweak)

d.o. page

Adds Twig syntax to insert views, view results, regions, entities (e.g. nodes, blocks, webforms), menus, images, image styles, tokens, breadcrumbs, messages, contextual links and more.

Twig Extensions (twig_extensions)

d.o. page

Text filters, array and date manipulation.

(haven't tried this yet)

Trash (trash)

d.o. page

Adds a trash bin for all content, so you may later restore (or permanently delete) it.  Depends on Content Moderation module.  Alpha in D8.

Toolbar menu (toolbar_menu)

d.o. page

"Essential"

Add extra menus (which appear as cog icons with a title, which you can click and expand) to the admin toolbar at the top of your site.

Token (token)

d.o. page

"Essential"

Adds a user interface for browsing tokens (the tags you can insert into various fields).

Telephone (telephone)

d.o. page

Telephone number field type.  This is in core, but you need to enable it.

TagCloud (tagclouds)

d.o. page

Provides a block with a tag cloud of chosen taxonomy term. Works but a bit buggy, e.g. UI taxonomy setting reverts to 'tags'.  Requires clearing the cache to update (including changing any settings).  Choice of numbers after each tag to indicate quality, or 'wordcloud' style with varying sizes (will need you to modify your CSS to add some spacing between words). 

Table trash (table_trash)

d.o. page

Add extra tables JS support for views (and many other pages) - e.g. search box, dynamic column sorting, rearranging columns, exporting to clipboard etc.

If you get "TypeError: tables.DataTable is not a function" when using datatables module, first, try going to /admin/config/content/table_trash/global_settings and saving the existing settings.

Structure Sync (structure_sync)

d.o. page

"Essential"

Lets you synchronise taxonomies, custom blocks and menus.  

Important: always double check after importing if menu / block etc. has been correctly updated - if not, you may need to use a more forceful option.

String Overrides (stringoverrides)

d.o. page

"Essential"

Replace text on the site.

Spambot (spambot)

d.o. page

"Essential"

Scans email addresses/usernames/IP addresses against the stopforumspam.com database and then blocks or deletes the accounts.
You can set the threshold - i.e. how many times an email address needs to be listed in the spam database before action is taken.
You can also have it scan your entire existing database, not just new users. (It does this via a configurable cron run.)

Tested with D7.

Snippet Manager (snippet_manager)

d.o. page

Snippets are Twig templates that can be managed using the UI.  They can be inserted in various ways including via CKEditor, tokens.

Support for HTML, CSS, JS, and variables.

SMTP Authentication Support (smtp)

d.o. page

"Essential"

Send mail to a remote SMTP server (e.g. a transactional email provider like Postmark).  

You should put your authentication details in settings.php, rather than files you commit to the repo, for security.  

To get this to work - it was sending tests but nothing else - it seemed I needed to switch to a commit on the dev branch:

"drupal/smtp": "dev-1.x#3d354b3911409c9b11716bf2104498fb431eea72"

(note to self: see SM notes) 
 

Simple OAuth (simple_oauth)

d.o. page

An implementation of  OAuth 2.0 Authorization Framework RFC - based on a PHP League package.

Serial Field (serial)

d.o. page

"Essential"

Creates a field with a serial number, so you can have the equivalent of a MySQL AUTO_INCREMENT field for a content type (if nodes are deleted the old serial number is not reused).

Although this only has a dev branch which hasn't had updates since April 2016, it does work in D8.

There's no direct migration path previous versions, but people have written their own migrations.

Check issue queue for patches - including:

 

 

SEO Checklist (seo_checklist)

d.o. page

Shows a long checklist, split over a series of tabs, you can tick off items and some (e.g. modules you need to install) are auto-detected. See Module of the Week blog post. 

Save edit (save_edit)

d.o. page

"Essential"

Add a save and edit button

  • Needed(?) patchto ignore the ?destination=querystring on admin page. 
  • Integrated dropbutton doesn't seem to style correctly, turn this off.
Rules (rules)

d.o. page

Patch needed (the pages and roles tabs are missing on block editing form otherwise):

https://www.drupal.org/project/rules/issues/3160347

Role Watchdog (role_watchdog)

d.o. page

"Essential"

Logs every time a role is changed. Users get a Role History tab and there's a notification feature. 

Should now work fine on D8, not personally tested it (earlier: 15 Sep 2018 - there's a dev branch, but when you install it complains about missing role entity, and drush updb does nothing) 

Role Delegation (role_delegation)

d.o. page

Ordinarily, if you grant a user "Administer Users", they can do everything *except* change the roles (they don't even see the checkboxes).  You could give them 'Administer Permissions', but that also allows them to do other things.  

This module lets you set which roles they are allowed to enable for a user.  Administrators still see the roles checkboxes in the usual place (below 'status' on /user/123/edit), but everyone  gets a new 'Roles' tab.  

Works with D8 but not updated since April 2016.

Patches:

I'm not using any patches, but there are a couple RTBC-ed  the queue.

 

Restrict Login or Role Access by IP Address (restrict_by_ip)

d.o. page

Can specify single IP address or ranges. Two modes: restrict login, so they can only login from certain IPs, and restrict role, so they can login from anywhere but only access a role's permissions from the defined IPs. There's a D8 dev branch, last updated June 2016.

Responsive and off-canvas menu (responsive_menu)

d.o. page

This uses a JS library and works without a second copy of the menu in the HTML, and you don't need to make any changes to your existing navigation menu.

Look at the README file for instructions.
You need to install mm_menu and superfish in your libraries folder.

Note you're forced with the mobile version of the menu to have it expand to full depth (although the hack/workaround, if you want a top-level menu only,  is to hide the lower elements in CSS)

For hand-crated CSS / minimal javascript solutions, see https://css-tricks.com/responsive-menu-concepts/

Resave nodes (resave_nodes)

d.o. page

"Essential"

If you want to manually refresh a series of nodes.
Mainly useful if you have a rule or a hook that relies on a node being saved, to update a computed field etc.

You can choose the node type.

Required by role (required_by_role)

d.o. page

"Essential"

Set required fields more precisely.

How to verify it it's in use on any fields (so you can remove it if desired)

I wanted to upgrade a site to D10 and there was a dependency from required_by_role on required_api, which was not yet D10 compatible. I wasn't sure if I was even using required_by_role on any fields - turns out I wasn't. There's no admin UI page overview which shows it's use, but you can just run a simple SQL query:

select * from config where data like "%required_by_role%";

(the config table is where all your field settings are stored).
Refreshless (refreshless)

d.o. page

Only loads the parts of page that change when navigating between pages.

Unclear if still being maintained (no updates since Sep 2016) - part of the issue is it requires a core patch.

Redirect after login (redirect_after_login)

d.o. page

"Essential"

Sends users (depending on their role) to another page, rather than their profile, immediately after logging in.

There's a bug (patch available, fortunately) with this which will break session cookies in Drupal 9, and upgrade_status doesn't warn you about it. 

Redirect (redirect)

d.o. page

"Essential"

Add redirects, including specifying from the full range of HTTP codes (e.g 307 Temporary).  Won't let you redirect from the homepage, use Config > Basic Site Settings for that.

reCAPTCHA (recaptcha)

d.o. page

"Essential"

Use in conjunction with the Captcha module to prevent spam on forms.
As of Jan 2020, still ONLY supports v2 of Google's reCAPTCHA API (there's an active issue for v3 support)
There's also an option for non-js fallback.

Tested with D7 and D8.

Patch needed for AJAX forms (e.g. Webforms with AJAX support turned on) to stop the ReCAPTCHA UI disappearing when page is reloaded.

Real Name (realname)

d.o. page

Use tokens to merge first name, last name or any other fields.
Then you can display the realname field in various places.  

Note: you have to add code to substitute the default username in the title of user node views - e.g. in mytheme_preprocess_block(&$variables)

Raven (raven)

d.o. page

"Essential"

This module logs events and sends them to Sentry.  Sentry is an open source application you can self-install, but also a free/paid SaaS version.

For a content management framework as complex as Drupal it's worth logging errors.

Tips:

  • In Raven config, recommend not logging debug and info messages, but do select Enable fatal error handler and Enable stacktraces.
  • You can enable the javascript error handler as well, but personally I only use PHP.


Drupal benefits:

  • logs the Drupal uid
  • logs referrer URLs
  • you can tag versions (e.g. commits) as well as different environments
  • you get a full breakdown of AJAX requests

 

Rabbit hole (rabbit_hole)

d.o. page

Lets you set display, access denied, redirect or programmatic accessing for direct access to nodes.

However, note that includes both /node/xxx and the node alias, i.e. you can't just use it to restrict numeric URLs, the human friendly ones will get blocked too - so restrict_node_page_view might be more appropriate.

There's a series of submodules (such as rh_node) and without enabling them you won't see any options in the UI.
(look for the Rabbit Hole tab when editing nodes, for example).