Frontend JavaScript
When targeting is enabled and at least one targeting rule or target group is configured, Pimcore injects a snippet
of JavaScript into HTML responses to frontend GET requests. Requests made in the admin context, non-GET
requests and non-HTML responses such as JSON or redirects are skipped. This snippet carries
information the frontend needs about the application state (for example, whether debug mode is enabled) and loads
the script bundles/pimcorepersonalization/js/targeting.js, which handles the frontend behavior of the targeting
engine (for example, it exposes an API to set the visitor ID). All targeting logic runs inside the window._ptg
object.
The frontend code provides a few extension points, documented on this page.
Setting a Custom Visitor ID
targeting.js exposes a method to set a visitor ID programmatically. This sets the visitor ID and stores it in the
visitor ID cookie delivered to the backend.
_ptg.api.setVisitorId('my-custom-visitor-id');
Use a unique visitor ID for each visitor.
Change or Extend the Code Snippet Injected into the Response
The TargetingCodeGenerator
generates the code injected into the response and fires a TargetingEvents::TARGETING_CODE event (see
Events). Use this event to influence the data and the template used to render the code snippet:
<?php
// src/EventListener/TargetingCodeListener.php
namespace App\EventListener;
use Pimcore\Bundle\PersonalizationBundle\Event\Targeting\TargetingCodeEvent;
use Pimcore\Bundle\PersonalizationBundle\Event\TargetingEvents;
use Pimcore\Bundle\PersonalizationBundle\Targeting\Code\TargetingCodeGenerator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class TargetingCodeListener implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
TargetingEvents::TARGETING_CODE => 'onTargetingCode',
];
}
public function onTargetingCode(TargetingCodeEvent $event): void
{
// add code to a code block (see TargetingCodeGenerator and the default
// template for a list of blocks and their location)
$event
->getBlock(TargetingCodeGenerator::BLOCK_BEFORE_SCRIPT)
->append([
'console.log("Custom targeting code");'
]);
// completely override the rendered template
$event->setTemplate('@App/Targeting/targetingCode.html.twig');
}
}
The listener above sets a custom template which can either extend the core one or define a completely custom output:
{# templates/Targeting/targetingCode.html.twig #}
{% extends '@PimcorePersonalization/Targeting/targetingCode.html.twig' %}
{% block beforeScriptTag %}
{{ parent() }}
<script type="text/javascript">
console.log('Custom targeting template');
</script>
{% endblock %}
Frontend Data Providers
Some conditions or data providers may need data from the frontend. To make this possible, a backend implementation
can call $visitorInfo->addFrontendDataProvider() during the matching process to tell the frontend it needs data
from a specific provider. You implement and register these frontend data providers in the frontend JS; they're
expected to deliver their data back to the backend somehow, for example by storing it in a cookie or sending it
through an async request.
Currently, this feature is only sparsely used, but the
GeoLocation
data provider, which can read the visitor location from browser geolocation data, informs the frontend that it
needs data from the geolocation frontend data provider. Pimcore adds this information to the browser response,
triggering targeting.js to execute this frontend data provider. The data provider then stores its data in a
cookie, consumed by the backend data provider on the next request.
Implementing a Custom Frontend Data Provider
Register your frontend data provider on the window._ptg.dataProviders object before targeting.js loads. Here's
a simple provider that does nothing more than log the current user agent to the console:
// /public/js/targeting/frontend.js
(function () {
window._ptg = window._ptg || {};
window._ptg.dataProviders = window._ptg.dataProviders || {};
window._ptg.dataProviders.userAgent = function() {
console.log('The current user agent is ' + navigator.userAgent);
};
}());
Reusing the example listener above, load your script through a custom code snippet template:
{# templates/Targeting/targetingCode.html.twig #}
{% block targetingScript %}
<script type="text/javascript" src="{{ asset('bundles/app/js/targeting/frontend.js') }}"></script>
{{ parent() }}
{% endblock %}
To actually execute the provider, add the following call somewhere in your matching process, for example while loading data from a data provider:
$visitorInfo->addFrontendDataProvider('userAgent');