Skip to main content
Back to Guides & Use Cases

Redirecting the Enroll Button to an External Cart

Replace the default checkout with your own ecommerce system

This guide documents how to redirect learners from the Thought Industries Enroll button to an external cart (e.g., your own ecommerce/cart system) on course and product detail pages.

Product View Scripts (Global Redirect)

Best for: Redirecting all Enroll buttons across the site to one external cart, with product data (ID, SKU, etc.) passed in the URL.

How It Works

Product View Scripts run when a learner views a product (course, collection, learning path, etc.). You can inject JavaScript that replaces or intercepts the Enroll button and redirects to your cart instead of opening the Thought Industries checkout modal.

DOM Timing

The platform uses Ember (SPA). The enroll section may render asynchronously after the Product View Script runs. Use polling to wait for the button to appear, or event delegation to catch clicks once the DOM is ready.

Configuration

  1. Go to Settings → Connections → Layout Settings (or Tracking Scripts)
  2. Find Product View Scripts
  3. Paste one of the scripts below (customize the redirect URL)

Sample Script A: Polling + Button ReplacementRecommended

More robust for Ember/SPA pages. Polls until the Enroll button exists, then replaces it with a new button that redirects to your cart. Includes empty-SKU handling for debugging.

<script nonce="{{cspNonce}}">
(function() {
  var sku = '{{purchasableSku}}';
  var redirectUrl = 'https://store.abc.com/cart/add?productId=' + encodeURIComponent(sku);

  function poll(delay) {
    delay = delay || 100;
    var btn = document.querySelector('.enroll__buy button.btn--primary')
           || document.querySelector('.enroll__buy button');
    if (!btn) {
      setTimeout(function() { poll(delay); }, delay);
      return;
    }

    var replacement = document.createElement('button');
    replacement.type = btn.type || 'button';
    replacement.className = btn.className;

    if (!sku) {
      replacement.style.backgroundColor = 'red';
      replacement.style.color = 'white';
      replacement.innerHTML = 'NO PRODUCT SKU!';
    } else {
      replacement.innerHTML = btn.innerHTML;
      replacement.addEventListener('click', function() {
        window.location.href = redirectUrl;
      });
    }

    btn.replaceWith(replacement);
  }

  poll();
})();
</script>

Sample Script B: Event Delegation

Alternative approach. Intercepts clicks in the capture phase. Works if the enroll section is already rendered when the script runs.

<script nonce="{{cspNonce}}">
(function() {
  var cartBaseUrl = 'https://store.abc.com/cart/add';
  var params = [
    'sku=' + encodeURIComponent('{{purchasableSku}}'),
    'id=' + encodeURIComponent('{{purchasableId}}'),
    'title=' + encodeURIComponent('{{purchasableTitle}}'),
    'price=' + encodeURIComponent('{{priceInCents}}')
  ].join('&');
  var redirectUrl = cartBaseUrl + (cartBaseUrl.indexOf('?') >= 0 ? '&' : '?') + params;

  function handleEnrollClick(e) {
    var btn = e.target.closest('button.btn--primary');
    if (!btn) return;
    var enrollSection = e.target.closest('.enroll, .enroll__buy, .course__detail__sidebar');
    if (!enrollSection) return;
    if (btn.closest('.enroll')
        && btn.textContent.toLowerCase().indexOf('waitlist') !== -1) return;

    e.preventDefault();
    e.stopPropagation();
    window.location.href = redirectUrl;
    return false;
  }

  document.addEventListener('click', handleEnrollClick, true);
})();
</script>

Available Substitutions

These placeholders are automatically replaced with product data when the script runs.

PlaceholderDescriptionExample
{{purchasableId}}Product/course IDabc123
{{purchasableSku}}Product SKULINUX-101
{{purchasableTitle}}Product titleLinux Fundamentals
{{purchasableSlug}}URL sluglinux-fundamentals
{{purchasableType}}Type (courseGroup, learningPath, etc.)courseGroup
{{priceInCents}}Price in cents9900
{{priceInDollars}}Price in dollars99.00
{{email}}Current user email[email protected]
{{userId}}Current user IDusr_xyz
{{cspNonce}}CSP nonce for inline scripts(required for script tag)

Important Notes

Single product per page

Product View fires once per page load. The substitutions reflect the product being viewed. For course groups with multiple sessions, {{purchasableId}} and {{purchasableSku}} are typically the displayed/default session.

CSP compliance

Always include nonce="{{cspNonce}}" in the <script> tag if your site uses Content Security Policy.

Empty SKU

If {{purchasableSku}} is empty, Script A shows a red "NO PRODUCT SKU!" button for debugging. Ensure courses have SKUs set in Manager → Catalog → Ecommerce.

Waitlist handling

Script B excludes buttons containing "waitlist." Remove that check if you want to redirect waitlist signups as well.

Other product types

This approach works for courses, learning paths, bundles, discount groups, and pickable groups. The Enroll button appears in .enroll or .enroll__buy containers.

Add Cart Item Scripts (Alternative)

Best for: Running logic when an item is actually added to the Thought Industries cart (e.g., syncing to external system). This does not prevent the Thought Industries cart modal from opening — it runs after the user adds to cart. For redirecting instead of using the Thought Industries cart, use Product View Scripts above.

Comparison

ApproachPer-product configDynamic product dataBlocks Thought Industries cart
External Purchase LinkYesNo (static URL)Yes
Product View ScriptsNo (global)Yes (substitutions)Yes
Add Cart Item ScriptsNoYesNo

Recommendation: If you need one global redirect with product data in the URL, use Product View Scripts with Sample Script A (polling + button replacement) for best compatibility with the platform's async rendering.

Troubleshooting

IssuePossible Cause / Fix
Script not firingEnsure Product View Scripts are saved and the page is a product detail page (course, learning path, bundle, etc.).
Button not found / runs too earlyUse Script A (polling + replacement). The platform renders the enroll section asynchronously; polling waits for it.
Redirect not workingFor Script B, ensure e.preventDefault() and e.stopPropagation() run before window.location.href, and use the capture phase (true as third argument).
"NO PRODUCT SKU!" appearsThe product has no SKU. Set a SKU in Manager → Catalog → [Course] → Ecommerce.
Wrong product dataOn multi-session courses, Product View data may reflect the default session. Use External Purchase Link per session or custom DOM logic.

Related