Design is not just what it looks like or feels like. Design is how it works!!
Absolutely! Gainsight PX has made significant advancements recently, thanks to the incredible analytic add-ons and improvements in the new editor. Remember the dialogue we had during our last release announcement? Well, you'll be glad to know that we have achieved that level of engagement using our own editor.
Our engagement editor goes beyond just cells and elements. It's like a canvas where you can create your own masterpiece. The real trick lies in customizing things according to your preferences by leveraging custom coding. It may sound a bit tricky, but it's never impossible. We are here to provide you with all the necessary information so that, for your next release, you won't have to worry about effectively communicating your release communications in a single slider with multiple steps.
We also completely understand the impact that drop-offs can have on your engagement, and we're here to assist you in overcoming that challenge. With this experiment, we've transformed a comprehensive 4-step slider into a single-step self-learning dialog. Now, users simply click on what interests them, and the best part is that we gather valuable insights about who is viewing what. It's a win-win situation where you can capture user preferences while delivering a more streamlined and engaging experience.
Thanks to creative minds behind this :
What went into design of this engagement:
The logic for toggling the cards and changing the image on the right side is implemented through the JavaScript function that is triggered when a card is clicked. Let's break down the logic step by step:
1. Retrieving the selected card:
- The function first checks if the clicked card is already selected by checking if the `card-selected` class is present on the card element.
- The variable `isSelectedCard` is set to `true` if the card is already selected, or `false` if it is not selected.
2. Modifying the display of other card elements:
- The function hides the element with the `id` "none_right". This element is presumably the container for the image on the right side.
- It loops through all the card elements using `Array.from(document.getElementsByClassName('card'))`.
- For each card, it removes the `card-selected` class and adds the `card` class to reset their appearance.
3. Toggling the selected card:
- If the card is already selected (`isSelectedCard` is `true`), the function removes the `card-selected` class from the clicked card.
- If the card is not selected (`isSelectedCard` is `false`), the function adds the `card-selected` class to the clicked card.
4. Displaying/hiding the card description:
- The function loops through all the elements with the class `card_desc`.
- If the card is already selected, it sets the `display` style of the description element to `'none'` to hide it.
- If the card is not selected, it sets the `display` style of the description element to `'block'` to show it.
5. Displaying/hiding the right-side content:
- The function loops through all the elements with the class `card_right`.
- If the card is already selected, it sets the `display` style of the right-side content element to `'none'` to hide it.
- If the card is not selected, it sets the `display` style of the right-side content element to `'flex'` to show it.
6. Handling the case when no card is selected:
- If there are no cards with the `card-selected` class (`!document.querySelector('.card-selected')`), it sets the `display` style of the element with the `id` "none_right" to `'flex'` to show it.
7. Tracking the card click:
- The function includes calls to Aptrinsic analytics (`aptrinsic`) to identify the user and track the card click event with relevant data.
Overall, the logic of the toggle functionality involves adding/removing classes to toggle the appearance of the clicked card, hiding/showing the description and right-side content based on the card's selection status, and updating the visibility of the image on the right side.
Code Preview :
CSS :
/* ––––– WRAPPER ––––– */
.wrapper {
display: flex;
justify-content: center;
vertical-align: middle !important;
align-items: center;
height: calc(100% - 24px);
padding: 0px 10px !important;
}
.wrapper_body {
display: flex;
flex-direction: column;
gap: 20px;
}
.card {
background: #f2f2f2 !important;
border: none;
border-radius: 20px !important;
padding: 10px 10px 10px 10px !important;
font-family: 'Noto Sans', sans-serif;
transition: 0.4s;
}
/* DCECFE */
.card:hover {
background: #d6d6d6 !important;
cursor: pointer;
font-family: 'Noto Sans', sans-serif
}
.card-selected {
background: #ffffff !important;
font-family: 'Noto Sans', sans-serif
/*border: solid #f4f4f4;*/
}
#c1_title, #c2_title, #c3_title, #c4_title {
> strong {
display: flex;
align-items: center;
gap: 4px;
}
}
.card_header
{
display: flex;
align-items: center;
gap: 15px;
}
.card_desc, .card_right {
display: none;
}
#c3_desc, #c4_desc{
margin: 5px 10px 5px 39px !important;
}
#c2_desc{
margin: 5px 10px 5px 41px !important;
}
#c1_desc{
margin: 5px 10px 5px 44px !important;
}
/*
#c3_desc, #c4_desc{
margin-left:28px;
margin-top: 4px;
}
*/
.card_right{
vertical-align: middle;
justify-content: center;
height: 100%;
align-items: center;
display: flex;
}
.px-step-navigation{
border-top:solid #f2f2f2 2px !important;
}
.px-div-group-buttons{
display: none !important;
}
/*
#px-4eb6dab6-337e-4ad4-b751-ea6c1de911de{
width: calc((40% + 0px) - 0px) !important;
}
#px-4a86d74d-d09e-45a6-b630-8204bb45a66c{
width: calc((60% + 0px) - 0px) !important;
}
*/
HTML :
<div class="wrapper">
<div class="wrapper_body">
<div class="card card-selected" id="c1_left" onclick="(function (card) {
let isSelectedCard = document.getElementById(`${card}_left`).classList.contains('card-selected');
document.getElementById('none_right').style.display = 'none';
Array.from(document.getElementsByClassName('card')).forEach(item => {
item.classList.remove('card-selected');
item.classList.add('card');
})
if (isSelectedCard) {
document.getElementById(`${card}_left`).classList.remove('card-selected');
} else {
document.getElementById(`${card}_left`).classList.add('card-selected');
}
Array.from(document.getElementsByClassName('card_desc')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_desc`).style.display = 'none';
} else {
document.getElementById(`${card}_desc`).style.display = 'block';
}
Array.from(document.getElementsByClassName('card_right')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_right`).style.display = 'none';
} else {
document.getElementById(`${card}_right`).style.display = 'flex';
}
if (!document.querySelector('.card-selected')) {
document.getElementById('none_right').style.display = 'flex';
}
})('c1'); aptrinsic('identify',{'id':'{{User.id}}','release_card1':'true'}); aptrinsic('track', 'release_card1', {'clicked': 'true', 'clickedNumber':1, 'clickedBoolean':true})">
<div class="card_header" id="c1_title">
<strong class="card_header">
<img src="https://storage.googleapis.com/froala-upload-prod/0b669fad-5e70-4250-a06f-0cd41e9feb3d/image/82a61b25-5afe-4986-bf31-d4a9519c91e3.png" width="30" id="px-d28e170f-4eba-4393-b9f8-42fabddd7be9" height="30" style="width: 30px; height: 30px;">
<span style="font-size: 16px; color: rgb(52, 56, 58); text-align: left; display: flex;">Draft Mode Improves Engagement Life-cycle Management</span>
</strong>
</div>
<div class="card_desc" id="c1_desc" style="display: block; text-align: left; margin-left: 10px;">
<span style="color: rgb(104, 93, 93); font-size: 12px;">Using the new Draft Mode, you can now make edits to active engagements without pausing or affecting the live version. Simply turn on Draft Mode, make your edits, and publish your changes.</span>
</div>
</div>
<div class="card" id="c2_left" onclick=" (function (card) {
let isSelectedCard = document.getElementById(`${card}_left`).classList.contains('card-selected');
document.getElementById('none_right').style.display = 'none';
Array.from(document.getElementsByClassName('card')).forEach(item => {
item.classList.remove('card-selected');
item.classList.add('card');
})
if (isSelectedCard) {
document.getElementById(`${card}_left`).classList.remove('card-selected');
} else {
document.getElementById(`${card}_left`).classList.add('card-selected');
}
Array.from(document.getElementsByClassName('card_desc')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_desc`).style.display = 'none';
} else {
document.getElementById(`${card}_desc`).style.display = 'block';
}
Array.from(document.getElementsByClassName('card_right')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_right`).style.display = 'none';
} else {
document.getElementById(`${card}_right`).style.display = 'flex';
}
if (!document.querySelector('.card-selected')) {
document.getElementById('none_right').style.display = 'flex';
}
})('c2'); aptrinsic('identify',{'id':'{{User.id}}','release_card2':'true'}); aptrinsic('track', 'release_card2', {'clicked': 'true', 'clickedNumber':1, 'clickedBoolean':true});">
<div id="c2_title">
<strong class="card_header">
<img src="https://storage.googleapis.com/froala-upload-prod/0b669fad-5e70-4250-a06f-0cd41e9feb3d/image/76b5e51a-b67b-43f1-b300-d7aee4d22941.png" style="width: 28px; text-align: center; height: 25px;" width="28" height="25" id="px-2d18506e-494d-4e15-9f4d-bda2f49d800d">
<span style="font-size: 16px; color: rgb(52, 56, 58); display: flex;">View Audience Targeting Estimates for Engagements</span>
</strong>
</div>
<div class="card_desc" id="c2_desc" style="display: none; text-align: left; margin-left: 10px;">
<span style="color: rgb(104, 93, 93); font-size: 12px;">Optimising your targeting strategy just got easier. With the new Preview option, you can estimate the potential target audience before launching an In-App engagement - even with complex audience rules.</span>
</div>
</div>
<div class="card" id="c3_left" onclick="(function (card) {
let isSelectedCard = document.getElementById(`${card}_left`).classList.contains('card-selected');
document.getElementById('none_right').style.display = 'none';
Array.from(document.getElementsByClassName('card')).forEach(item => {
item.classList.remove('card-selected');
item.classList.add('card');
})
if (isSelectedCard) {
document.getElementById(`${card}_left`).classList.remove('card-selected');
} else {
document.getElementById(`${card}_left`).classList.add('card-selected');
}
Array.from(document.getElementsByClassName('card_desc')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_desc`).style.display = 'none';
} else {
document.getElementById(`${card}_desc`).style.display = 'block';
}
Array.from(document.getElementsByClassName('card_right')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_right`).style.display = 'none';
} else {
document.getElementById(`${card}_right`).style.display = 'flex';
}
if (!document.querySelector('.card-selected')) {
document.getElementById('none_right').style.display = 'flex';
}
})('c3'); aptrinsic('identify',{'id':'{{User.id}}','release_card3':'true'}); aptrinsic('track', 'release_card3', {'clicked': 'true', 'clickedNumber':1, 'clickedBoolean':true});">
<div id="c3_title">
<strong class="card_header">
<img src="https://storage.googleapis.com/froala-upload-prod/0b669fad-5e70-4250-a06f-0cd41e9feb3d/image/1aef04f0-8117-4559-9675-c1219163a1ae.png" style="width: 25px; text-align: center; height: 25px;" width="25" height="25">
<span style="font-size: 16px; color: rgb(52, 56, 58); display: flex;">Enhanced Performance Analysis with Query Builder</span>
</strong>
</div>
<div class="card_desc" id="c3_desc" style="display: none; text-align: left; margin-left: 8px;">
<span style="color: rgb(104, 93, 93); font-size: 12px;">With the new Group By options and the ability to analyze all qualifying custom events, you can now conduct in-depth performance analysis of Features, Engagements, and Custom Events using Query Builder.</span>
</div>
</div>
<div class="card" id="c4_left" onclick="(function (card) {
let isSelectedCard = document.getElementById(`${card}_left`).classList.contains('card-selected');
document.getElementById('none_right').style.display = 'none';
Array.from(document.getElementsByClassName('card')).forEach(item => {
item.classList.remove('card-selected');
item.classList.add('card');
})
if (isSelectedCard) {
document.getElementById(`${card}_left`).classList.remove('card-selected');
} else {
document.getElementById(`${card}_left`).classList.add('card-selected');
}
Array.from(document.getElementsByClassName('card_desc')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_desc`).style.display = 'none';
} else {
document.getElementById(`${card}_desc`).style.display = 'block';
}
Array.from(document.getElementsByClassName('card_right')).forEach(item => {
item.style.display = 'none';
})
if (isSelectedCard) {
document.getElementById(`${card}_right`).style.display = 'none';
} else {
document.getElementById(`${card}_right`).style.display = 'flex';
}
if (!document.querySelector('.card-selected')) {
document.getElementById('none_right').style.display = 'flex';
}
})('c4'); aptrinsic('identify',{'id':'{{User.id}}','release_card4':'true'}); aptrinsic('track', 'release_card4', {'clicked': 'true', 'clickedNumber':1, 'clickedBoolean':true});">
<div id="c4_title">
<strong class="card_header">
<img src="https://storage.googleapis.com/froala-upload-prod/0b669fad-5e70-4250-a06f-0cd41e9feb3d/image/56acb429-50ef-4c91-aab8-f9d94ee284f9.png" style="width: 25px; text-align: center; height: 25px;" width="25" height="25" id="px-24f9ee96-102c-4fcc-b021-2f764bcb98f0">
<span style="font-size: 16px; color: rgb(52, 56, 58); display: flex;">
<strong>Streamlined Search with New Filters in Product Mapper</strong>
</span>
</strong>
</div>
<div class="card_desc" id="c4_desc" style="display: none; text-align: left; margin-left: 8px;">
<span style="color: rgb(104, 93, 93); font-size: 12px;">New Filters in the Product Feature Tree offer a quick and efficient way of searching for features and modules using multiple criteria.</span>
</div>
</div>
</div>
</div>
This experiment worked well in our case and we were able to communicate all the info in a more concise manner in a single dialog. We are sure you are already thinking how this logic can fit into your communications, please do share your use-cases with us and the community. Let’s do this together!
Happy PX-ing!