Skip to main content
Learn how to integrate Entri into any web application using plain JavaScript, without frameworks or build tools.

Prerequisites

  • Your applicationId from the Entri dashboard
  • A valid JWT token fetched from your server
  • Basic understanding of JavaScript and DOM events

Installation

Add the Entri SDK to your HTML page:
<script src="https://cdn.goentri.com/entri.js"></script>
The SDK will be available globally as window.entri.

Quick Start

A minimal working example to get started quickly:
<!DOCTYPE html>
<html>
<head>
  <title>Domain Setup</title>
  <script src="https://cdn.goentri.com/entri.js"></script>
</head>
<body>
  <button id="connect-btn">Connect Domain</button>

  <script>
    // Set up event listener before calling showEntri
    window.addEventListener('onEntriClose', (event) => {
      console.log('Entri closed:', event.detail);
    });

    document.getElementById('connect-btn').addEventListener('click', () => {
      window.entri.showEntri({
        applicationId: 'YOUR_APPLICATION_ID',
        token: 'YOUR_JWT_TOKEN',
        dnsRecords: [
          {
            type: 'CNAME',
            host: 'www',
            value: 'your-service.com',
            ttl: 300,
          },
        ],
      });
    });
  </script>
</body>
</html>

Full Implementation

Step 1: Create an Entri Manager

Encapsulate all Entri logic in a reusable module for cleaner code.
// entri-manager.js
const EntriManager = (() => {
  let isOpen = false;
  let onSuccessCallback = null;
  let onCloseCallback = null;
  let onStepChangeCallback = null;

  // Set up event listeners once
  window.addEventListener('onSuccess', (event) => {
    if (onSuccessCallback) {
      onSuccessCallback(event.detail);
    }
  });

  window.addEventListener('onEntriClose', (event) => {
    isOpen = false;
    if (onCloseCallback) {
      onCloseCallback(event.detail);
    }
  });

  window.addEventListener('onEntriStepChange', (event) => {
    if (onStepChangeCallback) {
      onStepChangeCallback(event.detail);
    }
  });

  return {
    open(config) {
      isOpen = true;
      window.entri.showEntri({
        applicationId: config.applicationId,
        token: config.token,
        dnsRecords: config.dnsRecords,
        prefilledDomain: config.prefilledDomain,
        userId: config.userId,
      });
    },

    close() {
      window.entri.close();
    },

    isOpen() {
      return isOpen;
    },

    onSuccess(callback) {
      onSuccessCallback = callback;
    },

    onClose(callback) {
      onCloseCallback = callback;
    },

    onStepChange(callback) {
      onStepChangeCallback = callback;
    },
  };
})();

Step 2: Use in Your Application

<!DOCTYPE html>
<html>
<head>
  <title>Domain Setup</title>
  <script src="https://cdn.goentri.com/entri.js"></script>
  <script src="entri-manager.js"></script>
  <style>
    .success { color: green; }
    .error { color: red; }
    button:disabled { opacity: 0.5; cursor: not-allowed; }
  </style>
</head>
<body>
  <div id="app">
    <button id="connect-btn">Connect Domain</button>
    <div id="status"></div>
  </div>

  <script>
    const connectBtn = document.getElementById('connect-btn');
    const statusDiv = document.getElementById('status');

    // Handle successful domain setup
    EntriManager.onSuccess((result) => {
      statusDiv.innerHTML = `<p class="success">Domain ${result.domain} connected successfully!</p>`;
      connectBtn.disabled = false;
      connectBtn.textContent = 'Connect Another Domain';
    });

    // Handle modal close
    EntriManager.onClose((result) => {
      connectBtn.disabled = false;
      connectBtn.textContent = 'Connect Domain';

      if (result.error) {
        statusDiv.innerHTML = `<p class="error">Error: ${result.error.title || 'An error occurred'}</p>`;
      } else if (!result.success) {
        statusDiv.innerHTML = `<p>Setup cancelled at: ${result.lastStatus}</p>`;
      }
    });

    // Handle button click
    connectBtn.addEventListener('click', () => {
      connectBtn.disabled = true;
      connectBtn.textContent = 'Connecting...';
      statusDiv.innerHTML = '';

      EntriManager.open({
        applicationId: 'YOUR_APPLICATION_ID',
        token: 'YOUR_JWT_TOKEN',
        userId: 'user-123',
        dnsRecords: [
          {
            type: 'CNAME',
            host: 'www',
            value: 'your-service.com',
            ttl: 300,
          },
        ],
      });
    });
  </script>
</body>
</html>

Event Handling

Entri emits several events during the flow. Set up listeners before calling showEntri().

onSuccess

Triggered when the user successfully completes domain setup (reaches the Congratulations screen).
window.addEventListener('onSuccess', (event) => {
  const { domain, setupType, provider, jobId } = event.detail;

  console.log('Domain:', domain);
  console.log('Setup type:', setupType); // 'automatic' or 'manual'
  console.log('Provider:', provider);
  console.log('Job ID:', jobId); // Use for webhook correlation
});

onEntriClose

Triggered when the modal is closed, whether successful or not.
window.addEventListener('onEntriClose', (event) => {
  const { success, domain, error, lastStatus } = event.detail;

  if (success) {
    console.log('Domain configured successfully:', domain);
  } else if (error) {
    console.log('Error:', error.code, '-', error.title);
  } else {
    console.log('User exited at:', lastStatus);
  }
});

onEntriStepChange

Triggered when the user moves between screens in the modal. Useful for analytics.
window.addEventListener('onEntriStepChange', (event) => {
  const { step, domain, provider } = event.detail;

  // Track user progress
  console.log('Step:', step);
  console.log('Domain:', domain);
  console.log('Provider:', provider);
});

onEntriManualSetupDocumentationClick

Triggered when the user clicks the manual setup guide link.
window.addEventListener('onEntriManualSetupDocumentationClick', () => {
  // Open your custom help, e.g., a support chat
  openSupportChat();
});

Common Patterns

Loading State UI

const button = document.getElementById('connect-btn');
const originalText = button.textContent;

const setLoading = (isLoading) => {
  button.disabled = isLoading;
  button.textContent = isLoading ? 'Connecting...' : originalText;
};

// When opening Entri
setLoading(true);
window.entri.showEntri(config);

// When Entri closes
window.addEventListener('onEntriClose', () => {
  setLoading(false);
});

Error Display

const showError = (error) => {
  const errorDiv = document.getElementById('error-message');

  if (!error) {
    errorDiv.style.display = 'none';
    return;
  }

  errorDiv.innerHTML = `<strong>${error.title}</strong><p>${error.details}</p>`;
  errorDiv.style.display = 'block';
};

window.addEventListener('onEntriClose', (event) => {
  if (event.detail.error) {
    showError(event.detail.error);
  }
});

Check Domain Before Opening

Use checkDomain to verify provider support before showing the modal:
const connectDomain = async (domain) => {
  const config = {
    applicationId: 'YOUR_APPLICATION_ID',
    token: 'YOUR_JWT_TOKEN',
    dnsRecords: [
      { type: 'CNAME', host: 'www', value: 'your-service.com', ttl: 300 }
    ],
  };

  // Check if automatic setup is supported
  const check = await window.entri.checkDomain(domain, config);

  if (check.setupType === 'Automatic') {
    console.log('Automatic setup available with', check.provider);
  } else {
    console.log('Manual setup required');
  }

  // Open Entri with prefilled domain
  config.prefilledDomain = domain;
  window.entri.showEntri(config);
};

Multiple DNS Records

Configure multiple records for complex setups:
window.entri.showEntri({
  applicationId: 'YOUR_APPLICATION_ID',
  token: 'YOUR_JWT_TOKEN',
  dnsRecords: [
    {
      type: 'CNAME',
      host: 'www',
      value: 'your-service.com',
      ttl: 300,
    },
    {
      type: 'TXT',
      host: '@',
      value: 'v=spf1 include:your-service.com ~all',
      ttl: 300,
    },
    {
      type: 'MX',
      host: '@',
      value: 'mail.your-service.com',
      ttl: 300,
      priority: 10,
    },
  ],
});

Troubleshooting

Event listeners not firing

Make sure you’re adding listeners before calling showEntri():
// Wrong - listener added after showEntri
window.entri.showEntri(config);
window.addEventListener('onEntriClose', handler); // Too late!

// Correct - listener added before showEntri
window.addEventListener('onEntriClose', handler);
window.entri.showEntri(config);

SDK not loaded

Check that the script has loaded before using it:
if (typeof window.entri === 'undefined') {
  console.error('Entri SDK not loaded');
  return;
}

window.entri.showEntri(config);
Or wait for the script to load:
window.addEventListener('load', () => {
  // Safe to use window.entri here
  document.getElementById('connect-btn').addEventListener('click', () => {
    window.entri.showEntri(config);
  });
});

Multiple event handlers firing

If you’re dynamically adding/removing elements, make sure to clean up event listeners:
const handler = (event) => {
  console.log('Entri closed:', event.detail);
};

// Add listener
window.addEventListener('onEntriClose', handler);

// Remove listener when no longer needed
window.removeEventListener('onEntriClose', handler);

Next Steps