diff --git a/inc/Plugin.php b/inc/Plugin.php
index c9733eec93..99de360f09 100644
--- a/inc/Plugin.php
+++ b/inc/Plugin.php
@@ -401,6 +401,7 @@ private function init_common_subscribers() {
'performance_hints_admin_subscriber',
'lrc_frontend_subscriber',
'taxonomy_subscriber',
+ 'termly_subscriber',
];
$host_type = HostResolver::get_host_service();
diff --git a/inc/ThirdParty/Plugins/Cookie/Termly.php b/inc/ThirdParty/Plugins/Cookie/Termly.php
new file mode 100644
index 0000000000..809b0dbbcd
--- /dev/null
+++ b/inc/ThirdParty/Plugins/Cookie/Termly.php
@@ -0,0 +1,45 @@
+ 'exclude_termly_defer_and_delay_js',
+ 'rocket_delay_js_exclusions' => 'exclude_termly_defer_and_delay_js',
+ ];
+ }
+
+ /**
+ * Defer and delay Termly Resources
+ *
+ * @param array $exclude_delay_js Array of JS to be excluded.
+ *
+ * @return array
+ */
+ public function exclude_termly_defer_and_delay_js( array $exclude_delay_js ): array {
+ $auto_block = get_option( 'termly_display_auto_blocker', 'off' );
+ if ( 'on' !== $auto_block ) {
+ return $exclude_delay_js;
+ }
+
+ $exclude_delay_js[] = 'app.termly.io/resource-blocker/(.*)';
+
+ return $exclude_delay_js;
+ }
+}
diff --git a/inc/ThirdParty/ServiceProvider.php b/inc/ThirdParty/ServiceProvider.php
index 25cdc783e6..3b763f1e9a 100644
--- a/inc/ThirdParty/ServiceProvider.php
+++ b/inc/ThirdParty/ServiceProvider.php
@@ -11,6 +11,7 @@
use WP_Rocket\Subscriber\Third_Party\Plugins\SyntaxHighlighter_Subscriber;
use WP_Rocket\ThirdParty\Plugins\Ads\Adthrive;
use WP_Rocket\ThirdParty\Plugins\ConvertPlug;
+use WP_Rocket\ThirdParty\Plugins\Cookie\Termly;
use WP_Rocket\ThirdParty\Plugins\Ecommerce\BigCommerce;
use WP_Rocket\ThirdParty\Plugins\Ecommerce\WooCommerceSubscriber;
use WP_Rocket\ThirdParty\Plugins\I18n\TranslatePress;
@@ -98,6 +99,7 @@ class ServiceProvider extends AbstractServiceProvider {
'wpgeotargeting',
'weglot',
'contactform7',
+ 'termly_subscriber',
];
/**
@@ -227,5 +229,6 @@ public function register(): void {
$this->getContainer()->addShared( 'translatepress', TranslatePress::class );
$this->getContainer()->addShared( 'wpgeotargeting', WPGeotargeting::class );
$this->getContainer()->addShared( 'contactform7', ContactForm7::class );
+ $this->getContainer()->addShared( 'termly_subscriber', Termly::class );
}
}
diff --git a/tests/Fixtures/inc/ThirdParty/Plugins/Cookie/deferJs.php b/tests/Fixtures/inc/ThirdParty/Plugins/Cookie/deferJs.php
new file mode 100644
index 0000000000..9aeb7873e1
--- /dev/null
+++ b/tests/Fixtures/inc/ThirdParty/Plugins/Cookie/deferJs.php
@@ -0,0 +1,61 @@
+
+
+
+HTML
+;
+
+$expected = <<
+
+
+HTML
+;
+
+$expected_exclusion = <<
+
+
+HTML
+;
+
+$exclusions_list = (object) [
+ 'defer_js_external_exclusions' => [
+ 'gist.github.com',
+ '/api/scripts/lb_cs.js',
+ ],
+];
+
+return [
+ 'testShouldReturnUpdatedHTML' => [
+ 'config' => [
+ 'donotrocketoptimize' => false,
+ 'post_meta' => false,
+ 'options' => [
+ 'defer_all_js' => 1,
+ 'exclude_defer_js' => [],
+ ],
+ 'exclusions' => $exclusions_list,
+ ],
+ 'html' => $html,
+ 'expected' => $expected,
+ ],
+
+ 'testShouldEvaluateRegexPatternInOptions' => [
+ 'config' => [
+ 'donotrocketoptimize' => false,
+ 'post_meta' => false,
+ 'options' => [
+ 'defer_all_js' => 1,
+ 'exclude_defer_js' => [
+ 'app.termly.io/resource-blocker/(.*)',
+ ],
+ ],
+ 'exclusions' => $exclusions_list,
+ ],
+ 'html' => $html,
+ 'expected' => $expected_exclusion,
+ ],
+];
diff --git a/tests/Fixtures/inc/ThirdParty/Plugins/Cookie/excludeDelayJs.php b/tests/Fixtures/inc/ThirdParty/Plugins/Cookie/excludeDelayJs.php
new file mode 100644
index 0000000000..638aa72089
--- /dev/null
+++ b/tests/Fixtures/inc/ThirdParty/Plugins/Cookie/excludeDelayJs.php
@@ -0,0 +1,20 @@
+ [
+ 'config' => [
+ 'excluded' => [],
+ 'termly_display_auto_blocker' => 'off'
+ ],
+ 'expected' => []
+ ],
+ 'shouldExcludeTermlyResources' => [
+ 'config' => [
+ 'excluded' => [],
+ 'termly_display_auto_blocker' => 'on'
+ ],
+ 'expected' => [
+ 'app.termly.io/resource-blocker/(.*)',
+ ]
+ ]
+];
diff --git a/tests/Integration/inc/ThirdParty/Plugins/Cookie/deferJs.php b/tests/Integration/inc/ThirdParty/Plugins/Cookie/deferJs.php
new file mode 100644
index 0000000000..5969aa10a6
--- /dev/null
+++ b/tests/Integration/inc/ThirdParty/Plugins/Cookie/deferJs.php
@@ -0,0 +1,61 @@
+exclude_defer_js = $config['options']['exclude_defer_js'];
+ $this->defer_js = $config['options']['defer_all_js'];
+
+ add_filter( 'pre_get_rocket_option_defer_all_js', [ $this, 'set_defer_js' ] );
+ add_filter( 'pre_get_rocket_option_exclude_defer_js', [ $this, 'set_exclude_defer_js' ] );
+
+ set_transient( 'wpr_dynamic_lists', $config['exclusions'], HOUR_IN_SECONDS );
+
+ $this->assertSame(
+ $expected,
+ wpm_apply_filters_typed('string', 'rocket_buffer', $html )
+ );
+ }
+
+ public function set_defer_js() {
+ return $this->defer_js;
+ }
+
+ public function set_exclude_defer_js() {
+ return $this->exclude_defer_js;
+ }
+}
diff --git a/tests/Integration/inc/ThirdParty/Plugins/Cookie/excludeDelayJs.php b/tests/Integration/inc/ThirdParty/Plugins/Cookie/excludeDelayJs.php
new file mode 100644
index 0000000000..a10bbe9559
--- /dev/null
+++ b/tests/Integration/inc/ThirdParty/Plugins/Cookie/excludeDelayJs.php
@@ -0,0 +1,61 @@
+event = $container->get( 'event_manager' );
+ }
+
+ public function tear_down() {
+ $this->event->remove_subscriber( $this->subscriber );
+
+ parent::tear_down();
+ }
+
+ /**
+ * @dataProvider configTestData
+ */
+ public function testShouldReturnExpected( $config, $expected ) {
+ $this->subscriber = new Termly();
+ $this->event->add_subscriber( $this->subscriber );
+
+ Functions\expect( 'get_option' )
+ ->twice()
+ ->andReturn( $config['termly_display_auto_blocker'] );
+
+ $this->assertSame(
+ $expected,
+ wpm_apply_filters_typed( 'array', 'rocket_delay_js_exclusions', $config['excluded'] )
+ );
+
+ $this->assertSame(
+ $expected,
+ wpm_apply_filters_typed( 'array', 'rocket_exclude_defer_js', $config['excluded'] )
+ );
+ }
+}