# 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`](https://github.com/pimcore/pimcore/blob/master/bundles/CoreBundle/Resources/public/js/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.

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

<div class="alert alert-warning">
Make sure to use a unique visitor ID for each visitor!
</div> 


## Change/extend the code snippet injected into the Response 

The code which is injected into the response is generated by the [`TargetingCodeGenerator`](https://github.com/pimcore/pimcore/blob/master/lib/Targeting/Code/TargetingCodeGenerator.php)
which fires a [TargetingEvents::TARGETING_CODE](https://github.com/pimcore/pimcore/blob/master/lib/Event/TargetingEvents.php#L30)
event. This event can be used to influence data and the used template which is used to render the code snippet:


```php
<?php

// src/AppBundle/EventListener/TargetingCodeListener.php

namespace AppBundle\EventListener;

use Pimcore\Event\Targeting\TargetingCodeEvent;
use Pimcore\Event\TargetingEvents;
use Pimcore\Targeting\Code\TargetingCodeGenerator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class TargetingCodeListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            TargetingEvents::TARGETING_CODE => 'onTargetingCode',
        ];
    }

    public function onTargetingCode(TargetingCodeEvent $event)
    {
        // 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:

```twig
{# src/AppBundle/Resources/views/Targeting/targetingCode.html.twig #} 

{% extends '@PimcoreCore/Targeting/targetingCode.html.twig' %}

{% block beforeScriptTag %}
    {{ parent() }}

    <script type="text/javascript">
        console.log('Custom targeting template');
    </script>
{% endblock %}
```

As this makes use of the same extension/code block system as the [Matomo Tracking Integration](../28_Marketing_Settings/07_Piwik.md)
see its documentation page for further details.


## 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`](https://github.com/pimcore/pimcore/blob/master/lib/Targeting/DataProvider/GeoLocation.php)
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:

```js
// src/AppBundle/Resources/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:

```twig
{# src/AppBundle/Resources/views/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):

```php
$visitorInfo->addFrontendDataProvider('userAgent');
```
