Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Symfony Usercentrics Bundle Laravel Package

t3g/symfony-usercentrics-bundle

Symfony bundle for integrating Usercentrics consent management into your app. It helps conditionally load scripts and services based on user consent, with Twig helpers and configuration for compliant cookie banners.

View on GitHub
Deep Wiki
Context7

Getting Started

The bundle wires Usercentrics (a consent management platform) into a Symfony app so you can render its CMP script and, ideally, gate other tracking scripts on the consent decisions it records.

1. Install

composer require t3g/symfony-usercentrics-bundle

2. Register the bundle (Symfony Flex usually does this for you):

// config/bundles.php
return [
    // ...
    T3G\SymfonyUsercentricsBundle\T3GSymfonyUsercentricsBundle::class => ['all' => true],
];

3. Configure your settings ID — grab it from Usercentrics Admin → Implementation → Settings ID:

# config/packages/t3g_symfony_usercentrics.yaml
t3g_symfony_usercentrics:
    settings_id: '%env(USERCENTRICS_SETTINGS_ID)%'
USERCENTRICS_SETTINGS_ID=your-settings-id-here

4. Drop the CMP script into your layout head, before any other tracking:

{# templates/base.html.twig #}
<head>
    {{ usercentrics() }}
    {# ... other head content ... #}
</head>

First use case: replace hard-coded Google Analytics / Meta Pixel / Hotjar snippets in your base.html.twig with scripts whose loading is gated by Usercentrics consent (see next section). The immediate win is compliance without manually maintaining cookie banners.

Where to look first: config/packages/*usercentrics*.yaml for the config tree, the Resources/views/ (or templates/) directory for what usercentrics() actually renders, and any UsercentricsInterface / service in src/ if you need programmatic consent checks.

Implementation Patterns

Render the CMP in the head, once

The CMP must be the first script on the page — it establishes the window.__ucCmp / UC_UI global and the consent state everything else reads. Put it above analytics, above GTM, above everything non-essential:

<head>
    <meta charset="UTF-8">
    {{ usercentrics() }}
    {% block head_extra %}{% endblock %}
</head>

Don't render it in multiple templates or per-component — that causes double initialization and broken consent callbacks.

Gating third-party scripts via data-usercentrics attributes

Usercentrics supports "blocker" mode where scripts are inert until consent via type="text/plain" and data-usercentrics="<service>":

{# Analytics only after "Google Analytics" is accepted #}
<script type="text/plain" data-usercentrics="Google Analytics">
    gtag('config', 'G-XXXXXXX');
</script>

This is the pattern to standardize on — it doesn't require your Symfony code to know about consent state at request time, and it survives full-page caching (the user's browser resolves it).

Environment-specific settings IDs

You almost never want production and dev hitting the same CMP project. Keep two IDs and switch via .env:

# config/packages/t3g_symfony_usercentrics.yaml
t3g_symfony_usercentrics:
    settings_id: '%env(USERCENTRICS_SETTINGS_ID)%'
# .env
USERCENTRICS_SETTINGS_ID=dev-settings-id

# .env.prod
USERCENTRICS_SETTINGS_ID=prod-settings-id

Usercentrics also offers a test mode toggle in the dashboard — use it when validating that consent actually unblocks tags, then flip it off.

Server-side consent checks (when you need them)

If the bundle exposes a service (check bin/console debug:container usercentrics), you can branch on consent:

use T3G\SymfonyUsercentricsBundle\Service\Usercentrics;

public function __construct(private Usercentrics $usercentrics) {}

public function index(): Response
{
    // Typically reads the Usercentrics cookie / UC_UI consent state
    $analyticsAllowed = $this->usercentrics->hasConsent('Google Analytics');

    return $this->render('page.html.twig', [
        'analyticsAllowed' => $analyticsAllowed,
    ]);
}

Caveat: anything reading a cookie is server-side and cache-hostile. If you're behind Varnish/Cloudflare/Symfony HttpCache, do not branch on consent server-side for cacheable responses — let the client do it via the text/plain pattern instead.

Twig-driven service list

If you have many tags, define them in config and loop:

# config/services_tracking.yaml
parameters:
    tracking_services:
        - { name: 'Google Analytics', src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXX' }
        - { name: 'Meta Pixel',     src: 'https://connect.facebook.net/en_US/fbevents.js' }
{% for svc in tracking_services %}
    <script async
            type="text/plain"
            data-usercentrics="{{ svc.name }}"
            src="{{ svc.src }}"></script>
{% endfor %}

This is a scalable pattern: adding a vendor becomes a YAML edit, not a template change.

Re-triggering logic on consent change

If the CMP handles script unblocking itself, you rarely need a callback. But for SPA-ish interactions or dynamic content, listen to the CMP event:

window.addEventListener('UC_UI_CMP_EVENT', (e) => {
    if (e.detail === 'ACCEPT_ALL' || e.detail === 'DENY_ALL') {
        // optionally reload or notify
    }
});

Prefer a full page reload after consent change for server-rendered Symfony apps — it's the simplest correct thing and avoids stale DOM.

Gotchas and Tips

  • Ordering is everything. If you render the CMP after GTM or after any <script> that touches consent, blockers won't fire and you'll see false "granted" states in devtools. Put {{ usercentrics() }} as the first script in <head>.

  • type="text/plain" scripts don't run under Strict CSP. If you ship a Content-Security-Policy, the CMP needs script-src entries for app.usercentrics.eu (and your blocked vendors). Missing hosts is the #1 "consent accepted but tag never fires" cause — check the browser console for CSP violations first.

  • Don't cache the rendered CMP script per-user. It's static and cacheable, but any Twig template that conditionally includes tracking services based on consent is not. If in doubt, use full-page cache for the template and let Usercentrics resolve consents client-side.

  • Cookie/consent persistence requires matching domains. The ucData/ucUserId cookies are set on the current host. Multi-domain, subdomain, or .dev environments will silently lose consent state if the CMP project's "domains" allowlist doesn't include them — add each hostname in the Usercentrics dashboard.

  • Blockers only work for scripts the bundle/data-usercentrics sees at parse time. Dynamically injected scripts (GTM tags, React widgets, lazy-loaded iframes) need explicit UC_UI.accept(...) calls or you'll need to disable tag firing in GTM itself and route through Usercentrics.

  • settings_id is public. Don't fret about it leaking — it's on every page by design. But don't put other secrets in the config file and assume it's private.

  • Debugging consent state: open devtools, run window.UC_UI.getConsentState() (or inspect the ucData cookie). If the object is undefined, the CMP didn't load — usually a CSP, ad-blocker, or wrong settings_id.

  • Ad blockers kill Usercentrics in the wild. A meaningful fraction of users have usercentrics.eu blocked; your CMP will never show and nothing will load. If you need tracking under ad-block conditions, that's a legal/product conversation, not a code one.

  • Extension point to watch: if the bundle exposes a UsercentricsRenderer or Twig extension, decorate it rather than copy-pasting the script tag into templates — that's how you'll survive version upgrades when Usercentrics changes the embed code.

  • Verify the config key name against php bin/console config:dump-reference t3g_symfony_usercentrics on the installed version. For a 0-dependency, low-star bundle, the config tree is the source of truth and has likely drifted from any README you find.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package