@@ -13,6 +13,7 @@ use lol_html::{
1313 text,
1414} ;
1515
16+ use crate :: integrations:: datadome:: { DATADOME_INTEGRATION_ID , DataDomeClientTagSuppressed } ;
1617use crate :: integrations:: gpt_diagnostics:: GptDiagnosticsRequestDecision ;
1718use crate :: integrations:: {
1819 AttributeRewriteOutcome , IntegrationAttributeContext , IntegrationDocumentState ,
@@ -175,6 +176,8 @@ pub struct HtmlProcessorConfig {
175176 pub max_buffered_body_bytes : usize ,
176177 /// Request-scoped conditional diagnostics delivery decision.
177178 pub gpt_diagnostics : Option < GptDiagnosticsRequestDecision > ,
179+ /// Whether to omit Trusted Server's automatic `DataDome` client-side tag.
180+ pub suppress_datadome_client_side_tag : bool ,
178181}
179182
180183impl HtmlProcessorConfig {
@@ -196,6 +199,7 @@ impl HtmlProcessorConfig {
196199 ad_bids_state : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
197200 max_buffered_body_bytes : settings. publisher . max_buffered_body_bytes ,
198201 gpt_diagnostics : None ,
202+ suppress_datadome_client_side_tag : false ,
199203 }
200204 }
201205
@@ -223,6 +227,13 @@ impl HtmlProcessorConfig {
223227 self . gpt_diagnostics = decision;
224228 self
225229 }
230+
231+ /// Attach the request-scoped `DataDome` client-tag suppression decision.
232+ #[ must_use]
233+ pub fn with_datadome_client_tag_suppression ( mut self , suppress : bool ) -> Self {
234+ self . suppress_datadome_client_side_tag = suppress;
235+ self
236+ }
226237}
227238
228239/// Create an HTML processor with URL replacement and integration hooks.
@@ -235,6 +246,9 @@ impl HtmlProcessorConfig {
235246pub fn create_html_processor ( config : HtmlProcessorConfig ) -> impl StreamProcessor {
236247 let post_processors = config. integrations . html_post_processors ( ) ;
237248 let document_state = IntegrationDocumentState :: default ( ) ;
249+ if config. suppress_datadome_client_side_tag {
250+ document_state. get_or_insert_with ( DATADOME_INTEGRATION_ID , || DataDomeClientTagSuppressed ) ;
251+ }
238252
239253 // Simplified URL patterns structure - stores only core data and generates variants on-demand
240254 struct UrlPatterns {
@@ -692,6 +706,7 @@ mod tests {
692706 ad_bids_state : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
693707 max_buffered_body_bytes : 16 * 1024 * 1024 ,
694708 gpt_diagnostics : None ,
709+ suppress_datadome_client_side_tag : false ,
695710 }
696711 }
697712
@@ -950,6 +965,46 @@ mod tests {
950965 assert_eq ! ( config. request_scheme, "https" ) ;
951966 }
952967
968+ #[ test]
969+ fn suppressed_datadome_tag_is_not_injected_into_processed_html ( ) {
970+ let mut settings = create_test_settings ( ) ;
971+ settings
972+ . integrations
973+ . insert_config (
974+ "datadome" ,
975+ & json ! ( {
976+ "enabled" : true ,
977+ "client_side_key" : "test-client-key" ,
978+ } ) ,
979+ )
980+ . expect ( "should configure DataDome integration" ) ;
981+ let registry = IntegrationRegistry :: new ( & settings)
982+ . expect ( "should create integration registry with DataDome" ) ;
983+ let config = HtmlProcessorConfig :: from_settings (
984+ & settings,
985+ & registry,
986+ "origin.example.com" ,
987+ "test.example.com" ,
988+ "https" ,
989+ )
990+ . with_datadome_client_tag_suppression ( true ) ;
991+ let mut processor = create_html_processor ( config) ;
992+
993+ let output = processor
994+ . process_chunk ( b"<html><head></head><body>content</body></html>" , true )
995+ . expect ( "should process HTML" ) ;
996+ let html = String :: from_utf8 ( output) . expect ( "should produce UTF-8 HTML" ) ;
997+
998+ assert ! (
999+ !html. contains( "window.ddjskey" ) ,
1000+ "should omit the DataDome client configuration"
1001+ ) ;
1002+ assert ! (
1003+ !html. contains( "/integrations/datadome/tags.js" ) ,
1004+ "should omit the DataDome client tag URL"
1005+ ) ;
1006+ }
1007+
9531008 #[ test]
9541009 fn test_real_publisher_html ( ) {
9551010 // Test with publisher HTML from test_publisher.html
@@ -1539,6 +1594,7 @@ mod tests {
15391594 ad_bids_state : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
15401595 max_buffered_body_bytes : 16 * 1024 * 1024 ,
15411596 gpt_diagnostics : None ,
1597+ suppress_datadome_client_side_tag : false ,
15421598 } ;
15431599 let mut processor = create_html_processor ( config) ;
15441600 let output = processor
@@ -1613,6 +1669,7 @@ mod tests {
16131669 ad_bids_state : state,
16141670 max_buffered_body_bytes : 16 * 1024 * 1024 ,
16151671 gpt_diagnostics : None ,
1672+ suppress_datadome_client_side_tag : false ,
16161673 } ;
16171674 let mut processor = create_html_processor ( config) ;
16181675 let output = processor
@@ -1649,6 +1706,7 @@ mod tests {
16491706 ad_bids_state : state,
16501707 max_buffered_body_bytes : 16 * 1024 * 1024 ,
16511708 gpt_diagnostics : None ,
1709+ suppress_datadome_client_side_tag : false ,
16521710 } ;
16531711 let mut processor = create_html_processor ( config) ;
16541712 // Malformed HTML with two <body> elements (common in CMS template pages)
@@ -1684,6 +1742,7 @@ mod tests {
16841742 ad_bids_state : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
16851743 max_buffered_body_bytes : 16 * 1024 * 1024 ,
16861744 gpt_diagnostics : None ,
1745+ suppress_datadome_client_side_tag : false ,
16871746 } ;
16881747 let mut processor = create_html_processor ( config) ;
16891748 let output = processor
@@ -1737,6 +1796,7 @@ mod tests {
17371796 ad_bids_state : state,
17381797 max_buffered_body_bytes : 16 * 1024 * 1024 ,
17391798 gpt_diagnostics : None ,
1799+ suppress_datadome_client_side_tag : false ,
17401800 } ;
17411801 let mut processor = create_html_processor ( config) ;
17421802 let output = processor
@@ -1764,6 +1824,7 @@ mod tests {
17641824 ad_bids_state : state,
17651825 max_buffered_body_bytes : 16 * 1024 * 1024 ,
17661826 gpt_diagnostics : None ,
1827+ suppress_datadome_client_side_tag : false ,
17671828 } ;
17681829 let mut processor = create_html_processor ( config) ;
17691830 let output = processor
0 commit comments