By default, Tweakwise Visuals serve a single image URL as defined in your data feed. Tweakwise does not provide an out-of-the-box convention to display text content tiles. This can be solved using a custom implementation using the Tweakwise JS render hook and your own frontend logic.
Implementation
To change the appearance of the tile, use the twn.product.visible hook.
Step 1: Prepare your data in Tweakwise
Add attributes to your visuals in the Tweakwise app (or your feed).
For example, add an attribute visual_title and visual_subtitle to your visual.
Consider adding an extra field for an image on different screensizes (though it's recommended to always use 1 squere image that can be always be cropped in an acceptable way).
Example: add your data to the item
<item>
<id>guided-selling-style</id>
<name>Guided Selling - Style</name>
<image><![CDATA[https://cdn.tweakwise.dev/content/shop/findyourperfectfit.png]]></image>
...
<attributes>
...
<attribute>
<name>visual_title</name>
<value><![CDATA[Find your perfect fit]]></value>
</attribute>
<attribute>
<name>visual_subtitle</name>
<value><![CDATA[Use the guided selling]]></value>
</attribute>
...
</attributes>
</item>Next, extend the API reponse with the attribute to expose the attribute so you can use it in Tweakwise JS.
Step 2: Use the visibility hook
Add the following logic to your tweakwiseListerPage function call. This listens for the item visibility event, identifies visual items, and appends the elements to the tile:
tweakwiseListerPage({
// ...
on: {
"twn.product.visible": function (event) {
const item = event.data;
if (item.type === "visual"){
tw__visual(event.targetElement, item)
}
}
}
})
.tw__visual-container{
padding: 30px;
display: flex;
flex-direction: column;
height: 100%;
justify-content: space-between;
}
.tw__visual-title {
position: relative;
z-index: 100;
color:#fff;
text-decoration: none;
font-size: 2rem;
border: none;
font-weight: bold;
}
.tw__visual-button {
position: relative;
z-index: 100;
display: inline-flex;
background: #fff000;
color: #222;
border-radius: 20px;
padding: 8px 16px;
font-weight: bold;
text-decoration: none;
border: none;
text-align: center;
align-items: center;
justify-content: center;
}
export function tw__visual(element, item){
if (item.type !== "visual") return;
const titleAttribute = item.attributes.find((o) => o.name == "visual_title");
const buttonAttribute = item.attributes.find((o) => o.name == "visual_button");
const themeAttribute = item.attributes.find((o) => o.name == "theme");
const target = element.querySelector(".twn-content-tile__link");
const container = createElement("div", "tw__visual-container");
if(titleAttribute && titleAttribute.values){
const visual_title = titleAttribute.values[0];
var title = createElement("div", "tw__visual-title", visual_title);
container.append(title);
}
if(buttonAttribute && buttonAttribute.values){
const visual_button = buttonAttribute.values[0];
var link = createElement("a", "tw__visual-button", visual_button);
container.append(link);
}
if(themeAttribute && themeAttribute.values){
container.classList.add('has-theme-' + themeAttribute.values[0])
}
target.append(container);
}