Use of Carousels in Adobe Journey Optimiser In-App Channel | Community
Skip to main content
Level 2
February 2, 2026
Solved

Use of Carousels in Adobe Journey Optimiser In-App Channel

  • February 2, 2026
  • 3 replies
  • 51 views

Has anyone used Carousels in Adobe Journey optimizer InApp Configuration? the requirements are to display multiple images under one In-App message content.

Let me know if there are any feedback or findings across this.

Thanks 

Prate

    Best answer by PrateekWa1

    @Manoj_Kumar thank you. have you done this in past? any example that could please help support this? we are looking to this now.

    3 replies

    Manoj_Kumar
    Community Advisor
    Community Advisor
    February 3, 2026

    Hi ​@PrateekWa1  You can use the Custom message layout and use HTML to display a carousel in IAM.

    Manoj  | https://themartech.pro
    PrateekWa1AuthorAccepted solution
    Level 2
    February 3, 2026

    @Manoj_Kumar thank you. have you done this in past? any example that could please help support this? we are looking to this now.

    Manoj_Kumar
    Community Advisor
    Community Advisor
    February 4, 2026

    @PrateekWa1 Here is a sample code you can use to create an IAM.

     


     

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>In-App Message Carousel</title>
    <style>
    * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    }

    body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    }

    .carousel-container {
    max-width: 500px;
    width: 100%;
    background: white;
    border-radius: 20px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    overflow: hidden;
    position: relative;
    }

    .carousel-wrapper {
    position: relative;
    overflow: hidden;
    }

    .carousel-slides {
    display: flex;
    transition: transform 0.5s ease-in-out;
    }

    .carousel-slide {
    min-width: 100%;
    padding: 40px 30px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    }

    .slide-icon {
    font-size: 60px;
    margin-bottom: 20px;
    }

    .slide-title {
    font-size: 24px;
    font-weight: 700;
    color: #2d3748;
    margin-bottom: 12px;
    }

    .slide-description {
    font-size: 16px;
    color: #718096;
    line-height: 1.6;
    margin-bottom: 20px;
    }

    .slide-cta {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    border: none;
    padding: 12px 32px;
    border-radius: 25px;
    font-size: 16px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.2s, box-shadow 0.2s;
    }

    .slide-cta:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
    }

    .slide-cta:active {
    transform: translateY(0);
    }

    .carousel-controls {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px 30px;
    background: #f7fafc;
    }

    .carousel-dots {
    display: flex;
    gap: 8px;
    }

    .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #cbd5e0;
    cursor: pointer;
    transition: all 0.3s;
    }

    .dot.active {
    background: #667eea;
    width: 24px;
    border-radius: 4px;
    }

    .carousel-nav {
    display: flex;
    gap: 10px;
    }

    .nav-btn {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    background: white;
    color: #667eea;
    font-size: 18px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }

    .nav-btn:hover {
    background: #667eea;
    color: white;
    transform: scale(1.1);
    }

    .nav-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
    }

    .nav-btn:disabled:hover {
    background: white;
    color: #667eea;
    transform: scale(1);
    }

    .close-btn {
    position: absolute;
    top: 15px;
    right: 15px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: none;
    background: rgba(0, 0, 0, 0.05);
    color: #4a5568;
    font-size: 20px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    z-index: 10;
    }

    .close-btn:hover {
    background: rgba(0, 0, 0, 0.1);
    transform: rotate(90deg);
    }
    </style>
    </head>
    <body>
    <div class="carousel-container">
    <button class="close-btn" onclick="closeCarousel()">×</button>

    <div class="carousel-wrapper">
    <div class="carousel-slides" id="carouselSlides">
    <!-- Slide 1 -->
    <div class="carousel-slide">
    <div class="slide-icon">🎉</div>
    <h2 class="slide-title">Welcome to Our App!</h2>
    <p class="slide-description">Discover amazing features that will help you get more done in less time.</p>
    <button class="slide-cta" onclick="handleCTA(0)">Get Started</button>
    </div>

    <!-- Slide 2 -->
    <div class="carousel-slide">
    <div class="slide-icon">🚀</div>
    <h2 class="slide-title">Boost Your Productivity</h2>
    <p class="slide-description">Unlock powerful tools designed to streamline your workflow and maximize efficiency.</p>
    <button class="slide-cta" onclick="handleCTA(1)">Learn More</button>
    </div>

    <!-- Slide 3 -->
    <div class="carousel-slide">
    <div class="slide-icon">✨</div>
    <h2 class="slide-title">New Features Available</h2>
    <p class="slide-description">Check out our latest updates and improvements crafted just for you.</p>
    <button class="slide-cta" onclick="handleCTA(2)">Explore Now</button>
    </div>

    <!-- Slide 4 -->
    <div class="carousel-slide">
    <div class="slide-icon">💎</div>
    <h2 class="slide-title">Upgrade to Premium</h2>
    <p class="slide-description">Get access to exclusive features and take your experience to the next level.</p>
    <button class="slide-cta" onclick="handleCTA(3)">Upgrade</button>
    </div>
    </div>
    </div>

    <div class="carousel-controls">
    <div class="carousel-dots" id="carouselDots"></div>
    <div class="carousel-nav">
    <button class="nav-btn" id="prevBtn" onclick="previousSlide()">‹</button>
    <button class="nav-btn" id="nextBtn" onclick="nextSlide()">›</button>
    </div>
    </div>
    </div>

    <script>
    let currentSlide = 0;
    const slides = document.querySelectorAll('.carousel-slide');
    const slidesContainer = document.getElementById('carouselSlides');
    const dotsContainer = document.getElementById('carouselDots');
    const totalSlides = slides.length;
    let autoPlayInterval;

    // Create dots
    function createDots() {
    for (let i = 0; i < totalSlides; i++) {
    const dot = document.createElement('div');
    dot.classList.add('dot');
    if (i === 0) dot.classList.add('active');
    dot.addEventListener('click', () => goToSlide(i));
    dotsContainer.appendChild(dot);
    }
    }

    // Update slide position
    function updateSlide() {
    slidesContainer.style.transform = `translateX(-${currentSlide * 100}%)`;

    // Update dots
    const dots = document.querySelectorAll('.dot');
    dots.forEach((dot, index) => {
    dot.classList.toggle('active', index === currentSlide);
    });

    // Update nav buttons
    document.getElementById('prevBtn').disabled = currentSlide === 0;
    document.getElementById('nextBtn').disabled = currentSlide === totalSlides - 1;
    }

    // Go to specific slide
    function goToSlide(index) {
    currentSlide = index;
    updateSlide();
    resetAutoPlay();
    }

    // Next slide
    function nextSlide() {
    if (currentSlide < totalSlides - 1) {
    currentSlide++;
    updateSlide();
    resetAutoPlay();
    }
    }

    // Previous slide
    function previousSlide() {
    if (currentSlide > 0) {
    currentSlide--;
    updateSlide();
    resetAutoPlay();
    }
    }

    // Auto play
    function startAutoPlay() {
    autoPlayInterval = setInterval(() => {
    if (currentSlide < totalSlides - 1) {
    nextSlide();
    } else {
    currentSlide = 0;
    updateSlide();
    }
    }, 5000); // Change slide every 5 seconds
    }

    function resetAutoPlay() {
    clearInterval(autoPlayInterval);
    startAutoPlay();
    }

    // Handle CTA clicks
    function handleCTA(slideIndex) {
    console.log(`CTA clicked on slide ${slideIndex + 1}`);
    alert(`Action triggered for slide ${slideIndex + 1}`);
    // Add your custom logic here
    }

    // Close carousel
    function closeCarousel() {
    console.log('Carousel closed');
    document.querySelector('.carousel-container').style.display = 'none';
    // Add your custom close logic here
    }

    // Keyboard navigation
    document.addEventListener('keydown', (e) => {
    if (e.key === 'ArrowLeft') previousSlide();
    if (e.key === 'ArrowRight') nextSlide();
    if (e.key === 'Escape') closeCarousel();
    });

    // Touch swipe support
    let touchStartX = 0;
    let touchEndX = 0;

    slidesContainer.addEventListener('touchstart', (e) => {
    touchStartX = e.changedTouches[0].screenX;
    });

    slidesContainer.addEventListener('touchend', (e) => {
    touchEndX = e.changedTouches[0].screenX;
    handleSwipe();
    });

    function handleSwipe() {
    if (touchEndX < touchStartX - 50) nextSlide();
    if (touchEndX > touchStartX + 50) previousSlide();
    }

    // Initialize
    createDots();
    updateSlide();
    startAutoPlay();
    </script>
    </body>
    </html>

     

    Manoj  | https://themartech.pro
    giriprasathb
    Level 2
    February 3, 2026

    Hi ​@PrateekWa1,As of now,Adobe Journey Optimizer (AJO) In-App Messaging does not support a native carousel component in the standard configuration. The available templates allow only a single image per message.

     

    If multiple images are required within a single In-App experience, the recommended approach is to pass multiple image assets in the payload and implement the carousel rendering on the mobile app side using the AEP Mobile SDK.

     

    At this time, there is no out-of-the-box carousel option available in the AJO In-App visual editor.

    Thanks,
    Giriprasath B

    Level 2
    February 3, 2026

    Okay, we can try this. Thanks for the input, really appreciated.

    Pulkit_Jain_
    Adobe Employee
    Adobe Employee
    February 4, 2026

    @PrateekWa1 

    In‑App templates do not include a Carousel component currently but you can implement a carousel by using a Full‑screen Custom template i.e you can upload HTML/CSS that includes your own carousel behavior with multiple images- fully controlled by the app via HTML.