Partners
Partner carousel, deal description, and partner logo strip modules.
Partners
Description
Partners modules showcase retailer deals and logos. There are three parts: a carousel of partner deals, a description section on each deal page, and a static strip of partner logos.
How to edit
- Manage the deal and merchant content first (see Deals and Merchants) — most of what appears on these modules comes from the deal itself.
- Go to Elementor → Editor → Templates.
- Search for
Partner(or a word from the specific template name below). - Open the template and edit the static content, such as headings and captions.
- Save, then check a deal page that uses the template.
The deal cards are generated from your deal data, so edit the deal rather than the card.
Variants
Carousel
| Template | What it is |
|---|---|
Ck – Partners – Carousel | Carousel of partner deals with logos and navigation controls |
Ck – Partners – Card | The deal card used by the carousel |
Description
| Template | What it is |
|---|---|
CK – Partners – Description | The reasons to shop at a particular merchant |
CK – Partners – Description item | A single line item inside a description card |
CK – Partner – Description Buttons | The buttons in the description section |
CK – Partner – Hero Buttons | The buttons in the deal page hero |
Logos
| Template | What it is |
|---|---|
CK – Partners – Logos | A static strip of partner logos |
The two carousel templates begin with a lowercase Ck, which is just an inconsistency in the naming and does not affect how they work.
Partners carousel
A responsive carousel for displaying partner deals with logos and navigation controls. The deal cards are created by a Dynamic Posts widget using the Ck – Partners – Card template, then moved into the carousel by the script below.
Where a deal is available in only one location, the location label has the word "only" added to it automatically. Where there are several locations, they are separated by a small dot.
Partners description
This section shows the reasons to shop at a particular merchant. It includes:
- A heading
- A description
- Four value proposition cards
- A list of finance offers to choose from
The heading, description, and card labels are static content and can be edited in Elementor. The values inside the cards come from the deal:
| Card | Field on the deal | What it shows |
|---|---|---|
| Shopping method | Availability (deal_availability) | The merchant's shopping methods: in-house, in-store, online, or phone orders only |
| Minimum spend | Deal Minimum spend (deal_minimum_spend) | The minimum spend, falling back to See terms when the field is empty |
| Promotional card | Promotional Card (show_promotional_card) | The promotional card belonging to the campaign chosen on the deal |
| Offer valid until | Deal expire date (deal_expire_date) | The expiry date as day, month, and year — for example 31 July 2026 |
| Interest-free payment options | Interest free term (deal_interest_free_term) | The highest interest-free option available for the deal |
A few things worth knowing about those values:
- Promotional Card is a campaign picker rather than a simple on or off switch. Choose the campaign you want and its promotional card appears, or leave it empty for no card. The content of the card is managed on the campaign itself (see Offers & campaigns).
- Offer valid until only has a date to show when the deal's schedule is set to Specific dates.
- The interest-free list is filtered so it only shows the terms attached to the deal you are viewing, rather than every term in the system. That filtering is handled in the site's code and does not need to be set up per deal.
Partner logos
A static strip of partner logos on a light gradient background. Logos sit inside rounded white pill containers. Separate desktop and mobile images are used, so if you update the logos, update both.
Classes
Primary classes used by the partners components:
Carousel
| Class | What it's for |
|---|---|
ck-partner-carousel | Main wrapper |
partners-carousel-content-loader | Dynamic Posts loader that fetches the deals |
partners-swiper | Carousel container |
partners-carousel-interactions | Navigation and pagination area |
partners-pagination | Pagination dots |
seperator-dot | Dot between multiple locations |
Description
| Class | What it's for |
|---|---|
partners-description | Main wrapper |
partners-tiles | The value proposition card grid |
partners-tiles__min-spend / partners-tiles__interest-free | The minimum spend and interest-free cards |
ck-partner__description-item | A single line item inside a card |
partners-description__field | Rich text field content |
partners-description__count-offers | The offers count heading |
partners-offer-tile / partners-offer-tile__title / partners-offer-tile__body | Finance offer tiles |
ck-partner-description__payment-holiday | Payment holiday value used to match an offer |
partners-badge | Badge added to a matching offer title |
Logos
| Class | What it's for |
|---|---|
partners-logos | Main wrapper |
logo-wrapper | Rounded white container around each logo |
partner-image-first / partner-image-last | First and last logo rows |
partner-logos-image-desktop / partner-logos-image-mobile | Desktop and mobile logo images |
Styling is done through a combination of the built-in page builder options as well as custom CSS where needed.
Scripts
Both scripts below are added using the HTML editor template.
Partners carousel
Moves the loaded deal cards into the carousel, starts the carousel, and tidies up the location labels. This script is compiled to JavaScript before it is added.
import Swiper from "swiper";
function movePartnerContent() {
const cards = document.querySelectorAll(
".partners-carousel-content-loader .dce-posts-wrapper .dce-post-item",
);
const target = document.querySelector(".partners-swiper .swiper-wrapper");
if (target) {
cards.forEach((card) => {
target.appendChild(card);
card.classList.add("swiper-slide");
});
}
}
function createPartnerPagination() {
const paginationCount = document.querySelectorAll(
".partners-carousel-content-loader .dce-posts-wrapper .dce-post-item",
).length;
let paginationHtml = "";
for (let i = 0; i < paginationCount; i++) {
paginationHtml += `<span class="swiper-pagination-bullet"><div class="display-dot"></div></span>`;
}
const target = document.querySelector(".partners-carousel-interactions");
if (target) {
target.insertAdjacentHTML(
"beforeend",
`<div class="partners-pagination">
${paginationHtml}
</div>`,
);
}
}
function initailisePartnerSwiper() {
const swiper = new Swiper(".partners-swiper", {
spaceBetween: 12,
navigation: {
nextEl: ".partners-swiper .swiper-button-next",
prevEl: ".partners-swiper .swiper-button-prev",
},
pagination: {
el: ".partners-pagination",
clickable: true,
renderBullet: function (index: number, className: string) {
return (
'<span class="' + className + '"><div class="display-dot"></div></span>'
);
},
},
breakpoints: {
768: {
slidesPerView: 2,
},
1024: {
slidesPerView: "auto",
},
},
});
}
function modifyCardContent() {
const cards = document.querySelectorAll(".partners-swiper .swiper-slide");
cards.forEach((card) => {
const content = card.querySelector(".location-container");
if (content && content.children.length == 1) {
const label = card.querySelector(".location-label .elementor-heading-title");
if (label) {
label.textContent = label.textContent + " only";
}
} else if (content && content.children.length > 1) {
const labels = card.querySelectorAll(".location-container >div");
for (const child of labels) {
child.insertAdjacentHTML(
"afterend",
'<svg class="seperator-dot" xmlns="http://www.w3.org/2000/svg" width="2" height="2" viewBox="0 0 2 2" fill="none"><circle cx="1" cy="1" r="1" fill="currentColor"/></svg>',
);
}
}
});
}
function waitForSwiper(method: () => void) {
if (typeof Swiper !== "undefined") {
method();
} else {
const checkInterval = setInterval(() => {
if (typeof Swiper !== "undefined") {
clearInterval(checkInterval);
method();
}
}, 100);
}
}
document.addEventListener("DOMContentLoaded", async () => {
waitForSwiper(() => {
createPartnerPagination();
movePartnerContent();
initailisePartnerSwiper();
modifyCardContent();
});
});Partners description
Formats the interest-free wording, adds the bullet icons, counts the offers, appends the minimum spend to each offer, and adds the payment holiday badge.
<script>
(() => {
document.addEventListener("DOMContentLoaded", () => {
// display only the last interest free
document
.querySelectorAll(
".partners-tiles .partners-tiles__interest-free .ck-partner__description-item .elementor-heading-title",
)
.forEach((element) => {
const hasSpan = element.querySelectorAll("span").length;
if (hasSpan > 0) {
element.querySelectorAll("span").forEach((span, index) => {
if (index < hasSpan - 1) {
span.style.display = "none";
}
});
// wrap the last span in a text
const defaultText = "Up to [xx] interest-free";
const lastSpan = element.querySelector("span:last-child");
const interestFree = lastSpan.textContent.toLowerCase().trim();
if (interestFree.indexOf("month") !== -1 && /\d/.test(interestFree)) {
const text = defaultText.replace("[xx]", interestFree);
lastSpan.textContent = text;
}
}
});
// Add class to parent and child elements to display the bullet point
document
.querySelectorAll(
".partners-tiles .ck-partner__description-item .elementor-heading-title",
)
.forEach((element) => {
const hasSpan = element.querySelectorAll("span").length;
if (hasSpan > 0) {
element.classList.add("ck-partner__description-item-child-icon");
} else {
element.classList.add("ck-partner__description-item-parent-icon");
}
});
// count how many offers are displayed and update the count
let totalOffers = 0;
document
.querySelectorAll(".partners-offer-body .partners-offer-tile")
.forEach((element) => {
totalOffers++;
});
const countElement = document.querySelectorAll(
".partners-description__count-offers .elementor-heading-title",
);
if (countElement.length > 0) {
let countText = countElement[0].textContent.trim();
countText = countText
.replace("[X]", totalOffers)
.replace("[x]", totalOffers);
if (totalOffers === 1) {
countText = countText.replace("offers", "offer");
}
countElement[0].textContent = countText;
}
// add the min spent to the description of each offer
const minSpent = document.querySelector(
".partners-tiles__min-spend .ck-partner__description-item .elementor-heading-title",
);
const description = document.querySelectorAll(
".partners-offer-body .partners-offer-tile .partners-offer-tile__body",
);
if (minSpent) {
let minSpentText = minSpent.textContent.trim().toLowerCase();
if (minSpentText.includes("$") || minSpentText.match(/\d+/)) {
description.forEach((desc) => {
desc.textContent =
desc.textContent + " Min spend " + minSpent.textContent + ".";
});
}
}
// add payment holiday badge
const isPaymetnHoliday = document.querySelector(
".ck-partner-description__payment-holiday",
);
if (isPaymetnHoliday) {
const paymentHolidayText = isPaymetnHoliday.textContent.trim();
const offersTitle = document.querySelectorAll(
".partners-offer-body .partners-offer-tile .partners-offer-tile__title",
);
offersTitle.forEach((title) => {
const offerText = title.textContent.trim();
if (offerText === paymentHolidayText) {
const badge = document.createElement("span");
badge.className = "partners-badge";
badge.textContent = "Payment Holiday";
title.appendChild(badge);
}
});
}
});
})();
</script>