Template Overrides
Template Overrides End-to-End
Use template overrides when you want to fully control the Engagement widget markup, styling, or behavior in your site templates while still using the plugin data and endpoints.
What You Can Override
Each widget type (ratings, likes, favorites) resolves three template handles: html, css, and js. You can set overrides globally in config, per render call in Twig, or both.
Default Template Handles
These are the built-in defaults used when no override is found.
ratings:
html: engagement/ratings/_render/widgethtml
css: engagement/ratings/_render/widgetcss
js: engagement/ratings/_render/widgetjs
likes:
html: engagement/likes/_render/widgethtml
css: engagement/likes/_render/widgetcss
js: engagement/likes/_render/widgetjs
favorites:
html: engagement/favorites/_render/widgethtml
css: engagement/favorites/_render/widgetcss
js: engagement/favorites/_render/widgetjsStep 1: Copy Plugin Templates Into Your Site
Create site template files for the widget type you are customizing. Start by copying the plugin defaults, then edit your site copies. This keeps behavior intact while you customize safely.
templates/engagement-overrides/ratings/widgethtml.twig
templates/engagement-overrides/ratings/widgetcss.twig
templates/engagement-overrides/ratings/widgetjs.twigStep 2: Add Global Overrides In config/engagement.php
Create config/engagement.php in your Craft project and map each widget type to your site template handles.
<?php
return [
'widgetTemplates' => [
'ratings' => [
'html' => 'engagement-overrides/ratings/widgethtml',
'css' => 'engagement-overrides/ratings/widgetcss',
'js' => 'engagement-overrides/ratings/widgetjs',
],
'likes' => [
'html' => 'engagement-overrides/likes/widgethtml',
'css' => 'engagement-overrides/likes/widgetcss',
'js' => 'engagement-overrides/likes/widgetjs',
],
'favorites' => [
'html' => 'engagement-overrides/favorites/widgethtml',
'css' => 'engagement-overrides/favorites/widgetcss',
'js' => 'engagement-overrides/favorites/widgetjs',
],
],
];Step 3: Override Per Render Call When Needed
Per-call overrides are useful for A/B tests, one-off components, or page-specific designs.
{{ craft.engagement.renderRating(entry.ratingField, {
widgetTemplates: {
html: 'engagement-experiments/ratings/v2/html',
css: 'engagement-experiments/ratings/v2/css',
js: 'engagement-experiments/ratings/v2/js'
}
}) }}Equivalent Per-Call Key Formats
All of these are supported. Later keys overwrite earlier ones if both are provided.
{{ craft.engagement.renderLikes(entry.likesField, {
widgetTemplates: {
html: 'my/likes/html',
css: 'my/likes/css',
js: 'my/likes/js'
},
htmlTemplate: 'my/likes/html-v2',
cssTemplate: 'my/likes/css-v2',
jsTemplate: 'my/likes/js-v2'
}) }}Supported Render Methods
You can use either the generic render method or type-specific methods.
{{ craft.engagement.render(entry.ratingField) }}
{{ craft.engagement.renderRating(entry.ratingField) }}
{{ craft.engagement.renderLikes(entry.likesField) }}
{{ craft.engagement.renderFavorite(entry.favoriteField) }}Twig Variables Available In Override Templates
All override files are rendered as Twig templates, so they receive the resolver context and can use variables directly in markup, CSS, and JS. Shared variables available to all widget types include widgetUid, previewMode, elementId, fieldId, siteId, actionUrl, loginUrl, guestInteractionMode, guestInteractionMessage, guestInteractionMessageHtml, isLoggedIn, guestAllowed, label, and widgetTemplates.
Ratings Variables
- scale
- average
- roundedAverage
- voteCount
- userRating
- icon
- emojiIcon
- customSvg
- headingText
- clickToRateText
- yourRatingText
- fillPercent
- emptyGlyph
- filledGlyph
- widgetHeadingTextRendered
- widgetClickToRateTextRendered
- widgetYourRatingTextRendered
Likes Variables
- userVote
- likeCount
- dislikeCount
- icon
- emojiIcon
- likeEmojiIcon
- dislikeEmojiIcon
- likeCustomSvg
- dislikeCustomSvg
- beforeLikeColor
- afterLikeColor
- beforeDislikeColor
- afterDislikeColor
- widgetLikeBeforeBg
- widgetLikeAfterBg
- widgetDislikeBeforeBg
- widgetDislikeAfterBg
- widgetHeadingTextRendered
- widgetLikeTextRendered
- widgetDislikeTextRendered
Favorites Variables
- isFavorited
- favoriteCount
- icon
- emojiIcon
- customSvg
- beforeFavoriteColor
- afterFavoriteColor
- widgetFavoriteBeforeBg
- widgetFavoriteAfterBg
- widgetHeadingTextRendered
- widgetFavoriteTextRendered
- widgetUnfavoriteTextRendered
Why Twig In CSS And JS Is Powerful
Because CSS and JS override files are Twig-rendered first, you can inject runtime values directly into styles and scripts without extra API calls or global data bootstrapping. This means your CSS can use per-field colors and your JS can use per-widget IDs, URLs, guest mode settings, and counts immediately at render time.
/* widgetcss.twig */
.eng-widget-{{ widgetUid }} {
--eng-accent: {{ isLoggedIn ? '#16A34A' : '#9CA3AF' }};
}
/* widgetjs.twig */
const widgetId = {{ widgetUid|json_encode|raw }};
const actionUrl = {{ actionUrl|json_encode|raw }};
const isLoggedIn = {{ isLoggedIn ? 'true' : 'false' }};
Precedence Rules
Override resolution order is highest to lowest: per-call options, then config/engagement.php widgetTemplates, then plugin defaults.
Authoring Rules For Override Files
HTML override files must output widget markup only. CSS override files must contain raw CSS only (no style tags). JS override files must contain raw JavaScript only (no script tags), because the resolver wraps CSS and JS automatically.
Recommended Workflow
Copy defaults, add a visible marker change in HTML, verify render, add CSS changes, verify render, add JS changes, verify interaction, then refactor and clean.