Fetch the Embeddable data from our Renderer API endpoint
Within your backend code that serves your site, start by fetching the Embeddable data from our Renderer API endpoint.
You must pass all query parameters from the request to the Renderer API endpoint for all Embeddables features to work correctly.
Copy
Ask AI
// ... Your existing code ...// @TODO: Replace with your Embeddable IDconst EMBEDDABLE_ID = 'flow_aaaaaaaaaaaaa';// @TODO: Update to create an object with all query parameters appended to the URL requested by the end-userconst queryParams = request.query// Construct the URL to the Renderer API endpointconst embeddablesEndpointUrl = new URL(`https://renderer.trysavvy.com/${EMBEDDABLE_ID}`);// Copy query parameters from request to destination URLObject.entries(queryParams).forEach(([key, value]) => { embeddablesEndpointUrl.searchParams.append(key, value);});// Fetch the Embeddable HTML and other data from the Renderer API endpointconst response = await fetch(embeddablesEndpointUrl.toString());const data = await response.json();
2
Construct the HTML
Construct the necessary HTML pieces that will need to be included in the final HTML response.
This includes, in order of appearance:
Boilerplate page styles (optional) - the minimum styles and meta tags to ensure the page is rendered correctly on all devices, if needed.
Embeddables bundle script - this loads asynchronously and is the full JS code that makes the Embeddables interactive.
Embeddable HTML - this is the initial rendering of the Embeddable, which is inserted here so that the end-user immediately sees the content, even before the bundle script has loaded.
Embeddables Onload Script - this is some initial JS that runs immediately on load. It contains code that affects the initial load (e.g. choosing the correct breakpoint for the end-user’s device size), meaning that we can’t wait for the bundle script to load before executing it.
Copy
Ask AI
// Add the minimum styles and meta tags to ensure the page is rendered correctly on all devices.// @TODO: Remove if you've already handled this.const boilerplatePageStyles = ` <style>body { margin: 0; }</style> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="UTF-8">`;// Include the Embeddables bundle script.const embeddablesBundleScript = `<script src="https://bundle.trysavvy.com/bundle.js" defer="defer"></script>`;// Include the HTML of the Embeddable itself.const embeddableElement = ` <savvy id="flow-${EMBEDDABLE_ID}"> ${data.html} </savvy>`;// Include the JavaScript that initializes the Embeddable on the client side.const clientSideOnloadScript = `<script>(${data.client_side_js})()</script>`;
3
Combine into the final HTML response
Combine all the pieces. This is the final HTML response that should be sent to the client (along with any other HTML you want to include, e.g. fonts, scripts, etc.):
Copy
Ask AI
const fullHtml = ` <!-- Boilerplate Page Styles --> ${boilerplatePageStyles} <!-- Embeddables Bundle Script --> ${embeddablesBundleScript} <!-- Embeddable HTML --> ${embeddableElement} <!-- Embeddables Onload Script --> ${clientSideOnloadScript}`;// @TODO: Then send the full HTML response to the client.// ... the rest of your code ...
Here’s the complete code example for a Node.js server using Express:
Copy
Ask AI
const express = require('express');const app = express();app.get('/embed/:flowId', async (req, res) => { // @TODO: Replace with your Embeddable ID const EMBEDDABLE_ID = 'flow_aaaaaaaaaaaaa'; // @TODO: Update to create an object with all query parameters appended to the URL requested by the end-user const queryParams = request.query // Construct the URL to the Renderer API endpoint const embeddablesEndpointUrl = new URL(`https://renderer.trysavvy.com/${EMBEDDABLE_ID}`); // Copy query parameters from request to destination URL Object.entries(queryParams).forEach(([key, value]) => { embeddablesEndpointUrl.searchParams.append(key, value); }); // Fetch the Embeddable HTML and other data from the Renderer API endpoint const response = await fetch(embeddablesEndpointUrl.toString()); const data = await response.json(); // Boilerplate Page Styles const boilerplatePageStyles = ` <style>body { margin: 0; }</style> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="UTF-8"> `; // Add the minimum styles and meta tags to ensure the page is rendered correctly on all devices. // @TODO: Remove if you've already handled this. const embeddablesBundleScript = `<script src="https://bundle.trysavvy.com/bundle.js" defer="defer"></script>`; // Include the HTML of the Embeddable itself. const embeddableElement = ` <savvy id="flow-${EMBEDDABLE_ID}"> ${data.html} </savvy> `; // Include the JavaScript that initializes the Embeddable on the client side. const clientSideOnloadScript = `<script>(${data.client_side_js})()</script>`; const fullHtml = ` <!-- Boilerplate Page Styles --> ${boilerplatePageStyles} <!-- Embeddables Bundle Script --> ${embeddablesBundleScript} <!-- Embeddable HTML --> ${embeddableElement} <!-- Embeddables Onload Script --> ${clientSideOnloadScript} `; res.setHeader('Content-Type', 'text/html;charset=UTF-8'); res.send(fullHtml);});app.listen(3000, () => { console.log('Server running on port 3000');});
Here’s the complete code example for a Node.js server using Express:
Copy
Ask AI
const express = require('express');const app = express();app.get('/embed/:flowId', async (req, res) => { // @TODO: Replace with your Embeddable ID const EMBEDDABLE_ID = 'flow_aaaaaaaaaaaaa'; // @TODO: Update to create an object with all query parameters appended to the URL requested by the end-user const queryParams = request.query // Construct the URL to the Renderer API endpoint const embeddablesEndpointUrl = new URL(`https://renderer.trysavvy.com/${EMBEDDABLE_ID}`); // Copy query parameters from request to destination URL Object.entries(queryParams).forEach(([key, value]) => { embeddablesEndpointUrl.searchParams.append(key, value); }); // Fetch the Embeddable HTML and other data from the Renderer API endpoint const response = await fetch(embeddablesEndpointUrl.toString()); const data = await response.json(); // Boilerplate Page Styles const boilerplatePageStyles = ` <style>body { margin: 0; }</style> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="UTF-8"> `; // Add the minimum styles and meta tags to ensure the page is rendered correctly on all devices. // @TODO: Remove if you've already handled this. const embeddablesBundleScript = `<script src="https://bundle.trysavvy.com/bundle.js" defer="defer"></script>`; // Include the HTML of the Embeddable itself. const embeddableElement = ` <savvy id="flow-${EMBEDDABLE_ID}"> ${data.html} </savvy> `; // Include the JavaScript that initializes the Embeddable on the client side. const clientSideOnloadScript = `<script>(${data.client_side_js})()</script>`; const fullHtml = ` <!-- Boilerplate Page Styles --> ${boilerplatePageStyles} <!-- Embeddables Bundle Script --> ${embeddablesBundleScript} <!-- Embeddable HTML --> ${embeddableElement} <!-- Embeddables Onload Script --> ${clientSideOnloadScript} `; res.setHeader('Content-Type', 'text/html;charset=UTF-8'); res.send(fullHtml);});app.listen(3000, () => { console.log('Server running on port 3000');});
Here’s a complete code example for a page served by a Cloudflare Worker:
Copy
Ask AI
export default { async fetch(request, env, ctx) { // @TODO: Replace with your Embeddable ID const EMBEDDABLE_ID = 'flow_aaaaaaaaaaaaa'; // @TODO: Update to create an object with all query parameters appended to the URL requested by the end-user const queryParams = request.query // Construct the URL to the Renderer API endpoint const embeddablesEndpointUrl = new URL(`https://renderer.trysavvy.com/${EMBEDDABLE_ID}`); // Copy query parameters from request to destination URL Object.entries(queryParams).forEach(([key, value]) => { embeddablesEndpointUrl.searchParams.append(key, value); }); // Fetch the Embeddable HTML and other data from the Renderer API endpoint const response = await fetch(embeddablesEndpointUrl.toString()); const data = await response.json(); // Boilerplate Page Styles const boilerplatePageStyles = ` <style>body { margin: 0; }</style> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="UTF-8"> `; // Add the minimum styles and meta tags to ensure the page is rendered correctly on all devices. // @TODO: Remove if you've already handled this. const embeddablesBundleScript = `<script src="https://bundle.trysavvy.com/bundle.js" defer="defer"></script>`; // Include the HTML of the Embeddable itself. const embeddableElement = ` <savvy id="flow-${EMBEDDABLE_ID}"> ${data.html} </savvy> `; // Include the JavaScript that initializes the Embeddable on the client side. const clientSideOnloadScript = `<script>(${data.client_side_js})()</script>`; const fullHtml = ` <!-- Boilerplate Page Styles --> ${boilerplatePageStyles} <!-- Embeddables Bundle Script --> ${embeddablesBundleScript} <!-- Embeddable HTML --> ${embeddableElement} <!-- Embeddables Onload Script --> ${clientSideOnloadScript} `; return new Response(fullHtml, { headers: { "content-type": "text/html;charset=UTF-8", }, }); }}