Embedding user flows
You can embed some of our flows inside your own website or mobile app so the user experience feels like part of your own product.
Detecting the completion of the flow
Registration Flow

You can embed the registration with the following html:
<iframe src="https://app.hurdle.bio/register?publicToken=XYZ&..."/>
Parameter name | Information | Value | Required |
---|---|---|---|
partnerCode | Applies white-label customisation | This is provided to you by your account manager. | No |
publicToken | Auto logs in the user | Generate a public token on your backend. | No |
kitId | Pre-fills the kitId during registration | You can obtain this from the QR code on the box when the user scans it. | No |
hideHeader | Hides the entire header when logged in | true or false | No |
hideFooter | Hides the entire footer | true or false | No |
Results Flow
You can embed the results page with the following html:
<iframe src="https://app.hurdle.bio/?publicToken=XYZ&..."/>
Logging in
Unless you provide the
publicToken
parameter as outlined bellow, the user will be asked to login.
Parameter name | Information | Value | Required |
---|---|---|---|
partnerCode | Applies white-label customisation | This is provided to you by your account manager. | No |
publicToken | Auto logs in the user | Generate a public token on your backend. | No |
hideHeader | Hides the entire header when logged in | true or false | No |
hideFooter | Hides the entire footer | true or false | No |
Phlebotomy Booking Flow
You can embed phlebotomy booking with the following html:
<iframe src="https://app.hurdle.bio/phlebotomy?productCode=XXX"/>
Parameter name | Information | Value | Required |
---|---|---|---|
partnerCode | Applies white-label customisation | This is provided to you by your account manager. | No |
productCode | Limits the bookings to clinics that support this product. | Supports multiple productCodes | Yes |
hideHeader | Hides the entire header when logged in | true or false | No |
hideFooter | Hides the entire footer | true or false |
Complete HTML example
Here is a complete example (for illustration purposes only) of loading the registration flow.
<html>
<head>
</head>
<body>
<iframe id="iframe" style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;">
</iframe>
</body>
<script>
var urlParams = new URLSearchParams(window.location.search);
var kitId = urlParams.get("kitId");
var iframeSrc = "https://app.hurdle.bio/register?partnerCode=ABCD";
if (kitId) {
iframeSrc += "&kitId=" + kitId;
}
document.getElementById("iframe").src = iframeSrc;
</script>
</html>
<html>
<head>
</head>
<body>
<iframe id="iframe" style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;">
</iframe>
</body>
<script>
window.addEventListener("message", (event) => {
// Check the origin (for security)
console.log("Message received from:", event.origin);
const appointmentDetails = event.data;
console.log("Received appointment details:", appointmentDetails);
}, false);
var urlParams = new URLSearchParams(window.location.search);
var iframeSrc = "https://app.stage.chronomics.com/phlebotomy?publicToken=XXX&product=XYZ";
document.getElementById("iframe").src = iframeSrc;
</script>
</html>
The partnerCode is passed silently while the kitId it taken from the parent URL and passed down if its present.
Linking user accounts
By default, users going through a registration flow or results page will be asked to login. See linking user accounts for how to log the users in automatically, removing any need for a Hurdle registration/login.
Detecting the completion of the flow
Once the user completes the registration flow or phlebotomy booking flow, a message will be published using window.postMessage().
In order to receive the published message, you need to add an event listener to the iframe's parent window.
Upon receipt of the message, the iframe can be closed, and any appropriate further action can be taken (i.e. redirect the user to your desired location).
You can check an example on how listening to the event below, as well as the schema of the event emitted.
window.addEventListener("message", (event) => {
if (event.origin === "https://app.hurdle.bio"){ // use https://app.sandbox.hurdle.bio when testing
console.log("Message received from:", event.origin);
const appointmentDetails = event.data;
console.log("Received appointment details:", appointmentDetails);
// Close the iframe
}
}, false);
{
"location": {
"name": "Clinic's Name",
"address": "Clinic's address",
"postcode": "Clinic's postcode",
"latitude": 00.00000,
"longitude": -0.000000,
"distance": 000.000000,
"phoneNumber": "+4411111111",
"distanceUnit": "MILES",
"externalClinicId": "someId"
},
"appointmentSlot": {
"id": "ABCD-0020-20250304-09501000",
"phlebotomyType": "IN-CLINIC",
"startTime": "2025-03-04T09:50:00.000Z",
"endTime": "2025-03-04T10:00:00.000Z"
},
"productInformation": {
"title": "In Clinic Complete XXX Blood Test",
"medicalGuidance": null,
"phlebotomyType": "IN-CLINIC",
"specimenType": "VENOUS_BLOOD"
}
}
Updated 2 days ago