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/widgetjs

Step 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.twig

Step 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.