Live-seatmaps

Custom seatmaps and live seatmaps

If you don't use our seatmaps iFrame and want to create you own seatmaps, follow the guide below.

Getting seatmap configuration and capacity.

You should use the seatmaps availability api to get the sections, rows and seats information that should allow you to draw the seatmap.

White listing domains

You can't connect to the channel from locahost, you will need to deploy into a well know server and provide the domains used to connect to sandbox and to production to the support team so they can enable those domains in the respective environments. The domains have to be under https.

Postman collections and environments

You can download the following Postman collection that contains the two API's you need to use to get the token used by the websocket to authenticate your calls. There is also an environment that you can download and use to setup secrets like x-api-key, username and pwd. The environment works with the collection and it will autofill the variables needed to call the other endpoints.

Postman Collection

Postman Environment

Test tool

You can play around with the websocket using this test-tool (you can also look at the code and base your code on it).

Test tool

Live seatmaps configuration and code sample

Live seatmaps allow you to display in real time when users in other browsers select a seat in the seatmap.

You should use the phoenix.js library to create to the api.

npm i phoenix@1.4.16

You will need to connect to the seatmaps API to get an access token. You should do that in your server side, see below an example using axios.

Replace the x-api-key-value and the jwtToken with proper values for your account. see here

Do this on the server side so not to expose your jwtToken

//client is an axios instance
return client({
      url: "https://api.betterez.com/seatmaps/access-ticket",
      method: "post",
      headers: {
        'x-api-key': "{{x-api-key-value}}",
        'authorization': `Bearer ${jwtToken}`
      }
    });

Client side code to sync data.

The phoenix.js library is client side code.

In the code example below blockSeat and unblockSeat are functions that will change the visual representation of the seat in your seatmap. The functions unSelectSeat and selectSeat are function you should call when that happens in your seatmap to call the websocket and publish the events.

leg_from and leg_to are the leg indexes on the trip. scheduleId is the schdule Id of the selected trip date in the format yyyy-mm-dd (date of travel) seatId example: "section-55fb31b822670b6f1a000461-row-1-seat-0" accessTicket You got this before

  const idForLiveSeatmap = `${scheduleId}_${date}`;
  const socketUrl = "wss://api.betterez.com/seatmaps/socket";

  //the phoenix library comes from the phoenix.js file in phoenix@1.4.16
  const socket = new Phoenix.Socket(socketUrl, { params: { token: accessTicket } });
  socket.connect();
    
  const channel = socket.channel("seatmap:" + idForLiveSeatmap, {leg_from, leg_to});

    channel.join()
      .receive("ok", function () {          
      })
      .receive("error", function (err) { console.log("failed join", err.reason); });

    channel.on("seat:selected", function (msg) {
      var selected_seat = msg.selected_seat;
      // console.log("seat:selected", selected_seat);
      blockSeat(selected_seat.seat_id);
    });

    channel.on("seat:unselected", function (msg) {
      var unselected_seat = msg.unselected_seat;
      // console.log("seat:unselected", unselected_seat);
      unblockSeat(unselected_seat.seat_id);
    });

    channel.on("sync:join", function (msg) {
      // console.log("sync:join", msg.seats);
      msg.seats.forEach(function (seat) {
        blockSeat(seat.seat_id);
      });
    });

    channel.on("sync:seats", function (msg) {
      // console.log("expires!", msg.expired);
      msg.expired.forEach(function (expired) {
        unblockSeat(expired.seat_id);
      });

      var data = {
        eventName: "expiredSeats",
        expired: msg.expired
      };

      window.parent.postMessage(data, "*");
    });
  }

  function unSelectSeat(selector) {
    //your code to handle unselection

    if (liveSeatmapsActivated && channel) {
      var payload = {
        seat: {
          leg_from: window.legFrom, 
          leg_to: window.legTo, 
          seat_id: selector
        },
        ttl_sec: window.ttlSec
      };
      channel.push("seat:unselected", payload);
    }
  }

  function selectSeat(selector) {
    // you code to show the seat selected

    if (liveSeatmapsActivated && channel) {
      var payload = {
        seat: {
          leg_from: window.legFrom, 
          leg_to: window.legTo, 
          seat_id: selector
        },
        ttl_sec: window.ttlSec
      };
      channel.push("seat:selected", payload);
    }
  }

  function blockSeat (selector) {
    var opts = splitSeat(selector);
    // custom code as needed ex: set the seat as blocked
  }

  function unblockSeat(selector) {
    var opts = splitSeat(selector);
    // custom code as needed
  }