Skip to content

Bound GTM inline script accumulation by the configured script limit #1224

Description

@prk-Jr

Description

Make GTM inline script accumulation respect IntegrationScriptContext::max_buffered_script_bytes, supplied from HtmlProcessorConfig::max_buffered_body_bytes (the publisher's configured buffer limit).

GoogleTagManagerIntegration::rewrite currently appends matching script fragments without reading that limit. Once a fragment contains a full GTM or GA marker, later fragments can accumulate up to the full text-node size. This also affects first-party inline scripts containing an analytics reference.

Next.js already enforces the same limit in nextjs/rsc_stream.rs::capture_fragment with FragmentState::{Idle, Buffering, BypassUntilLast}. When a script exceeds the limit, it restores buffered text and passes subsequent fragments through until the text node ends.

This is pre-existing behavior. PR #1179 makes GTM accumulation document-local to prevent cross-request residue; it does not bound that accumulation. The follow-up was requested in the sandbox lifecycle review and is deliberately separate from that PR.

Proposed approach

Apply equivalent bounded fragment capture to GTM, reusing or extracting the Next.js mechanism if appropriate. Keep the state in IntegrationDocumentState, preserve GTM's cheap gate for unrelated scripts, and restore every suppressed fragment in source order on overflow before bypassing rewriting for the rest of that text node. Avoid introducing a new configuration field.

Coordinate with #1208, which tracks overlapping script rewriters and GTM fragment ordering; this issue specifically tracks enforcing the configured accumulation limit.

Done when

  • GTM reads max_buffered_script_bytes and does not keep accumulating a text node beyond the limit.
  • Overflow restores all previously suppressed text and emits the current and remaining fragments unchanged, without truncation, duplication, or reordering.
  • A completed oversized script in a single callback passes through unchanged; scripts at or below the limit retain normal rewriting behavior.
  • Bypass resets at the end of the text node, allowing the next script to be rewritten normally.
  • State stays document-local, and interruption while buffering or bypassing leaves no residue for a second document through the same retained registry.
  • Tests cover exact-limit and over-limit inputs, overflow on intermediate and final fragments, single-callback oversized input, markers split across fragments, unrelated scripts, multiple scripts in one document, and overlapping Next.js/GTM selectors.
  • Existing GTM and Next.js fragment and interrupted-document regressions pass.

Affected area

HTML processing / JS injection

Relevant files: crates/trusted-server-core/src/integrations/google_tag_manager.rs, crates/trusted-server-core/src/integrations/nextjs/rsc_stream.rs, and crates/trusted-server-core/src/integrations/registry.rs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions