Home Features How It Works Pricing Integrations FAQ Contact
← Back to Integrations Integrations · PHP

A copy-paste iframe, with real tracking.

No plugin needed — just an iframe embed and one small helper function, so Google Ads and Meta can still attribute bookings correctly.

// 01

Helper function

Add this once, in a shared include:

includes/fb-tracking.php
<?php
function fb_tracking_query() {
    $keys = ['gclid','gbraid','wbraid','utm_source','utm_medium','utm_campaign','utm_term','utm_content','fbclid'];
    $qs = '';
    foreach ($keys as $k) {
        $val = '';
        if (!empty($_GET[$k])) {
            $val = $_GET[$k];                       // 1st: this page's own URL
        } elseif (!empty($_COOKIE['fb_' . $k])) {
            $val = $_COOKIE['fb_' . $k];             // 2nd: sitewide cookie (see below)
        }
        if ($val !== '') {
            $qs .= '&' . $k . '=' . rawurlencode($val);
        }
    }
    return $qs;
}
?>
// 02

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:

  1. The resizer script — before the iframe
  2. The iframe itself, with a fixed id
  3. 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.

// 03

Compact widget

<script src="https://app.farebookings.com/iframe-resizer/iframeResizer.min.js"></script>

<iframe
  id="fb-booking-widget"
  src="https://app.farebookings.com/booking-widget.php?k=YOUR_COMPANY_KEY&lng=gb<?php echo fb_tracking_query(); ?>"
  width="100%" height="640" frameborder="0" scrolling="no" style="border:none">
</iframe>

<script>
  if (window.iFrameResize) {
    iFrameResize({checkOrigin: false, heightCalculationMethod: 'lowestElement'}, '#fb-booking-widget');
  }
</script>
// 04

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 — forward this page's entire query string into the iframe, without listing each parameter by hand:

<script src="https://app.farebookings.com/iframe-resizer/iframeResizer.min.js"></script>

<?php
// Forward everything this page's own URL was given — this is what
// carries the widget's data through when it redirects here.
$ownParams = $_SERVER['QUERY_STRING'] ?? '';
?>

<iframe
  id="fb-booking-form"
  src="https://app.farebookings.com/step1sslv3.php?k=YOUR_COMPANY_KEY&d=pp&lng=gb<?php echo $ownParams ? '&' . $ownParams : ''; ?>"
  width="100%" scrolling="no" style="border:none;min-height:1400px">
</iframe>

<script>
  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. Forwarding $_SERVER['QUERY_STRING'] wholesale already carries through anything the widget sent — including gclid/utm_* — so fb_tracking_query() isn't needed again on this specific page.

// 05 · Recommended if running paid campaigns

Sitewide tracking

Add this to the shared footer/template of every page:

<script>
(function(){
  var keys = ['gclid','gbraid','wbraid','utm_source','utm_medium','utm_campaign','utm_term','utm_content','fbclid'];
  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';
    }
  });
})();
</script>

This stores the campaign data as soon as it's seen on any page, so fb_tracking_query() can still pick it up even if the visitor browsed a few pages before reaching the widget.

// Common options
Dark modeAdd &dark=1 to the iframe URL.
Options panel openAdd &opts_open=1.
LanguageChange lng=gb to lng=es, lng=fr, etc.
Horizontal barAdd &layout=inline to the widget iframe URL (widget only, not the full form). Needs ~1000px of width and stacks on its own under 900px — no separate markup for mobile. Set the iframe's starting 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.
// Checking it worked

Verifying tracking works

  1. Visit any page with ?gclid=test123 on the end of the URL.
  2. Open the browser console (F12) → type document.cookie.
  3. fb_gclid=test123 should be there.
  4. 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 sites with no backend at all.