Skip to main content
Version: 2023.3

Frontend JavaScript

When targeting is enabled, a snippet of JavaScript in injected into every response. This snippet contains some information needed by the frontend regarding the application state (e.g. if debug mode is enabled) and includes the script pimcore/static6/js/frontend/targeting.js which handles the frontend behaviour of the targeting engine (e.g. exposes an API to set the visitor ID). The whole targeting logic is handled inside the window._ptg object.

The frontend code provides a couple of extension points which are documented on this page.

Setting a custom Visitor ID

The targeting.js exposes a method to set a visitor ID programmatically. By doing so, the visitor ID will be set and stored in the visitor ID cookie which is delivered to the backend.

_ptg.api.setVisitorId('my-custom-visitor-id');

Make sure to use a unique visitor ID for each visitor!

Change/extend the code snippet injected into the Response

The code which is injected into the response is generated by the TargetingCodeGenerator which fires a TargetingEvents::TARGETING_CODE event. This event can be used to influence data and the used template which is 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 might need data from the frontend. To make this possible, a backend implementation can call $visitorInfo->addFrontendDataProvider() during the matching process to inform the frontend that it needs data from a specific provider. These frontend data providers need to be implemented and registered to the frontend JS and are expected to deliver their data to the backend in some way (e.g. by storing data in a cookie or by 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. This information is added to the browser response, triggering the targeting.js to execute this frontend data provider. The data provider in turn stores its data as cookie which is consumed by the (backend) data provider on the next request.

Implementing a Custom Frontend Data Provider

Simply register your frontend data provider on the window._ptg.dataProviders object before targeting.js is loaded. As example a simple provider which does nothing more than logging 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);
};
}());

Taking the example listener above, we use a custom code snippet template to load our script:

{# 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 (e.g. while loading data from a data provider):

$visitorInfo->addFrontendDataProvider('userAgent');