Edit on GitHub

Visitor Info

The VisitorInfo is the central data object which is passed to every part of the targeting system. A new VisitorInfo is created for every request and enriched with data throughout the matching process. Starting from an empty object, data will be added to the VisitorInfo from several components, making it hold all relevant targeting data for the current request.

Visitor ID

To identify returning visitors, the engine needs some kind of unique identificator which will be assigned to each visitor. This identificator, internally referred to as visitor ID, is expected to be generated or set by the browser and to be stored as a cookie. When creating a VisitorInfo the targeting engine tries to load a visitor ID from the _pc_vis cookie. This ID is (by default) generated by the frontend on 2 events:

  • when loading a site with targeting enabled and no visitor ID was previously set, a random string is generated
  • if Matomo integration is configured and the tracker is loaded, the unique Matomo visitor ID will be used. This has the advantage that tracking for returining visitors or logged in users can be implemented based on Matomo's User ID feature

If you want to manually set the visitor ID in your frontend code you can do so with the following call which is exposed by the targeting JS implementation:

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

The visitor ID will be used for every action where a unique identificator is needed, e.g. when identifying returning visitors or when persisting data for a specific visitor to a targeting storage.

Upon setting a visitor ID, it is stored in 2 places of the user's browser:

  • a _pc_vis cookie
  • a _ptg.user local storage entry. This entry contains some persistent data about the user (e.g. an activity log and a list of previous visitor IDs) which may be used in later enhancements of the targeting framework. If the visitor ID cookie is missing but the local storage entry contains an ID that ID will be used to write a new cookie.

Accessing the Visitor Info in your code

Similar to the security token in Symfony's security system, you can fetch the current VisitorInfo from a VisitorInfoStorage. This storage is defined as service an can simply be injected into your services or used as controller action argument when your controllers are registered as service. You can just define the VisitorInfoStorageInterface as dependency and Symfony and the service configuration take care of the rest.

As an example, a sample service working with the VisitorInfo:

<?php

namespace AppBundle\Targeting;

use Pimcore\Targeting\VisitorInfoStorageInterface;

class MyService
{
    /**
     * @var VisitorInfoStorageInterface
     */
    private $visitorInfoStorage;

    public function __construct(VisitorInfoStorageInterface $visitorInfoStorage)
    {
        $this->visitorInfoStorage = $visitorInfoStorage;
    }

    public function getVisitorId()
    {
        // always check if there is a visitor info before trying to fetch it
        if (!$this->visitorInfoStorage->hasVisitorInfo()) {
            return null;
        }

        $visitorInfo = $this->visitorInfoStorage->getVisitorInfo();

        return $visitorInfo->getVisitorId();
    }
}

And the matching service definition:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    # if using autowiring you're already set by just defining your service - the
    # type hint against the VisitorInfoStorageInterface is enough to enable autowiring
    AppBundle\Targeting\MyService: ~

    # if you don't use autowiring you need to manually wire your dependency
    AppBundle\Targeting\MyService:
        arguments:
            $visitorInfoStorage: '@Pimcore\Targeting\VisitorInfoStorageInterface'

If your controllers are defined as services, you can make use of argument injection:

<?php

namespace AppBundle\Controller;

use Pimcore\Targeting\VisitorInfoStorageInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\JsonResponse;

class VisitorInfoController
{
    /**
     * @Route("/visitor-info")
     */
    public function visitorInfoAction(VisitorInfoStorageInterface $visitorInfoStorage)
    {
        $data = [
            'visitorId' => null
        ];

        // always check if there is a visitor info before trying to fetch it
        if ($visitorInfoStorage->hasVisitorInfo()) {
            $visitorInfo = $visitorInfoStorage->getVisitorInfo();

            $data['visitorId'] = $visitorInfo->getVisitorId();
        }

        return new JsonResponse($data);
    }
}