No backend? No problem.
Everything — the embed and the campaign tracking — runs client-side in JavaScript, since there's no server to process the company key or the tracking parameters.
Sitewide tracking + retrieval function
Add this to the <head> or just before </body> on every page of the site:
<script>
(function(){
var KEYS = ['gclid','gbraid','wbraid','utm_source','utm_medium','utm_campaign','utm_term','utm_content','fbclid'];
// Stores a cookie if this page has any of them in the URL
KEYS.forEach(function(k){
var m = new RegExp('[?&]'+k+'=([^&#]*)').exec(window.location.href);
if(m){
document.cookie = 'fb_' + k + '=' + m[1] + ';max-age=7776000;path=/;SameSite=Lax';
}
});
// Used by the embeds below to retrieve it
window.fbGetTrackingParams = function(){
var qs = '';
KEYS.forEach(function(k){
var m = new RegExp('[?&]'+k+'=([^&#]*)').exec(window.location.href);
var val = m ? m[1] : null;
if(!val){
var match = document.cookie.match(new RegExp('(^| )fb_' + k + '=([^;]+)'));
if(match) val = match[2];
}
if(val) qs += '&' + k + '=' + val;
});
return qs;
};
})();
</script>
Let the iframe resize itself
An iframe doesn't grow when its content grows — without telling it to, the form gets cut off the moment its content expands (opening the Options panel, for example). Both embeds below already include this, but the pattern is always the same three pieces, in this order:
- The resizer script — before the iframe
- The iframe itself, with a fixed
id - A small script that activates the resize — after the iframe, targeting that same
id
Use FareBookings' own copy of the script
app.farebookings.com/iframe-resizer/iframeResizer.min.js — not a third-party CDN. Ad blockers, corporate firewalls, and site-optimisation plugins sometimes block external CDNs but not the domain the widget already lives on.
Compact widget
<div id="fb-widget-container"></div>
<script src="https://app.farebookings.com/iframe-resizer/iframeResizer.min.js"></script>
<script>
(function(){
var container = document.getElementById('fb-widget-container');
var params = 'k=YOUR_COMPANY_KEY&lng=gb';
var tracking = window.fbGetTrackingParams ? window.fbGetTrackingParams() : '';
var iframe = document.createElement('iframe');
iframe.id = 'fb-booking-widget';
iframe.src = 'https://app.farebookings.com/booking-widget.php?' + params + tracking;
iframe.width = '100%';
iframe.height = '640';
iframe.frameBorder = '0';
iframe.scrolling = 'no';
iframe.style.border = 'none';
container.appendChild(iframe);
if (window.iFrameResize) {
iFrameResize({checkOrigin: false, heightCalculationMethod: 'lowestElement'}, '#fb-booking-widget');
}
})();
</script>
Full booking form
The most important fix on this page
If a compact widget elsewhere on the site (the homepage, say) submits and sends the visitor to this page, everything they already typed — origin, destination, date, passengers, plus any gclid/utm_* — arrives in this page's own URL. If this page doesn't read that and forward it into the iframe, all of it is lost and the form loads blank. This only applies when the widget sends visitors to a page of your own with the form embedded — if the widget links straight to app.farebookings.com instead, it builds that URL itself and none of this is needed.
The fix — read this page's own query string with window.location.search and forward it wholesale into the iframe:
<div id="fb-form-container"></div>
<script src="https://app.farebookings.com/iframe-resizer/iframeResizer.min.js"></script>
<script>
(function(){
var container = document.getElementById('fb-form-container');
var baseParams = 'k=YOUR_COMPANY_KEY&d=pp&lng=gb';
// Forward EVERYTHING this page's own URL was given — this is what
// carries the widget's data through when it redirects here.
var ownParams = window.location.search.replace(/^\?/, '');
var finalParams = baseParams + (ownParams ? '&' + ownParams : '');
var iframe = document.createElement('iframe');
iframe.id = 'fb-booking-form';
iframe.src = 'https://app.farebookings.com/step1sslv3.php?' + finalParams;
iframe.width = '100%';
iframe.style.border = 'none';
iframe.style.minHeight = '1400px';
iframe.scrolling = 'no';
container.appendChild(iframe);
if (window.iFrameResize) {
iFrameResize({checkOrigin: false, heightCalculationMethod: 'lowestElement'}, '#fb-booking-form');
}
})();
</script>
Replace YOUR_COMPANY_KEY with the real key from the Frontend tab of your panel, in both snippets above. Forwarding window.location.search wholesale already carries through anything the widget sent — including gclid/utm_* — so fbGetTrackingParams() isn't needed again on this specific page.
&dark=1 to params.&opts_open=1 to params.lng=gb to lng=es, lng=fr, etc.&layout=inline to params for the widget (not the full form). Needs ~1000px of width and stacks on its own under 900px — no separate markup for mobile. Set iframe.height to '200' instead of '640' when using this layout, or there's a visible gap under the bar for the first moment before iframeResizer measures it.Verifying tracking works
- Visit any page with
?gclid=test123on the end of the URL. - Open the browser console (F12) → type
document.cookie. fb_gclid=test123should be there.- Navigate to another page (without the parameter) and confirm the cookie is still there before reaching the widget/form.
Building on a different platform?
There are dedicated guides for WordPress and plain PHP sites.