diff --git a/docs/mauticjs_api/tracking_script.rst b/docs/mauticjs_api/tracking_script.rst index d51cba39..c26121c6 100644 --- a/docs/mauticjs_api/tracking_script.rst +++ b/docs/mauticjs_api/tracking_script.rst @@ -64,11 +64,184 @@ 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 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. .. 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 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`` 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:: + + 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. + +.. 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( + <<