Status | ||
---|---|---|
|
Table of Contents | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
Simple XML Sitemap
...
Setup variants
Install using composer
...
After that navigate to the configuration page for the module (admin/config/search/simplesitemap
)
On the “Settings” tab switch to the “Variants” child tab and create a variant
default | default_hreflang | Default
- the first segment is a URL segment - leave blank if you want your sitemap to live in the root of the site /sitemap.xml
and you are not planning to use any other sitemap variants (| default_hreflang | Default
).
If you are submitting your sitemap to third-party SEO services other than Google, identify their requirements to for the path of sitemap.
Configure settings
Switch to the “Settings” tab and configure the settings.
Cron settings:
Allow regeneration of the sitemap on cron.
Reduce the interval to a daily - this is optimal amount of time a good default setting, but make sure it is in alignment with the volume of published content on your project. Some projects can have sitemap regenerated less often - some more often.
The bigger is your site the higher are the chances chance that the sitemap generation will not be finished completed during one cron run so have having the interval bigger set to a higher value helps to eliminate alleviate this problem. If the sitemap isn’t finished during one cron run then it can finish during the consequent subsequent runs.
Language settings:
If your site is multilingual pay attention to the Language settings. Open “Language settings” fieldset and select “Skip non-existent translations” - this will allow to not include non-existent translation into the sitemap.
Keep the checkbox: “Remove hreflang markup in HTML” - unchecked for site that have global audience.
Advanced configuration:
If you have redirects on your site from multiple domains to one, include base URL setting.
...
Set a sitemap generation time - it influences performance so make sure it’s not too high or too low. 10 is a reasonable starting number.
Multilingual sites setup
Content Translation Redirect module
This module allows to redirect redirecting to the default language if a translation doesn’t exist.
...
In the configuration section (admin/config/regional/content-translation-redirect
)
Set redirect status to 302. Never set it to 301 unless you know the translation will never exist.
...
Preprocess hreflang attribute
It’s required to have an hreflang attribute per language and region to help Google identify what content needs to be served for visitors in particular geolocation regions. It’s also good practice for SEO. Make sure your sitemap includes an hreflang alternate for every translation. They can be created using hook_page_attachments_alter
Code Block | ||
---|---|---|
| ||
/** * Implements hook_page_attachments_alter(). */ function example_page_attachments_alter(array &$attachments) { if (isset($attachments['#attached']['html_head_link'])) { $node = \Drupal::routeMatch()->getParameter('node'); $host = \Drupal::request()->getSchemeAndHttpHost(); if ($node instanceof NodeInterface) { $siblings = \Drupal::service('example.context_helpers')->getSiblings($node); if (!empty($siblings)) { $paths = \Drupal::service('example.context_helpers')->getAliases($siblings); if (!empty($paths)) { $links = []; $props = []; foreach ($paths as $i => $path) { $props[0]['rel'] = 'alternate'; $props[0]['hreflang'] = $path['lang']; $props[0]['href'] = $host . $path['link']; $props[1] = TRUE; $links[] = $props; } } } } foreach ($attachments['#attached']['html_head_link'] as $key => $link) { if (isset($link[0]['rel']) && !empty($link[0]['rel']) && $link[0]['rel'] == 'alternate' && isset($link[0]['href'])) { $href = $link[0]['href']; $href = str_replace('https://', '', $href); $href = str_replace('http://', '', $href); $href_arr = explode('/', $href); if (isset($href_arr[2]) && $href_arr[2] !== 'node') { $attachments['#attached']['html_head_link'][$key][0]['hreflang'] = $href_arr[1] . '-' . $href_arr[2]; } } } // Setting default one. $attachments['#attached']['html_head_link'][] = [['rel' => 'alternate', 'hreflang' => 'x-default', 'href' => 'https://example.com']]; } } |
Service helper functions you should place in your service class:
Code Block | ||
---|---|---|
| ||
/**
* Helper function to get siblings of the node if sibling relationship exists.
*
* @param Node $node
* node interface.
*
* @return array $siblings
* array of node siblings ids.
*/
public function getSiblings(Node $node) {
$siblings = [];
if (isset($node->field_master_node)) {
$master = $node->field_master_node->target_id;
if (isset($master)) {
$siblings = $this->getChildNodes($master);
}
}
return $siblings;
}
/**
* Helper function to get node aliases and language / region prefix by nid.
*
* @param array $nids
* Node ids.
*
* @return array $aliases
* Array of aliases.
*/
public function getAliases($nids) {
$languages = \Drupal::languageManager()->getLanguages();
if (!is_array($nids)) {
$nids = [$nids];
}
$aliases = [];
$i = 0;
foreach ($nids as $nid) {
foreach ($languages as $lng_code => $lang) {
$alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/' . $nid, $lng_code);
if (strpos($alias, '/node/') === FALSE) {
$al_arr = explode('/', $alias);
$alias = '/' . $lng_code . $alias;
$aliases[$i]['link'] = $alias;
$aliases[$i]['lang'] = $al_arr[1] . '-' . $lng_code;
$i++;
}
}
}
return $aliases;
} |
Rabbit Hole
Rabbit hole is a module that allows you to avoid prevent bots and users to access from accessing nodes and other entities that are not meant to shouldn’t have a full page display. The example would be CTA content type nodes used inside views but not necessarily requiring full page display.
...
Code Block |
---|
composer require drupal/rabbit_hole |
Enable Rabbit Hole and , Rabbit Hole Nodes, Rabbit Hole Taxonomies, and Rabbit Hole Users.
...
The permission allows admins to still have full access to the page views of the rabbit-holed entities.
Allows to also create published pages A nice side effect of using this module is that is can be used to allow to create page previews for internal review.
Metatag ecosystem
Make sure the metatag module is installed. Global option is options are configured as well as options for content. Add a metatag field to the content types to allow editors to override keywords and descriptions as needed.
Make sure metatag is setup set up for views especially if you are using page displays on the site.
Install using composer
Code Block |
---|
composer require drupal/metatag |
Google Tag
It is preferable to install the Google Tag module vs Google Analytics since this module provides more control and flexibility in terms of installing not only Analytics tags but also any additional trackers that might be required for SEO.
Install using composer
Code Block |
---|
composer require drupal/google_tag |
Make sure to adjust the configuration to exclude any undesired tracking paths and to not track administrators and editors.
If you don’t redirect b’s needs, exclude tracking on dev and stage environments domains.
Redirect
Setup and install redirect module.
Install using composer
Code Block |
---|
composer require drupal/redirect |
Setup default settings (admin/config/search/redirect/settings
). For the first launch of a site make sure that the settings are set to 302 not 301 status. Check "Automatically create redirects when URL aliases are changed." and "Retain query string through redirect."
Make sure that you are enforcing clean and canonical URLs.
Pathauto
Install using composer
Code Block |
---|
composer require drupal/pathauto |
Update the settings for pathauto (admin/config/search/path/settings
)
Make sure that all publicly accessible entities have a URL pattern setup.
Work with the client to ensure the patterns strategy works for their business needs and minimizes the redirection effort where possible.
Pre-launch set it up so that pathauto creates a new alias and deletes the old one.
Make sure that strings that are set to be removed don’t impact existing aliases, contribute to the creation of awkward aliases because of the removal of the conjunction word, or change the meaning. Work with clients to identify potential risks.
Breadcrumbs modules
Easy Breadcrumb
Provides additional easy customization for breadcrumbs. Useful when breadcrumbs don’t have to match menu active trail.
Install using composer
Code Block |
---|
composer require drupal/easy_breadcrumb |
Adds current page as an unlinked crumb. Edit / Hide home link, exclude pages, display unlinked paths.
Menu Breadcrumb
Allows constructing a breadcrumb trail based on the active menu trail. Useful when aliases don’t match the menu trail and it is important to use the menu as a primary reference for the breadcrumb.
Install using composer
Code Block |
---|
composer require drupal/menu_breadcrumb |
Allows for easy exclusion of certain menus.
...
Review History
Who | When | Status |
---|---|---|
Bob | 20230531 | Current |