Case
Objective: Capture the email entered by the user on a custom screen and pass it into the Paddle or Stripe checkout flow.
Flow:
User sees a custom screen before the paywall.
User enters their email and submits the form.
The screen validates the email.
If valid, the app triggers the event
LeaveCustomScreenWithEmail
with the provided email.Paddle or Stripe receives this email and pre-fills it into the payment form.
Solution
To implement this, you can use the special event:
LeaveCustomScreenWithEmail
When called, it passes the user’s email to the payment provider.
Event structure:
{ "email": "[email protected]" }
Example of a Custom Screen
Here’s a working example of a custom HTML screen that collects and validates email before proceeding:
<html>
<head>
<meta charset='UTF-8'>
<title>Some custom screen</title>
<!-- OO-PORT-MESSAGE-HANDLER-START -->
<!-- DO NOT REMOVE THIS CODE -->
<script>
window.onboardingOnlineCustomScreenData = {
inputs: {},
labels: {},
userData: {},
customData: {}
};
window.leaveCustomScreenWithEmail = () => {};
window.backScreen = () => {};
window.acceptCookie = () => {};
window.declineCookie = () => {};
window.onmessage = (event) => {
if (typeof (event.data) === 'object' && event.data.eventName === 'InitCustomScreen') {
window.onboardingOnlineCustomScreenData.inputs = event.data.args.inputs;
window.onboardingOnlineCustomScreenData.labels = event.data.args.labels;
window.onboardingOnlineCustomScreenData.userData = event.data.args.userData;
window.onboardingOnlineCustomScreenData.customData = event.data.args.customData;
const port = event.ports[0];
if (port) {
window.leaveCustomScreenWithEmail = (email) => {
port.postMessage({
eventName: 'LeaveCustomScreenWithEmail',
args: { email },
}, []);
};
window.backScreen = () => {
port.postMessage({
eventName: 'BackScreen',
args: null,
}, []);
};
window.acceptCookie = () => {
port.postMessage({
eventName: 'AcceptCookie',
args: null,
}, []);
};
window.declineCookie = () => {
port.postMessage({
eventName: 'DeclineCookie',
args: null,
}, []);
};
}
}
};
</script>
<!-- OO-PORT-MESSAGE-HANDLER-END -->
<style>
body {
background-color: #ffffff;
font-family: Arial, sans-serif;
}
#custom-form {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
gap: 16px;
}
input {
width: 300px;
padding: 12px 14px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 8px;
outline: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
transition: border-color 0.2s, box-shadow 0.2s;
}
input:focus {
border-color: #4a90e2;
box-shadow: 0 0 6px rgba(74,144,226,0.4);
}
button {
width: 300px;
padding: 12px 14px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 8px;
background-color: #4a90e2;
color: white;
font-weight: bold;
transition: background-color 0.2s;
}
button:hover {
background-color: #357abd;
}
.error {
color: red;
font-size: 14px;
}
</style>
</head>
<body>
<form id='custom-form'>
<input type='email' id='email' name='email' placeholder='Enter your email' required autofocus />
<span id='error-message' class='error'></span>
<button id='submit-button'>Next screen</button>
</form>
<script>
const form = document.getElementById('custom-form');
const emailInput = document.getElementById('email');
const errorMessage = document.getElementById('error-message');
form.addEventListener('submit', function(event) {
event.preventDefault();
const email = emailInput.value.trim();
if (!validateEmail(email)) {
errorMessage.textContent = 'Please enter a valid email address';
emailInput.style.borderColor = 'red';
return;
}
errorMessage.textContent = '';
emailInput.style.borderColor = '#ccc';
window.leaveCustomScreenWithEmail(email);
});
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email.toLowerCase());
}
</script>
</body>
</html>
How It Works
The custom form captures the user’s email.
Basic validation ensures only valid addresses proceed.
On success, it triggers:
window.leaveCustomScreenWithEmail(email);
The event passes
{ "email": "[email protected]" }
back to the app.Paddle or Stripe automatically uses this email in their checkout flow.