# Checkout

Accept payments with an embeddable checkout, modular components, or no-code links.

## Find your solution

div
div
label

      Do you have development capacity to build your payment integration?
    
select
option
Select an option...
option
Yes, we have development capacity
option
No, we need a no-code solution
div
label

      Do you have a website or app where the payment needs to take place?
    
select
option
Select an option...
option
Yes, payment must happen inside our website or app
option
No, we don
'
t have a website or app — we just need a hosted payment page we can share with customers
option
We have a website but also want a standalone payment page option
div
label

      How fast do you need to go live?
    
select
option
Select an option...
option
As fast as possible — hours, not weeks
option
We can invest time to build the right experience
div
label

      How much control do you need over the design of your payment form?
    
select
option
Select an option...
option
Full control — every field, button and layout must match our brand exactly
option
Standard branding is enough — colours, fonts, button shape, component size
style

.checkout-recommendation-system {
  margin: 2rem 0;
  padding: 1.5rem;
  background: linear-gradient(135deg, var(--white) 0%, var(--bright-blue-01) 100%);
  border-radius: 8px;
  border: 1px solid var(--bright-blue-02);
}

.recommendation-selector {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 600px;
  margin-bottom: 1.5rem;
}

.recommendation-selector label {
  color: var(--bright-blue-09);
  font-size: 1rem;
}

.recommendation-dropdown {
  padding: 0.75rem 2.5rem 0.75rem 1rem;
  font-size: 1rem;
  border: 2px solid var(--grey-02);
  border-radius: 6px;
  background-color: white;
  cursor: pointer;
  transition: all 0.2s ease;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 12px;
}

.recommendation-dropdown:hover {
  border-color: #0600ff;
}

.recommendation-dropdown:focus {
  outline: none;
  border-color: #0600ff;
  box-shadow: 0 0 0 3px rgba(6, 0, 255, 0.1);
}

h2 {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.recommended-badge {
  display: inline-block;
  background: linear-gradient(135deg, var(--green) 0%, var(--bright-blue) 100%);
  color: white;
  padding: 0.25rem 0.75rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
  line-height: 1.5;
  flex-shrink: 0;
}

.horizontal-tab.recommended {
  position: relative;
}

.horizontal-tab.recommended::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(135deg, var(--green) 0%, var(--bright-blue) 100%);
  border-radius: 4px 4px 0 0;
}

script

(function() {
  // Prevent multiple initialisations
  if (window.__checkoutRecommendationInitialized) return;
  window.__checkoutRecommendationInitialized = true;
  
  const DEBUG = true;
  let currentRecommendation = null;
  let isManualTabSwitch = false;
  
  function log(...args) {
    if (DEBUG) console.log('[Checkout Rec]', ...args);
  }
  
  // Recommendation logic
  const recommendationRules = {
    q1: {
      'no': { 
        recommend: 'Links', 
        copy: 'Links is the only product that requires zero coding — merchants create and share payment links directly from the Unity Portal.', 
        showNext: false 
      }
    },
    q2: {
      'no-website': { 
        recommend: 'Links', 
        copy: 'Links is the natural fit — it generates a hosted payment page that works anywhere, no website required.', 
        showNext: false 
      },
      'embedded': { 
        recommend: null,
        showNext: true
      },
      'both': { 
        recommend: null,
        showNext: true
      }
    },
    q3: {
      'fast': { 
        recommend: null,
        copy: null,
        showNext: false,
        dynamic: true // Special flag to handle based on Q2
      },
      'invest-time': { 
        recommend: null,
        copy: null,
        showNext: true,
        dynamic: true // Special flag to handle based on Q2
      }
    },
    q4: {
      'full': { 
        recommend: 'Components', 
        copy: 'Components lets you mount each input individually, position them freely, replace PXP UI elements with your own, and apply unlimited custom styling with no constraints.', 
        showNext: false 
      },
      'standard': { 
        recommend: 'Drop-in',
        secondary: 'Links',
        copy: 'Drop-in and Links both offer standard branding control. Drop-in offers meaningful branding control via Unity: accent colour, body text colour, background colour, button text/background colour, button shape, font family including custom Google Fonts, and component size scaling. Links provides a fully hosted payment page with customisable branding and appearance.',
        showNext: false 
      }
    }
  };

  function getRecommendation() {
    const q1 = document.getElementById('developer-availability')?.value;
    const q2 = document.getElementById('website-app')?.value;
    const q3 = document.getElementById('timeline')?.value;
    const q4 = document.getElementById('design-control')?.value;
    
    // Check Q4 first (deepest level) with conditional logic
    if (q4 && recommendationRules.q4[q4]) {
      // Special case: Q1=yes, Q2=embedded, Q3=invest-time, Q4=standard → Drop-in only
      if (q4 === 'standard' && q2 === 'embedded') {
        return {
          recommend: 'Drop-in',
          secondary: null,
          copy: 'Drop-in offers meaningful branding control via Unity: accent colour, body text colour, background colour, button text/background colour, button shape, font family including custom Google Fonts, and component size scaling.',
          showNext: false
        };
      }
      
      return recommendationRules.q4[q4];
    }
    
    // Check Q3 with dynamic logic based on Q2
    if (q3 && recommendationRules.q3[q3]) {
      const q3Rule = recommendationRules.q3[q3];
      
      if (q3 === 'fast') {
        // Q3 "fast" logic depends on Q2
        if (q2 === 'embedded') {
          // Q1=yes, Q2=embedded, Q3=fast → Drop-in only
          return {
            recommend: 'Drop-in',
            copy: 'Drop-in is a plug-and-play single SDK integration, designed to get merchants live in days with all payment methods included out of the box.',
            showNext: false
          };
        } else if (q2 === 'both') {
          // Q1=yes, Q2=both, Q3=fast → Drop-in and Links
          return {
            recommend: 'Drop-in',
            secondary: 'Links',
            copy: 'Drop-in and Links are both designed for speed. Drop-in is a plug-and-play single SDK integration that gets you live in days with all payment methods included. Links requires zero coding — create and share payment links directly from the Unity Portal.',
            showNext: false
          };
        }
      } else if (q3 === 'invest-time') {
        // Q3 "invest-time" logic depends on Q2
        if (q2 === 'embedded') {
          // Q1=yes, Q2=embedded, Q3=invest-time → Components and Drop-in
          return {
            recommend: 'Components',
            secondary: 'Drop-in',
            copy: 'Components and Drop-in are both designed for embedded payments. Components lets you mount each input individually and apply unlimited custom styling. Drop-in is a plug-and-play single SDK integration that gets you live in days with all payment methods included.',
            showNext: false
          };
        } else if (q2 === 'both') {
          // Q1=yes, Q2=both, Q3=invest-time → Show Q4
          return { recommend: null, showNext: true };
        }
      }
    }
    
    // Check Q2
    if (q2 && recommendationRules.q2[q2]) {
      return recommendationRules.q2[q2];
    }
    
    // Check Q1
    if (q1 && recommendationRules.q1[q1]) {
      return recommendationRules.q1[q1];
    }
    
    return null;
  }

  // Get current active platform
  function getCurrentPlatform() {
    // Find the active platform button (Web, Android, or iOS)
    const platformButtons = document.querySelectorAll('.components__PlatformTabButton-sc-5p96il-7');
    
    log('Checking platform buttons for active state...');
    for (const button of platformButtons) {
      const buttonText = button.textContent.trim();
      const classes = button.className;
      
      // The active platform button has class 'kxoAlJ', inactive has 'diVxVF'
      const isSelected = classes.includes('kxoAlJ');
      
      log(`  Button "${buttonText}": ${isSelected ? 'ACTIVE' : 'inactive'} (${classes})`);
      
      if (isSelected) {
        const buttonTextLower = buttonText.toLowerCase();
        log('✓ Active platform button found:', buttonText);
        
        if (buttonTextLower.includes('android')) return 'Android';
        if (buttonTextLower.includes('ios')) return 'iOS';
        if (buttonTextLower.includes('web')) return 'Web';
      }
    }
    
    log('Could not detect active platform from buttons, defaulting to Web');
    return 'Web'; // Default to Web
  }

  function applyRecommendation(result) {
    log('=== Applying recommendation:', result, 'isManualTabSwitch:', isManualTabSwitch);
    
    // Detect current platform
    const currentPlatform = getCurrentPlatform();
    log('Current platform:', currentPlatform);
    
    // Create a working copy of result to avoid modifying the original
    let workingResult = result;
    
    // Adjust recommendation if Links is recommended on Android/iOS
    if ((currentPlatform === 'Android' || currentPlatform === 'iOS') && result) {
      
      // If Links is the only recommendation, switch to Drop-in (not Components, since they said "no dev capacity")
      if (result.recommend === 'Links' && !result.secondary) {
        log('Links not available on', currentPlatform, '- switching to Drop-in');
        workingResult = {
          recommend: 'Drop-in',
          secondary: null,
          copy: 'Links (our no-code hosted payment page solution) is only available for Web. For ' + currentPlatform + ', we recommend Drop-in instead — a low-code embedded checkout that gets you live in days with minimal development effort.',
          showNext: false
        };
      } 
      // If Links is secondary, remove it and update copy
      else if (result.secondary === 'Links') {
        log('Removing Links as secondary on', currentPlatform);
        workingResult = {
          recommend: result.recommend,
          secondary: null,
          copy: result.recommend + ' is recommended for ' + currentPlatform + '. (Note: Links is only available for Web.)',
          showNext: false
        };
      }
    }
    
    // Always remove all existing badges first (both heading badges and tab badges)
    const existingBadges = document.querySelectorAll('.recommended-badge');
    log('Removing', existingBadges.length, 'existing badges');
    existingBadges.forEach(badge => {
      log('  Removing badge from:', badge.parentElement?.textContent?.substring(0, 50));
      const parent = badge.parentElement;
      if (parent) {
        parent.removeAttribute('data-has-badge');
      }
      badge.remove();
    });
    
    // Remove all tab badges
    removeAllTabBadges();
    
    if (!workingResult || !workingResult.recommend) {
      log('No recommendation, exiting');
      return;
    }
    
    const recommended = workingResult.recommend;
    const secondary = workingResult.secondary;
    
    // Store current recommendation (store the ORIGINAL, not the platform-adjusted version)
    currentRecommendation = result;
    log('Stored recommendation:', currentRecommendation);
    
    // Add badge to the recommended tab
    addBadgeToTab(recommended);
    
    // Add badge to secondary recommendation if it exists
    if (secondary) {
      addBadgeToTab(secondary);
    }
    
    // FIRST: Click the correct tab if not manual switch
    if (!isManualTabSwitch) {
      log('Looking for tab button to click first...');
      const allTabsLists = document.querySelectorAll('.components__HorizontalTabsList-sc-5p96il-18');
      log('Found', allTabsLists.length, 'tab lists');
      
      for (const tabsList of allTabsLists) {
        // Check if this tabs list is in the currently active platform
        const platformPanel = tabsList.closest('[role="tabpanel"]');
        if (platformPanel && platformPanel.getAttribute('aria-hidden') === 'true') {
          log('Skipping tabs list (platform panel hidden)');
          continue;
        }
        
        const buttons = tabsList.querySelectorAll('button');
        log('Checking', buttons.length, 'buttons in this list');
        
        for (const btn of buttons) {
          const btnContent = btn.textContent.trim();
          log('  Button:', btnContent.substring(0, 30));
          
          if (btnContent.includes(recommended)) {
            const ariaSelected = btn.getAttribute('aria-selected');
            log('  ✓ Found matching button, aria-selected:', ariaSelected);
            
            if (ariaSelected !== 'true') {
              log('  Clicking button to switch tab');
              btn.click();
              
              // Wait for tab switch to complete, then add badge
              setTimeout(() => addBadgeToVisibleHeading(workingResult), 100);
              return; // Exit early, badge will be added after timeout
            } else {
              log('  Button already selected');
              break;
            }
          }
        }
      }
    }
    
    // If we get here, either manual switch or button already selected
    // Add badge immediately
    addBadgeToVisibleHeading(workingResult);
  }
  
  function removeAllTabBadges() {
    log('=== Removing all tab badges and recommendation copy');
    // Find all tab titles that might have badges
    const allTabTitles = document.querySelectorAll('[class*="HorizontalTabTitle"]');
    allTabTitles.forEach(title => {
      const badge = title.querySelector('.tab-badge-recommended') ||
                   Array.from(title.querySelectorAll('span')).find(span => 
                     span.textContent === 'Recommended' || span.textContent === 'RECOMMENDED'
                   );
      if (badge) {
        log('  Removing tab badge from:', title.textContent.substring(0, 30));
        badge.remove();
      }
    });
    
    // Remove recommendation copy
    const existingCopy = document.querySelectorAll('.recommendation-copy');
    existingCopy.forEach(copy => {
      log('  Removing recommendation copy');
      copy.remove();
    });
  }
  
  function addBadgeToTab(recommended) {
    log('=== Adding badge to tab for:', recommended);
    
    // Find all horizontal tab lists in visible platform panels
    const allTabsLists = document.querySelectorAll('.components__HorizontalTabsList-sc-5p96il-18');
    
    for (const tabsList of allTabsLists) {
      // Check if this tabs list is in the currently active platform
      const platformPanel = tabsList.closest('[role="tabpanel"]');
      if (platformPanel && platformPanel.getAttribute('aria-hidden') === 'true') {
        log('Skipping tabs list (platform panel hidden)');
        continue;
      }
      
      // Find all tab buttons
      const buttons = tabsList.querySelectorAll('button');
      
      for (const btn of buttons) {
        // Look for the tab title within the button
        const tabTitle = btn.querySelector('[class*="HorizontalTabTitle"]');
        if (!tabTitle) continue;
        
        const titleText = tabTitle.textContent.trim();
        
        // Check if this tab matches the recommendation
        if (titleText.includes(recommended)) {
          log('  Found matching tab:', titleText);
          
          // Check if badge already exists (check for both our custom class and any span with "Recommended")
          const existingBadge = tabTitle.querySelector('.tab-badge-recommended') || 
                               Array.from(tabTitle.querySelectorAll('span')).find(span => 
                                 span.textContent === 'Recommended' || span.textContent === 'RECOMMENDED'
                               );
          if (existingBadge) {
            log('  Badge already exists, skipping');
            continue;
          }
          
          // Create and add badge matching the original .recommended-badge styling
          const badge = document.createElement('span');
          badge.className = 'tab-badge-recommended';
          badge.textContent = 'Recommended';
          badge.style.cssText = `
            display: inline-block;
            background: linear-gradient(135deg, var(--green) 0%, var(--bright-blue) 100%);
            color: white;
            padding: 0.15rem 0.5rem;
            border-radius: 3px;
            font-size: 0.625rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            white-space: nowrap;
            line-height: 1.5;
            margin-left: 0.5rem;
          `;
          
          tabTitle.appendChild(badge);
          log('  Badge added to tab:', titleText);
        }
      }
    }
  }
  
  function addRecommendationCopy(result) {
    log('=== Adding recommendation copy for:', result);
    
    // Remove any existing recommendation copy first
    const existingCopy = document.querySelectorAll('.recommendation-copy');
    existingCopy.forEach(copy => copy.remove());
    
    if (!result || !result.recommend || !result.copy) {
      log('No recommendation copy to display');
      return;
    }
    
    const copyText = result.copy;
    
    // Find which question was answered to trigger this recommendation
    const q1 = document.getElementById('developer-availability')?.value;
    const q2 = document.getElementById('website-app')?.value;
    const q3 = document.getElementById('timeline')?.value;
    const q4 = document.getElementById('design-control')?.value;
    
    let targetSelector = null;
    
    // Determine which selector to place the copy after (check from Q4 down to Q1)
    if (q4) {
      targetSelector = document.getElementById('control-selector');
      log('Target: Q4 control-selector');
    } else if (q3) {
      targetSelector = document.getElementById('timeline-selector');
      log('Target: Q3 timeline-selector');
    } else if (q2) {
      targetSelector = document.getElementById('website-selector');
      log('Target: Q2 website-selector');
    } else if (q1) {
      targetSelector = document.getElementById('developer-selector');
      log('Target: Q1 developer-selector');
    }
    
    if (!targetSelector) {
      log('No target selector found for recommendation copy');
      return;
    }
    
    // Create and insert the recommendation copy
    const copyElement = document.createElement('div');
    copyElement.className = 'recommendation-copy';
    copyElement.textContent = copyText;
    copyElement.style.cssText = `
      font-size: 0.95rem;
      color: var(--bright-blue-08);
      margin-top: 1rem;
      margin-bottom: 1.5rem;
      padding: 1rem;
      border-left: 3px solid var(--bright-blue);
      line-height: 1.5;
    `;
    
    // Insert after the selector
    targetSelector.insertAdjacentElement('afterend', copyElement);
    log('Recommendation copy added after selector');
  }
  
  function addBadgeToVisibleHeading(result) {
    log('=== Adding badge to visible heading for:', result);
    
    if (!result || !result.recommend) {
      return;
    }
    
    const recommended = result.recommend;
    
    // Find all h2 headings in the document
    const headings = document.querySelectorAll('h2');
    log('Found', headings.length, 'h2 headings');
    
    let badgeCount = 0;
    
    // Find THE ONE currently visible heading that matches
    for (const heading of headings) {
      const text = heading.textContent.trim();
      
      // Remove any existing "Recommended" text for clean comparison
      const cleanText = text.replace('Recommended', '').trim();
      
      // Match pattern like "Components for Web", "Drop-in for Android", etc.
      // Must be EXACT match: "Drop-in for Web" not "Links for Web"
      const expectedText = recommended + ' for';
      if (cleanText.startsWith(expectedText)) {
        log('Found matching heading:', cleanText);
        
        // Check if this heading already has a badge
        const existingBadge = heading.querySelector('.recommended-badge');
        if (existingBadge) {
          log('  ⚠ Heading already has a badge, skipping');
          continue;
        }
        
        // Find the tab panel container
        const tabPanel = heading.closest('[role="tabpanel"]');
        log('  Tab panel:', tabPanel);
        
        if (tabPanel) {
          const ariaHidden = tabPanel.getAttribute('aria-hidden');
          const isHidden = ariaHidden === 'true';
          log('  aria-hidden:', ariaHidden, 'isHidden:', isHidden);
          
          if (isHidden) {
            log('✗ Tab panel is hidden (aria-hidden=true), skipping');
            continue;
          }
        }
        
        // Additional visibility checks
        const offsetParent = heading.offsetParent;
        const computedStyle = window.getComputedStyle(heading);
        const rect = heading.getBoundingClientRect();
        const isVisible = offsetParent !== null && 
                         computedStyle.display !== 'none' &&
                         computedStyle.visibility !== 'hidden' &&
                         rect.width > 0 && rect.height > 0;
        
        log('  offsetParent:', offsetParent);
        log('  display:', computedStyle.display);
        log('  visibility:', computedStyle.visibility);
        log('  rect:', rect.width, 'x', rect.height);
        log('  isVisible:', isVisible);
        
        if (isVisible && badgeCount === 0) {
          log('✓ Heading is visible, adding badge (count:', badgeCount, ')');
          
          // Add badge with unique identifier
          const badge = document.createElement('span');
          badge.className = 'recommended-badge';
          badge.textContent = 'Recommended';
          badge.setAttribute('data-heading', cleanText);
          badge.setAttribute('data-recommendation', recommended);
          heading.appendChild(badge);
          heading.setAttribute('data-has-badge', 'true');
          badgeCount++;
          log('Badge added to:', cleanText, '(total badges now:', badgeCount, ')');
          
          // Only badge ONE visible heading, then stop
          log('Stopping search (found visible match, badgeCount:', badgeCount, ')');
          break;
        } else {
          log('✗ Heading is NOT visible or already badged, skipping');
        }
      }
    }
    
    // Add recommendation copy under the dropdown
    addRecommendationCopy(result);
    
    log('=== Done adding badge (total badges added:', badgeCount, ')');
  }

  // Handle dropdown changes
  function handleDropdownChange() {
    log('>>> Dropdown changed');
    const result = getRecommendation();
    log('Current result:', result);
    
    // Handle visibility of next questions
    const q1 = document.getElementById('developer-availability')?.value;
    const q2 = document.getElementById('website-app')?.value;
    const q3 = document.getElementById('timeline')?.value;
    
    const websiteSelector = document.getElementById('website-selector');
    const timelineSelector = document.getElementById('timeline-selector');
    const controlSelector = document.getElementById('control-selector');
    
    // Q1 logic
    if (q1 === 'yes') {
      // Show Q2
      if (websiteSelector) websiteSelector.style.display = 'flex';
    } else if (q1 === 'no') {
      // Hide all subsequent questions
      if (websiteSelector) websiteSelector.style.display = 'none';
      if (timelineSelector) timelineSelector.style.display = 'none';
      if (controlSelector) controlSelector.style.display = 'none';
      // Clear subsequent dropdowns
      if (document.getElementById('website-app')) document.getElementById('website-app').value = '';
      if (document.getElementById('timeline')) document.getElementById('timeline').value = '';
      if (document.getElementById('design-control')) document.getElementById('design-control').value = '';
    } else {
      // No selection - hide all
      if (websiteSelector) websiteSelector.style.display = 'none';
      if (timelineSelector) timelineSelector.style.display = 'none';
      if (controlSelector) controlSelector.style.display = 'none';
    }
    
    // Q2 logic
    if (q2 === 'embedded' || q2 === 'both') {
      // Show Q3
      if (timelineSelector) timelineSelector.style.display = 'flex';
    } else if (q2 === 'no-website') {
      // Hide Q3 and Q4
      if (timelineSelector) timelineSelector.style.display = 'none';
      if (controlSelector) controlSelector.style.display = 'none';
      if (document.getElementById('timeline')) document.getElementById('timeline').value = '';
      if (document.getElementById('design-control')) document.getElementById('design-control').value = '';
    } else if (q2 === '') {
      // Q2 cleared - hide Q3 and Q4
      if (timelineSelector) timelineSelector.style.display = 'none';
      if (controlSelector) controlSelector.style.display = 'none';
    }
    
    // Q3 logic
    if (q3 === 'invest-time') {
      // Show Q4
      if (controlSelector) controlSelector.style.display = 'flex';
    } else if (q3 === 'fast') {
      // Hide Q4
      if (controlSelector) controlSelector.style.display = 'none';
      if (document.getElementById('design-control')) document.getElementById('design-control').value = '';
    } else if (q3 === '') {
      // Q3 cleared - hide Q4
      if (controlSelector) controlSelector.style.display = 'none';
    }
    
    // Apply recommendation
    applyRecommendation(result);
  }
  
  // Handle developer availability change
  function handleDeveloperAvailabilityChange() {
    log('>>> Developer availability changed');
    handleDropdownChange();
  }

  // Handle platform tab changes
  function handlePlatformTabChange() {
    log('>>> Platform tab clicked');
    // Remove tab badges when switching platforms
    removeAllTabBadges();
    
    // Re-apply the current recommendation to the new active platform
    if (currentRecommendation) {
      log('Re-applying stored recommendation:', currentRecommendation);
      setTimeout(() => applyRecommendation(currentRecommendation), 100);
    } else {
      log('No stored recommendation to re-apply');
    }
  }
  
  // Handle horizontal tab changes
  function handleHorizontalTabChange() {
    log('>>> Horizontal tab clicked');
    isManualTabSwitch = true;
    
    // Remove all badges immediately when switching horizontal tabs
    const existingBadges = document.querySelectorAll('.recommended-badge');
    log('After tab switch, removing', existingBadges.length, 'badges');
    existingBadges.forEach(badge => badge.remove());
    
    // Don't remove tab badges when manually switching - they should stay visible
    
    // Re-apply recommendation after tab content has loaded
    if (currentRecommendation) {
      log('Re-applying recommendation after horizontal tab switch');
      setTimeout(() => {
        applyRecommendation(currentRecommendation);
        // Reset the flag after applying
        setTimeout(() => {
          isManualTabSwitch = false;
          log('Reset isManualTabSwitch to false');
        }, 100);
      }, 50);
    } else {
      isManualTabSwitch = false;
    }
  }

  // Initialize
  function initialize() {
    log('Initialising...');
    
    // Attach listener to all dropdowns
    const dropdowns = [
      'developer-availability',
      'website-app',
      'timeline',
      'design-control'
    ];
    
    dropdowns.forEach(id => {
      const dropdown = document.getElementById(id);
      if (dropdown && !dropdown.__listenerAttached) {
        dropdown.addEventListener('change', handleDropdownChange);
        dropdown.__listenerAttached = true;
        log(`Dropdown ${id} listener attached`);
      }
    });
    
    // Listen for platform tab button clicks
    const platformButtons = document.querySelectorAll('.components__PlatformTabButton-sc-5p96il-7');
    log('Found', platformButtons.length, 'platform buttons');
    
    platformButtons.forEach((btn, index) => {
      if (!btn.__listenerAttached) {
        btn.addEventListener('click', handlePlatformTabChange);
        btn.__listenerAttached = true;
        log('  Attached listener to platform button', index, ':', btn.textContent.trim());
      }
    });
    
    // Listen for horizontal tab button clicks (the Components/Drop-in buttons)
    const horizontalButtons = document.querySelectorAll('.components__HorizontalTabsList-sc-5p96il-18 button');
    log('Found', horizontalButtons.length, 'horizontal tab buttons');
    
    horizontalButtons.forEach((btn, index) => {
      if (!btn.__listenerAttached) {
        btn.addEventListener('click', handleHorizontalTabChange);
        btn.__listenerAttached = true;
        log('  Attached listener to horizontal button', index);
      }
    });
    
    log('Initialisation complete');
  }

  // Wait for DOM to be ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initialize);
  } else {
    initialize();
  }
})();

Web
Components
### Components for Web

We recommend PXP Checkout Components if you need complete control over your payment experience — from how individual fields are laid out to how each payment method is presented. Components gives you modular, individually mountable inputs for your payment methods that you can arrange and style with no constraints. It supports MIT-based recurring payments, Kount fraud prevention, 3DS, and a unified SDK across Web, Android and iOS.

#### Key features

- Full UI customisation
- Granular control over payment flow
- Seamless integration with existing design systems
- PCI DSS compliant components


#### Use cases

- Custom checkout experiences
- Multi-step payment flows
- Branded payment pages
- Complex form requirements


#### Supported payment methods

      

[Learn more ](/guides/checkout)
[Try it ](/guides/checkout)

Drop-in
### Drop-in for Web

We recommend PXP Drop-in if you need a complete embedded checkout without the overhead of building it yourself. Drop-in brings all PXP payment methods into a single pre-built UI that can be live in days. You get meaningful branding control via Unity (colours, fonts, button styling, component sizing), dynamic or manual payment method ordering, and full support for MIT-based recurring payments — all with a single SDK integration.

#### Key features

- Ready-made payment UI
- Quick implementation (minutes, not days)
- Automatic updates and maintenance
- Built-in best practices


#### Use cases

- Quick market entry
- Standard checkout flows
- Minimal development resources
- Prototype and MVP development


#### Supported payment methods

      

[Learn more ](/guides/checkout)
[Try it ](/guides/checkout)

Links
### Links for Web

We recommend PXP Links if you don't need a checkout embedded in your site — you need a fast, flexible way to collect payments wherever your customers are. PXP Links generates secure, branded payment pages you can share via email, SMS, WhatsApp or QR code, with no development required. All major payment methods are supported, and you get a full link management dashboard, and enterprise-grade security with 3DS and Kount out of the box.

#### Key features

- Single-use or open-use link types
- Customisable branding and appearance
- Flexible customer data collection
- Built-in fraud protection with AVS


#### Use cases

- Invoice payments
- Subscription sign-ups
- Donation collection
- Order payments


#### Supported payment methods

      

[Learn more ](/guides/checkout/links/)
[Try it ](/guides/checkout)

Android
Components
### Components for Android

We recommend PXP Checkout Components if you need complete control over your payment experience — from how individual fields are laid out to how each payment method is presented. Components gives you modular, individually mountable inputs for your payment methods that you can arrange and style with no constraints. It supports MIT-based recurring payments, Kount fraud prevention, 3DS, and a unified SDK across Web, Android and iOS

#### Key features

- Full UI customisation
- Granular control over payment flow
- Seamless integration with existing design systems
- PCI DSS compliant components


#### Use cases

- Custom checkout experiences
- Multi-step payment flows
- Branded payment pages
- Complex form requirements


#### Supported payment methods

    

[Learn more ](/guides/checkout)
[Try it ](/guides/checkout)

Drop-in
### Drop-in for Android 

We recommend PXP Drop-in if you need a complete embedded checkout without the overhead of building it yourself. Drop-in brings all PXP payment methods into a single pre-built UI that can be live in days. You get meaningful branding control via Unity (colours, fonts, button styling, component sizing), dynamic or manual payment method ordering, and full support for MIT-based recurring payments — all with a single SDK integration.

#### Key features

- Ready-made payment UI
- Quick implementation (minutes, not days)
- Automatic updates and maintenance
- Built-in best practices


#### Use cases

- Quick market entry
- Standard checkout flows
- Minimal development resources
- Prototype and MVP development


#### Supported payment methods

    

[Learn more ](/guides/checkout)
[Try it ](/guides/checkout)

Links
Links is only available for Web. Take a look at Components or Drop-in instead.

iOS
Components
### Components for iOS

We recommend PXP Checkout Components if you need complete control over your payment experience — from how individual fields are laid out to how each payment method is presented. Components gives you modular, individually mountable inputs for your payment methods that you can arrange and style with no constraints. It supports MIT-based recurring payments, Kount fraud prevention, 3DS, and a unified SDK across Web, Android and iOS.

#### Key features

- Full UI customisation
- Granular control over payment flow
- Seamless integration with existing design systems
- PCI DSS compliant components


#### Use cases

- Custom checkout experiences
- Multi-step payment flows
- Branded payment pages
- Complex form requirements


#### Supported payment methods

  

[Learn more ](/guides/checkout)
[Try it ](/guides/checkout)

Drop-in
### Drop-in for iOS 

We recommend PXP Drop-in if you need a complete embedded checkout without the overhead of building it yourself. Drop-in brings all PXP payment methods into a single pre-built UI that can be live in days. You get meaningful branding control via Unity (colours, fonts, button styling, component sizing), dynamic or manual payment method ordering, and full support for MIT-based recurring payments — all with a single SDK integration. Get up and running quickly with our pre-built payment UI. Ideal for merchants who want a fast, turnkey payment solution.

#### Key features

- Ready-made payment UI
- Quick implementation (minutes, not days)
- Automatic updates and maintenance
- Built-in best practices


#### Use cases

- Quick market entry
- Standard checkout flows
- Minimal development resources
- Prototype and MVP development


#### Supported payment methods

    

[Learn more ](/guides/checkout)
[Try it ](/guides/checkout)

Links
Links is only available for Web. Take a look at Components or Drop-in instead.

## Feature comparison

| Feature  | Components  | Drop-in  | Links  |
|  --- | --- | --- | --- |
| Requires development capacity |  |  |  |
| Embedded in your website or app |  |  |  |
| Hosted shareable payment page |  |  |  |
| Fast integration (hours not weeks) |  |  |  |
| Full custom design control |  |  |  |
| Standard branding (colours, fonts, buttons) |  |  |  |
| Control placement of each individual element |  |  |  |
| Per-method custom layout |  |  |  |
| Dynamic payment method ordering |  |  |  |
| Manual payment method ordering |  |  |  |