Data collection

Learn how to collect information for personalization.

This guide explains how to associate the visitor with a user from your application, enrich their profile, and detect their locale, so you can deliver personalized experiences.

Identity and locale are resolved on the server. Profile and session attributes are collected in the browser, which you trigger from your templates with the croct Twig filter.

Identity

When your application has authenticated users, you can link the visitor session with the logged-in user so you can recognize them when they return.

Automatic reconciliation

When Symfony Security is configured, the bundle reconciles the visitor with the authenticated user on every request, using the user identifier as the user ID. This is enabled by default and requires no code, controlled by the identity.enabled option.

You can then recognize identified users in your queries using the user variable:

user is identified

Custom identifier

By default, the bundle uses the Symfony user identifier, such as the email or username. To reconcile with a different identifier, such as a database ID, implement the IdentityResolver interface:

src/Croct/AuthIdentityResolver.php
123456789101112131415161718192021222324
<?php
namespace App\Croct;
use App\Entity\User;use Croct\Plug\IdentityResolver;use Symfony\Bundle\SecurityBundle\Security;
final class AuthIdentityResolver implements IdentityResolver{    private Security $security;
    public function __construct(Security $security)    {        $this->security = $security;    }
    public function getUserId(): ?string    {        $user = $this->security->getUser();
        return $user instanceof User ? (string) $user->getId() : null;    }}

Then bind it to the interface so the bundle uses it instead of the default:

config/services.yaml
services:    Croct\Plug\IdentityResolver: '@App\Croct\AuthIdentityResolver'

Manual control

If you do not use Symfony Security, disable automatic reconciliation and manage identity yourself:

config/packages/croct.yaml
croct:    identity:        enabled: false

Then call identify when the user logs in and anonymize when they log out, using the injected Plug service:

src/Controller/SessionController.php
123456789101112131415161718192021222324252627282930
<?php
namespace App\Controller;
use Croct\Plug\Plug;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Attribute\Route;
final class SessionController extends AbstractController{    #[Route('/login', name: 'login', methods: ['POST'])]    public function login(Request $request, Plug $croct): Response    {        $user = $this->authenticate($request);
        $croct->identify($user->getId());
        return $this->redirectToRoute('dashboard');    }
    #[Route('/logout', name: 'logout')]    public function logout(Plug $croct): Response    {        $croct->anonymize();
        return $this->redirectToRoute('home');    }}

Profile and session attributes

Besides identity, you can enrich the visitor’s profile and session with information relevant to your business. These calls run in the browser, so you trigger them from your templates with the croct Twig filter, passing server-side values through Twig.

Profile data

Profile attributes describe the user across visits, such as their name, email, or interests. For example, to sync the signed-in user’s details into their profile:

templates/base.html.twig
123456789101112131415161718
<!DOCTYPE html><html>    <head>        <title>My application</title>    </head>    <body>        {% block body %}{% endblock %}
        {% if app.user %}            {% apply croct %}                croct.user.edit()                    .set('name', {{ app.user.fullName|json_encode|raw }})                    .set('email', {{ app.user.email|json_encode|raw }})                    .save();            {% endapply %}        {% endif %}    </body></html>

Session data

Session attributes describe the current visit, such as the plan a user is considering on the pricing page:

templates/pricing/index.html.twig
12345678910111213141516171819
{% extends 'base.html.twig' %}
{% block body %}    <select id="plan-selector">        <option value="basic">Basic</option>        <option value="premium">Premium</option>        <option value="enterprise">Enterprise</option>    </select>
    {% apply croct %}        const selector = document.getElementById('plan-selector');
        selector.addEventListener('change', () => {            croct.session.edit()                .set('plan', selector.value)                .save();        });    {% endapply %}{% endblock %}

See Data collection for the full client-side API.

Locale detection

The bundle detects the visitor locale from the request automatically and forwards it as the preferred locale, so content is returned in the matching language out of the box. This is enabled by default, controlled by the locale.enabled option.

To pin a fixed locale or set a fallback when detection is disabled, use the locale.default option:

config/packages/croct.yaml
croct:    locale:        default: en-us

For full control, implement the LocaleResolver interface and bind it the same way as a custom identity resolver:

config/services.yaml
services:    Croct\Plug\LocaleResolver: '@App\Croct\AccountLocaleResolver'