diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b1de68..e836629 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,12 @@ This library adheres to [Semantic Versioning](https://semver.org/) and [Keep a C
Nothing yet.
+## 2.2.0
+
+### Added
+
+- `GTM_Script` feature.
+
## 2.1.0
### Changed
diff --git a/docs/feature.md b/docs/feature.md
index df6f2e8..6d4a38c 100644
--- a/docs/feature.md
+++ b/docs/feature.md
@@ -14,6 +14,7 @@ interface Feature {
- [Conditional_Feature](https://github.com/alleyinteractive/wp-type-extensions/blob/main/src/alley/wp/features/class-conditional-feature.php): Boot a feature only when a condition is met.
- [Group](https://github.com/alleyinteractive/wp-type-extensions/blob/main/src/alley/wp/features/class-group.php): Group related features.
+- [GTM_Script](https://github.com/alleyinteractive/wp-type-extensions/blob/main/src/alley/wp/features/class-gtm-script.php): Add the standard Google Tag Manager script and data layer.
- [Lazy_Feature](https://github.com/alleyinteractive/wp-type-extensions/blob/main/src/alley/wp/features/class-lazy-feature.php): Instantiate a feature only when called upon.
- [Quick_Feature](https://github.com/alleyinteractive/wp-type-extensions/blob/main/src/alley/wp/features/class-quick-feature.php): Make a callable a feature.
- [Template_Feature](https://github.com/alleyinteractive/wp-type-extensions/blob/main/src/alley/wp/features/class-template-feature.php): Boot a feature only when templates load.
diff --git a/src/alley/wp/features/class-gtm-script.php b/src/alley/wp/features/class-gtm-script.php
new file mode 100644
index 0000000..b996700
--- /dev/null
+++ b/src/alley/wp/features/class-gtm-script.php
@@ -0,0 +1,81 @@
+ $data_layer
+ *
+ * @param string $tag_id GTM tag ID.
+ * @param array|stdClass|JsonSerializable $data_layer Initial data layer data.
+ */
+ public function __construct(
+ private readonly string $tag_id,
+ private readonly array|stdClass|JsonSerializable $data_layer,
+ ) {}
+
+ /**
+ * Boot the feature.
+ */
+ public function boot(): void {
+ add_action( 'wp_head', [ $this, 'render_head' ] );
+ add_action( 'wp_body_open', [ $this, 'render_body' ] );
+ }
+
+ /**
+ * Render the GTM tag in the document body.
+ */
+ public function render_head(): void {
+ $data = $this->data_layer instanceof JsonSerializable ? $this->data_layer : (object) $this->data_layer;
+ $flags = WP_DEBUG ? JSON_PRETTY_PRINT : 0;
+
+ printf(
+ <<<'HTML'
+
+
+
+
+
+HTML,
+ wp_json_encode( $data, $flags ),
+ wp_json_encode( $this->tag_id, $flags ),
+ );
+ }
+
+ /**
+ * Render the GTM tag in the document body.
+ */
+ public function render_body(): void {
+ printf(
+ <<<'HTML'
+
+
+
+HTML,
+ esc_url( "https://www.googletagmanager.com/ns.html?id={$this->tag_id}" ),
+ );
+ }
+}