Search then book on another page

Pick dates on one page, land on the right rental's page with those dates already filled in.

Available onPro

One page asks your guest for dates. They see which of your rentals are free and what each one costs, pick one, and land on that rental's own page with the dates and the guest count already in the booking form. It is the shape most hosts with several rentals want, and it takes a few lines of code on two of your pages.

This one is for whoever edits your website. If that is not you, you may not need it at all: the collection booking widget already asks for dates, shows which rentals are free and takes the booking, all on one page, from a snippet you paste and nothing else. Use the recipe here when you want the guest to finish on your own rental page instead.

What the guest does

  1. 1On the page that shows all of your rentals, the guest picks a check-in and a check-out.
  2. 2The rentals free for those dates appear, each with its own price for that stay.
  3. 3The guest picks one and lands on the page for that rental, with the dates and the guest count already in the booking form.
  4. 4They fill in their details and send the request. Nothing was typed twice.

What you need

  • The Pro plan, because the booking widget is a Pro feature.
  • A collection, which is your rentals gathered into one named list on the dashboard Home tab.
  • A page on your own website for each rental. On Wix, one dynamic page serving every rental counts as that.
  • The script embed on both pages, not the iframe one.
  • Someone who can paste code into those pages. On Wix that means the page code panel, which Wix calls Velo.
The script embed is the snippet with a <script> tag in it, and it is the one that does both halves of this for you: it carries the guest's pick out to your page, and on the rental page it reads the dates back off the address. Inside a builder like Wix it is the only option that works at all, because an iframe there is talking to the builder's own frame, which your page code never sees, and nothing can send a message back into it.

How it works

  1. 1Your overview page carries the collection booking widget. It asks for dates and lists the rentals free for them.
  2. 2When the guest picks one, your page sends them to the page for that rental and carries the dates in the address.
  3. 3That rental page carries its own booking form, which opens on the dates it was handed.

The widgets do the first and the last step by themselves. The code below is the middle one: it listens for the rental the guest picked and sends the browser to your page for it. The widget hands over the dates and the guest count in a message called booking.unit_selected, one of the postMessage events your widgets send out.

Wix needs its own version, because it runs every embed inside a frame of its own. Jump to the Wix version if that is your site. Any other builder that lets you paste HTML uses the first version.

Any site you can paste HTML into

The overview page

Drop in the collection booking widget with no data-picker attribute, which is the dates-first flow, then listen for the rental the guest picks.

HTML
<!-- Overview page: the collection booking widget, dates first -->
<div class="rentalbeam-booking-form" data-collection-id="YOUR-COLLECTION-ID"></div>
<script src="https://cdn.rentalbeam.com/v1/embed.js" async></script>

<script>
  // One path per rental in the collection.
  var PATHS = {
    'a1b2c3d4-...': '/rentals/seaside-cottage',
    'e5f6a7b8-...': '/rentals/cabin-a'
  };

  window.addEventListener('message', function (event) {
    if (!event.data || event.data.source !== 'rentalbeam') return;
    if (event.data.event !== 'booking.unit_selected') return;

    var d = event.data.data;
    var path = PATHS[d.unitId];
    // No dates means a rental-first picker, so there is nothing to carry over.
    if (!path || !d.checkIn) return;

    var query = '?checkin=' + d.checkIn + '&checkout=' + d.checkOut;
    if (d.guests) query += '&guests=' + d.guests;
    if (d.adults) query += '&adults=' + d.adults;
    if (d.children != null) query += '&children=' + d.children;
    window.location.href = path + query;
  });
</script>

Each rental page

That rental's own booking form, and nothing else. The loader reads checkin, checkout, guests, adults and children off the page address and opens the calendar on those dates for the guest to confirm against live availability.

HTML
<!-- /rentals/seaside-cottage - that rental's own booking form.
     The loader reads checkin, checkout, guests, adults and children off the page address,
     so nothing else is needed here. -->
<div class="rentalbeam-booking-form" data-rental-id="a1b2c3d4-..."></div>
<script src="https://cdn.rentalbeam.com/v1/embed.js" async></script>

Wix

Wix puts your embed in a frame of its own, so the two pages talk to it rather than to the window. Everything else is the same recipe. Any builder that frames the embed and gives you page code works this way too. Wix is the worked example.

Coming out, the script embed passes every booking.* event up to the Wix page, so page code listens with $w('#html1').onMessage(...) on the Embed Code element. Going in, page code sends a booking.open message into that element, because it cannot reach the loader directly. It waits for the embed's widget.ready event first, since the element may not be loaded when page code runs.

The overview page

HTML (Wix Embed Code)
<!-- Wix Embed Code element on the overview page -->
<div class="rentalbeam-booking-form" data-collection-id="YOUR-COLLECTION-ID"></div>
<script src="https://cdn.rentalbeam.com/v1/embed.js" async></script>
JavaScript (Wix Velo)
// Wix Velo - the overview page's JavaScript panel.
// #html1 is the Embed Code element above.
import wixLocation from 'wix-location-frontend';

// One path per rental in the collection.
const PATHS = {
  'a1b2c3d4-...': '/rentals/seaside-cottage',
  'e5f6a7b8-...': '/rentals/cabin-a'
};

$w.onReady(function () {
  // Page code listens to the element, not to the window.
  $w('#html1').onMessage(function (event) {
    var message = event.data;
    if (!message || message.source !== 'rentalbeam') return;
    if (message.event !== 'booking.unit_selected') return;

    var d = message.data;
    var path = PATHS[d.unitId];
    if (!path || !d.checkIn) return;

    wixLocation.to(path
      + '?checkin=' + d.checkIn
      + '&checkout=' + d.checkOut
      + (d.guests ? '&guests=' + d.guests : '')
      + (d.adults ? '&adults=' + d.adults : '')
      + (d.children != null ? '&children=' + d.children : ''));
  });
});

Instead of the path map, the rental id can live as a field on the CMS item, next to the rest of the rental's content. Then the overview page reads the id from the collection item it is already rendering, and there is no second list to keep in step.

The rental template page

One Wix dynamic page serves every rental, so the container carries no id at all. When the embed reports widget.ready, page code reads the address and the CMS item's rental id, then sends one message. The loader mounts the empty container as that rental with the dates already applied.

HTML (Wix Embed Code)
<!-- Wix Embed Code element on the rental template page.
     No id on the container: page code names the rental. -->
<div class="rentalbeam-booking-form"></div>
<script src="https://cdn.rentalbeam.com/v1/embed.js" async></script>
JavaScript (Wix Velo)
// Wix Velo - the rental template page's JavaScript panel.
// #html1 is the Embed Code element above.
import wixLocation from 'wix-location-frontend';

$w.onReady(function () {
  // The element may not be loaded when page code runs, so post into it only
  // after the embed says widget.ready.
  $w('#html1').onMessage(function (event) {
    var message = event.data;
    if (!message || message.source !== 'rentalbeam') return;
    if (message.event !== 'widget.ready') return;

    // Read the CMS item inside the dataset's own ready handler. Calling
    // onReady after the dataset is ready runs straight away.
    $w('#dynamicDataset').onReady(function () {
      // The rental id is a field on the CMS item this page is showing.
      var item = $w('#dynamicDataset').getCurrentItem();
      var query = wixLocation.query;

      $w('#html1').postMessage({
        source: 'rentalbeam-host',
        event: 'booking.open',
        data: {
          rentalId: item.rentalId,
          checkIn: query.checkin,
          checkOut: query.checkout,
          guests: query.guests ? Number(query.guests) : undefined,
          adults: query.adults ? Number(query.adults) : undefined,
          children: query.children != null ? Number(query.children) : undefined
        }
      });
    });
  });
});
Inside a builder's frame the loader cannot see the page address. Wix and Google Sites both work this way. That is why the dates are read in page code here and passed in, rather than left for the widget to find.

If something does not line up

  • The overview page lists rentals but a pick goes nowhere: the ids in your path map are rental ids, the same one that appears as data-rental-id in that rental's own embed snippet, and the picker has to be the dates-first one, which is the snippet with no data-picker attribute.
  • The rental page opens empty of dates: check that the address really carries checkin and checkout, and on Wix that the message is sent after widget.ready.
  • Nothing at all reacts: check that both pages carry the snippet with the script tag. On a builder like Wix an iframe embed cannot reach your page code at all.