Navigation Integration
Audience: Site builders and administrators who want CRM links in the Drupal admin toolbar. For developer details on the underlying implementation, see Implementation details below.
The CRM module provides optional integration with Drupal core's Navigation module. When Navigation is enabled alongside CRM, a CRM item appears in the admin toolbar with a submenu of the main CRM administration sections.
The Navigation module is not required. CRM works fully without it; the toolbar integration activates automatically when both modules are enabled.
Requirements
- CRM module enabled.
- Drupal core Navigation module enabled
(
Admin > Extend, ordrush pm:enable navigation). - Users must have the
access navigationpermission and at least one CRM permission (such asadminister crm) to see the CRM toolbar links.
What You Get
CRM toolbar item
A top-level CRM link appears in the Navigation toolbar. Clicking it goes
directly to the contact collection (/admin/crm/contacts).
CRM submenu
Below the top-level item, a submenu is automatically derived from the CRM administration local tasks. The default items are:
| Submenu item | Destination |
|---|---|
| Contacts | /admin/crm/contacts |
| Methods | /admin/crm/contact-methods |
| Relationships | /admin/crm/relationships |
The submenu is built dynamically — if a contributed module or custom code adds
a local task with parent_id: crm.admin, it will appear here automatically.
Contact page tabs
When Navigation is enabled, Drupal's Navigation module suppresses the standard local-tasks block on most pages. CRM overrides this behavior on contact canonical and relationship/comment routes so the contact tabs (Summary, Relationship, Comments) continue to display as a single merged row.
Permissions
| Permission | Effect |
|---|---|
access navigation |
Required to see and use the Navigation toolbar at all. |
administer crm |
Grants access to the CRM toolbar item and its submenu. |
view any crm contact (or bundle-specific) |
Required to visit the contact canonical route where tabs are shown. |
Users who have access navigation but no CRM permissions will see the
Navigation toolbar without any CRM-specific links.
Enabling Navigation alongside CRM
# Using Drush
ddev drush pm:enable navigation -y
Clear caches after enabling:
ddev drush cache:rebuild
No additional configuration is needed. CRM detects the presence of the Navigation module at runtime and activates the integration automatically.
Troubleshooting
CRM links do not appear in the toolbar
- Verify Navigation is enabled — Go to
Admin > Extendand confirm the Navigation module is checked. - Check user permissions — The user needs both
access navigationand a CRM permission such asadminister crm. Go toAdmin > People > Permissionsto review. - Clear caches — After enabling Navigation or changing permissions, run
ddev drush cache:rebuildor use the toolbar cache-clear button.
Contact tabs show two rows or no tabs on the contact page
- Confirm Navigation is enabled. Without it, the tab-merging behavior does not activate and tabs render using the standard Drupal layout.
- If tabs are entirely missing, confirm the local tasks block is placed in a visible region.
Implementation details
Audience: Module developers and contributors.
The integration is implemented across three files and adds no required
dependency to crm.info.yml.
Toolbar links (crm.links.menu.yml)
Two entries in crm.links.menu.yml seed the toolbar integration. These are
separate from the standard CRM admin menu links in the same file; the standard
admin menu works independently of the Navigation module.
crm.navigation.content— the top-level CRM toolbar link, targeting the contact collection with a Navigation icon (pack_id: navigation,icon_id: entity-user-collection).crm.navigation.content.items— a placeholder that points toNavigationDeriver, which replaces it with dynamic submenu links at discovery time.
Dynamic submenu (NavigationDeriver)
Drupal\crm\Plugin\Derivative\NavigationDeriver implements
ContainerDeriverInterface. Its getDerivativeDefinitions() method:
- Loads all local task definitions via
plugin.manager.menu.local_task. - Filters to tasks whose
parent_idiscrm.admin. - Sorts by
weight. - Emits one menu link derivative per task, all parented to
crm.navigation.content.
Because it reads live plugin definitions, the submenu stays in sync with any task added by CRM or third-party modules without additional configuration.
Contact page tabs (ContactHooks)
Drupal\crm\Hook\ContactHooks implements two hooks that run after the
Navigation module's own implementations (order: new OrderAfter(['navigation'])):
hook_block_build_local_tasks_block_alter— removes the#accessFALSE that Navigation sets on the local tasks block for these routes:entity.crm_contact.canonical,crm.contact_relationship,crm.contact_comment.hook_block_view_local_tasks_block_alter— attaches a#pre_rendercallback (ContactHooks::mergeSecondaryIntoPrimary) that folds secondary tabs into the primary row so only one tab row is rendered, without modifying task definitions for other consumers including Navigation itself.
Testing
The integration is covered by a functional test suite:
| Test class | What it covers |
|---|---|
NavigationIntegrationTest::testCrmNavigationMenuLinkVisible |
CRM toolbar item visible to admin |
NavigationIntegrationTest::testCrmNavigationDerivedSubmenuItems |
Contacts/Methods/Relationships submenu |
NavigationIntegrationTest::testCrmNavigationRequiresPermission |
No CRM links without CRM permission |
NavigationIntegrationTest::testContactTabsSingleRowWithNavigation |
Single-row tabs on contact routes |
ContactHooksNavigationTest (Kernel) |
block_build/view_local_tasks_block_alter hook logic in isolation |
To run the Navigation-specific tests:
ddev phpunit --filter=NavigationIntegrationTest
ddev phpunit --filter=ContactHooksNavigationTest
Related documentation
- Contact entity — contact fields and bundles
- Comment integration — commenting on contacts, including the Comments tab route that the Navigation module must not suppress
- Group integration — group-based access control for contacts
- Views integration — exposing CRM data in Views