From f7a2f2107e5118da64b64f8926949ee0b09df7cc Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Mon, 20 Jul 2026 10:13:58 +0000 Subject: [PATCH 1/4] Document BuildJsScope model and split tracking scripts Documents the JS build scope model from mautic/mautic#16660: the BuildJsScope enum, BuildJsEvent::appendJsForScope()/acceptsScope(), the /mautic-essential.js and /mautic-tracking.js endpoints, client-side runtime globals, and the backward-compatibility impact on legacy appendJs() subscribers. --- docs/mauticjs_api/tracking_script.rst | 171 ++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/docs/mauticjs_api/tracking_script.rst b/docs/mauticjs_api/tracking_script.rst index d51cba39..61d13ec8 100644 --- a/docs/mauticjs_api/tracking_script.rst +++ b/docs/mauticjs_api/tracking_script.rst @@ -64,11 +64,182 @@ You can embed ``mtc.js`` in third party websites to manage communication between To inject custom JavaScript into ``mtc.js``, use an :ref:`Event Listener` for the ``CoreEvents::BUILD_MAUTIC_JS`` event. This event receives a ``Mautic\CoreBundle\Event\BuildJsEvent`` object where ``$event->appendJs($js, $sectionName);`` can be used to inject the script's code. +.. note:: + + ``appendJs()`` still works but now delegates to ``appendJsForScope()`` with ``BuildJsScope::TRACKING``, so code appended this way is treated as ``TRACKING`` scope and only appears in tracking-enabled builds - including ``/mtc.js`` and ``/mautic-tracking.js``. It's excluded from ``/mautic-essential.js``. See :ref:`Script scopes and split scripts`. + .. warning:: Note that the code that triggers the tracking call to Mautic has a priority of -255. Thus, any listener to this event should use a priority greater than -255. .. warning:: Only use native JavaScript or MauticJS API functions since ``jQuery`` and other libraries aren't guaranteed to be available in third party websites. +.. vale off + +Script scopes and split scripts +******************************* + +.. vale on + +Mautic generates its JavaScript under a scope model defined by ``Mautic\CoreBundle\Event\BuildJsScope``, an ``enum`` with three cases: + +* ``RUNTIME`` - the anonymous bootstrap runtime that the other scopes depend on. It performs no tracking. +* ``ESSENTIAL`` - pre-consent features that need no identity, such as Dynamic Content rendering and Form injection. +* ``TRACKING`` - the identity and tracking code, including the tracking pixel and the ``/mtc/event`` call. + +When you subscribe to ``CoreEvents::BUILD_MAUTIC_JS``, the ``BuildJsEvent`` reports which scopes the current build accepts. Its constructor accepts an ``array $acceptedScopes`` that defaults to all three cases (``[BuildJsScope::RUNTIME, BuildJsScope::ESSENTIAL, BuildJsScope::TRACKING]``), so a single subscriber can contribute code to more than one generated script depending on the scope it targets. + +.. warning:: + + A subscriber that only calls the legacy ``appendJs()`` now contributes ``TRACKING`` scoped code and is therefore excluded from ``/mautic-essential.js``. If a Plugin's code must run in the essential, pre-consent context, the subscriber must call ``appendJsForScope()`` with ``BuildJsScope::ESSENTIAL`` - or ``BuildJsScope::RUNTIME`` - and/or gate on ``acceptsScope()``. + + Mind the argument positions when migrating: the legacy ``appendJs($js, $section)`` takes the section name as the 2nd argument, whereas ``appendJsForScope($js, BuildJsScope $scope, $section = '')`` inserts the scope as the 2nd argument and moves the section name to the 3rd. A mechanical find-and-replace that keeps the old argument order would pass the section string where the scope now goes. + +.. vale off + +``appendJsForScope($js, BuildJsScope $scope, $section = '')`` +============================================================= + +.. vale on + +Appends code for a specific scope. If the current build doesn't accept that scope, the call is a no-op and returns the event without appending anything. Use it when a Plugin needs to inject code into the essential, pre-consent build rather than the tracking layer. + +.. code-block:: php + + ['onBuildJs', 0], + ]; + } + + public function onBuildJs(BuildJsEvent $event) + { + $event->appendJsForScope( + << ['onBuildJs', 0], + ]; + } + + public function onBuildJs(BuildJsEvent $event) + { + if (!$event->acceptsScope(BuildJsScope::TRACKING)) { + return; + } + + $event->appendJsForScope( + << Date: Tue, 28 Jul 2026 09:30:10 +0000 Subject: [PATCH 2/4] Address review: narrow ESSENTIAL scope wording, drop RUNTIME plugin alt, clarify mauticEssentialReady loader dependency --- docs/mauticjs_api/tracking_script.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/mauticjs_api/tracking_script.rst b/docs/mauticjs_api/tracking_script.rst index 61d13ec8..af95f3b1 100644 --- a/docs/mauticjs_api/tracking_script.rst +++ b/docs/mauticjs_api/tracking_script.rst @@ -83,14 +83,14 @@ Script scopes and split scripts Mautic generates its JavaScript under a scope model defined by ``Mautic\CoreBundle\Event\BuildJsScope``, an ``enum`` with three cases: * ``RUNTIME`` - the anonymous bootstrap runtime that the other scopes depend on. It performs no tracking. -* ``ESSENTIAL`` - pre-consent features that need no identity, such as Dynamic Content rendering and Form injection. +* ``ESSENTIAL`` - pre-consent features that need no identity, such as preserving existing Dynamic Content fallback content without making a new request, and initializing Forms already embedded in that fallback content. * ``TRACKING`` - the identity and tracking code, including the tracking pixel and the ``/mtc/event`` call. When you subscribe to ``CoreEvents::BUILD_MAUTIC_JS``, the ``BuildJsEvent`` reports which scopes the current build accepts. Its constructor accepts an ``array $acceptedScopes`` that defaults to all three cases (``[BuildJsScope::RUNTIME, BuildJsScope::ESSENTIAL, BuildJsScope::TRACKING]``), so a single subscriber can contribute code to more than one generated script depending on the scope it targets. .. warning:: - A subscriber that only calls the legacy ``appendJs()`` now contributes ``TRACKING`` scoped code and is therefore excluded from ``/mautic-essential.js``. If a Plugin's code must run in the essential, pre-consent context, the subscriber must call ``appendJsForScope()`` with ``BuildJsScope::ESSENTIAL`` - or ``BuildJsScope::RUNTIME`` - and/or gate on ``acceptsScope()``. + A subscriber that only calls the legacy ``appendJs()`` now contributes ``TRACKING`` scoped code and is therefore excluded from ``/mautic-essential.js``. If a Plugin's code must run in the essential, pre-consent context, the subscriber must call ``appendJsForScope()`` with ``BuildJsScope::ESSENTIAL``. It can also gate on ``acceptsScope()`` first to skip building a payload the build would discard. Mind the argument positions when migrating: the legacy ``appendJs($js, $section)`` takes the section name as the 2nd argument, whereas ``appendJsForScope($js, BuildJsScope $scope, $section = '')`` inserts the scope as the 2nd argument and moves the section name to the 3rd. A mechanical find-and-replace that keeps the old argument order would pass the section string where the scope now goes. @@ -203,7 +203,7 @@ Mautic serves the scopes through separate endpoints so that a site can load only - Purpose * - ``/mautic-essential.js`` - ``RUNTIME`` and ``ESSENTIAL`` - - Anonymous runtime, Dynamic Content rendering, and Form injection. No tracking. + - Anonymous runtime, Dynamic Content fallback handling, and initializing Forms already embedded in fallback content. No tracking. * - ``/mautic-tracking.js`` - ``TRACKING`` - The identity and tracking layer. @@ -239,6 +239,8 @@ Because the essential script may have finished loading before your code runs - i }); } +The ``mauticEssentialReady`` event comes only from the shipped consent-managed loader snippet, not from ``/mautic-essential.js`` itself. If you use a custom loader instead, run your code from your own script tag's ``load`` or ``onload`` callback once ``MauticJS.runtimeReady === true``, or dispatch an equivalent event yourself. + Hooking into the tracking process and returning custom responses **************************************************************** From a37362dce481e7c8ec04d7c2b60a03e231ab6b04 Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Wed, 29 Jul 2026 10:24:50 +0000 Subject: [PATCH 3/4] Address @adiati98 review: active voice, hyphen aside, clear Vale FeatureList - Rewrite the appendJs note in active voice ('is treated'/'It's excluded') - Replace parentheses around the inline-code scopes array with a spaced-hyphen aside - Reword the verb 'reports' to 'exposes' to clear the Mautic.FeatureList Vale warning --- docs/mauticjs_api/tracking_script.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mauticjs_api/tracking_script.rst b/docs/mauticjs_api/tracking_script.rst index af95f3b1..c26121c6 100644 --- a/docs/mauticjs_api/tracking_script.rst +++ b/docs/mauticjs_api/tracking_script.rst @@ -66,7 +66,7 @@ This event receives a ``Mautic\CoreBundle\Event\BuildJsEvent`` object where ``$e .. note:: - ``appendJs()`` still works but now delegates to ``appendJsForScope()`` with ``BuildJsScope::TRACKING``, so code appended this way is treated as ``TRACKING`` scope and only appears in tracking-enabled builds - including ``/mtc.js`` and ``/mautic-tracking.js``. It's excluded from ``/mautic-essential.js``. See :ref:`Script scopes and split scripts`. + ``appendJs()`` still works but now delegates to ``appendJsForScope()`` with ``BuildJsScope::TRACKING``, so Mautic treats code appended this way as ``TRACKING`` scope and includes it only in tracking-enabled builds - including ``/mtc.js`` and ``/mautic-tracking.js`` - but excludes it from ``/mautic-essential.js``. See :ref:`Script scopes and split scripts`. .. warning:: Note that the code that triggers the tracking call to Mautic has a priority of -255. Thus, any listener to this event should use a priority greater than -255. @@ -86,7 +86,7 @@ Mautic generates its JavaScript under a scope model defined by ``Mautic\CoreBund * ``ESSENTIAL`` - pre-consent features that need no identity, such as preserving existing Dynamic Content fallback content without making a new request, and initializing Forms already embedded in that fallback content. * ``TRACKING`` - the identity and tracking code, including the tracking pixel and the ``/mtc/event`` call. -When you subscribe to ``CoreEvents::BUILD_MAUTIC_JS``, the ``BuildJsEvent`` reports which scopes the current build accepts. Its constructor accepts an ``array $acceptedScopes`` that defaults to all three cases (``[BuildJsScope::RUNTIME, BuildJsScope::ESSENTIAL, BuildJsScope::TRACKING]``), so a single subscriber can contribute code to more than one generated script depending on the scope it targets. +When you subscribe to ``CoreEvents::BUILD_MAUTIC_JS``, the ``BuildJsEvent`` exposes which scopes the current build accepts. Its constructor accepts an ``array $acceptedScopes`` that defaults to all three cases - ``[BuildJsScope::RUNTIME, BuildJsScope::ESSENTIAL, BuildJsScope::TRACKING]`` - so a single subscriber can contribute code to more than one generated script depending on the scope it targets. .. warning:: From c334c61b84e16c35caa5f6404b264e50b9dbfc94 Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Wed, 29 Jul 2026 11:26:28 +0000 Subject: [PATCH 4/4] chore: trigger Read the Docs rebuild Empty commit to prompt Read the Docs to re-post its build status on the current PR head, as requested by @adiati98 (RTD dashboard rebuild and close/reopen did not refresh the pending status).