Skip to main content

Introduction

The Vaylo Widget is a powerful, embeddable booking solution that allows you to integrate tour booking functionality directly into your website. Built with React and TypeScript, it provides a seamless user experience with support for multiple languages, customizable themes, and comprehensive payment integration.

Note: This widget is designed to be framework-agnostic and can be embedded in any web application regardless of the underlying technology stack.

Key Features

  • 🌍 Multi-language support (English, Norwegian, Swedish)
  • 🎨 Fully customizable themes and styling
  • 💳 Integrated payment processing
  • 📱 Responsive design for all devices
  • 🔒 Secure booking flow
  • ♿ Accessibility-focused UI components

Installation

Follow these three simple steps to integrate the Vaylo booking widget into your website:

Step 1: Embed the Widget Script

Add the widget script inside your <head> tag. Select the appropriate environment URL:

Production
<script src="https://widget.bookingsystem.se/res_widget_script.iife.js"></script>
Staging
<script src="https://stage.widget.bookingsystem.se/res_widget_script.iife.js"></script>
Development
<script src="https://dev.widget.bookingsystem.se/res_widget_script.iife.js"></script>

Step 2: Create a Container Element

Add a <div> element in your page where you want the widget to appear. You can use any ID you prefer:

<div id="vaylo-widget"></div>

Step 3: Initialize the Widget

Add the initialization script, typically at the bottom of your <body> tag or in your JavaScript file:

window.addEventListener("load", function () {
  Widget.mount({
    containerID: "vaylo-widget",
  });
});
Note: The type parameter will default to "default" if not provided.

Requirements

For Default Mode (tour list with search):

  • A valid container element ID

For Trip Suggestions Mode (type: "trip_details"):

  • A valid container element ID
  • tourTag is required to filter and display specific tours
  • departureFrom date is important for showing available tours within the specified timeframe
  • duration (in months) to define the date range for tour availability

Quick Start

Complete Integration Example

Here's a complete example showing all three steps together:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Booking Site</title>

    <!-- Step 1: Embed the Widget Script -->
    <script src="https://widget.bookingsystem.se/res_widget_script.iife.js"></script>
</head>
<body>
    <!-- Step 2: Create Container Element -->
    <div id="vaylo-widget"></div>

    <!-- Step 3: Initialize the Widget -->
    <script>
        window.addEventListener("load", function () {
            Widget.mount({
                containerID: "vaylo-widget",
            });
        });
    </script>
</body>
</html>
Success! The widget should now be visible and functional on your page.
Next Steps: Customize the widget appearance and behavior using the configuration options detailed in the sections below.

Configuration Options

The widget accepts a configuration object with the following properties. You can easily customize the widget's appearance and behavior:

Property Type Description
containerID string ID of the DOM element where the widget will be mounted
type string Widget display mode: "default" (tour list with search) or "trip_details" (tour suggestions view)
theme object Full control over colors, fonts, font sizes, and header height
locale string Language of the widget (e.g., "en", "sv", "nb")
currencyCode string ISO currency code (e.g., "SEK", "USD", "EUR")
itemPerPage number Number of tours to display per page
dateFormat string Customize how dates appear (e.g., "dd MMM, yyyy")
departureFrom string Earliest departure date to show tours (Format: "YYYY-MM-DD")
duration number Number of months to look ahead for tours from departureFrom date
tourTag number Filter tours by a specific tour tag ID (optional)
searchKeys array Define which search filters are available to users. See Search Behavior section for all available options.
redirects object Define where users are sent on search, booking, and after booking success. See Redirect URLs section for details.

Example Configuration

Widget.mount({
    containerID: "vaylo-widget",
    type: "default",
    locale: "en",
    currencyCode: "SEK",
    itemPerPage: 10,
    dateFormat: "dd MMM, yyyy",
    departureFrom: "2025-04-24",
    duration: 3,
    tourTag: 101,
    showAllToursByDefault: false,
    searchKeys: [
        "tour_tag",
        "tags",
        "country",
        "location",
        "category",
        "passenger_types",
        "from_departure_date",
        "to_departure_date",
    ],
    redirects: {
        searchURL: "https://yourdomain.com/search",
        bookingURL: "https://yourdomain.com/bookings",
        successURL: "https://yourdomain.com/success",
    },
    theme: {
        color: {
            themeColor: "#FF5733",
            textColor: "#0A2540",
            secondaryTextColor: "#999999",
            backgroundColor: "#ffffff",
            foregroundColor: "#E9EBEE",
            borderColor: "#D1D9E6",
        },
        font: {
            default: "Inter",
            heading: "Playfair Display",
        },
        size: {
            heading: 31,
            title: 20,
            regular: 16,
            default: 13,
        },
        headerHeight: 81,
    },
});

What You Can Change Yourself

You can freely adjust the following configuration options to customize the widget behavior and appearance:

Colors and Fonts

Customize inside the theme section:

  • Theme colors (themeColor, textColor, backgroundColor, etc.)
  • Font families (default and heading fonts)
  • Font sizes (heading, title, regular, default)
  • Header height

Text Language

Set the locale property to change the widget language:

  • "en" - English
  • "sv" - Swedish
  • "nb" - Norwegian Bokmål

Displayed Tours

Control which tours are shown by adjusting:

  • departureFrom - Earliest departure date (Format: YYYY-MM-DD)
  • duration - Number of months to look ahead
  • tourTag - Filter tours by a specific tour tag ID
  • showAllToursByDefault - Whether to display all tours before user searches

Search Behavior

Configure available search filters using the searchKeys array. Important: Keys must match exactly (case-sensitive).

Available search keys:

  • "tour_tag"
  • "tags"
  • "category"
  • "country"
  • "location"
  • "destination"
  • "passenger_types"
  • "number_of_passengers"
  • "from_departure_date"
  • "to_departure_date"
  • "pickup_locations"
  • "departure_date"
Important: Be careful with spelling - search keys must match exactly as shown above.

Redirect URLs

Define user flow by setting URLs in the redirects section:

  • searchURL - Where users are redirected on search
  • bookingURL - Where users go when booking
  • successURL - Post-booking success page

Widget Container CSS

Customize the container element's appearance with your own CSS:

#vaylo-widget {
    width: 1200px;
    max-width: 100%;
    margin: -10rem auto 0;
}

You can adjust width, margins, padding, and other CSS properties to fit your page layout.

Theme Customization

Customize the widget's appearance by providing a theme configuration with colors, fonts, sizes, and header height:

Color Properties

Property Type Description
themeColor string Primary brand color for buttons, links, and accents
textColor string Main text color
secondaryTextColor string Secondary text color for less prominent text
backgroundColor string Background color of the widget
foregroundColor string Foreground/surface color for cards and panels
borderColor string Border color for inputs and dividers

Font Properties

Property Type Description
default string Default font family for body text
heading string Font family for headings and titles

Available font options: "Inter", "Poppins", "Montserrat", "Playfair Display", "Raleway", "Bebas Neue", "Roboto", "Open Sans", "Lato", "Doto"

Size Properties

Property Type Description
heading number Font size for main headings (in pixels)
title number Font size for section titles (in pixels)
regular number Font size for regular text (in pixels)
default number Base font size (in pixels)

Other Properties

Property Type Description
headerHeight number Gap spacing from your website's header (in pixels). Used for sticky positioning to prevent overlap with your site's header

Complete Theme Example

Widget.mount({
    containerID: "vaylo-widget",
    locale: "en",
    currencyCode: "SEK",
    theme: {
        color: {
            themeColor: "#2563eb",
            textColor: "#0A2540",
            secondaryTextColor: "#64748b",
            backgroundColor: "#ffffff",
            foregroundColor: "#f8fafc",
            borderColor: "#e2e8f0",
        },
        font: {
            default: "Inter",
            heading: "Poppins",
        },
        size: {
            heading: 28,
            title: 20,
            regular: 16,
            default: 14,
        },
        headerHeight: 70,
    },
    redirects: {
        searchURL: "https://yourdomain.com/search"
    }
});

Usage Examples

Basic HTML Integration

Simple integration in a static HTML page:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Booking Site</title>

    <!-- Load Widget Script -->
    <script src="https://widget.bookingsystem.se/res_widget_script.iife.js"></script>

    <style>
        #vaylo-widget {
            width: 1200px;
            max-width: 100%;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <div id="vaylo-widget"></div>

    <script>
        window.addEventListener("load", function () {
            Widget.mount({
                containerID: "vaylo-widget",
                type: "default",
                locale: "en",
                currencyCode: "SEK",
                itemPerPage: 10,
                dateFormat: "dd MMM, yyyy",
                redirects: {
                    searchURL: "https://yourdomain.com/search",
                    bookingURL: "https://yourdomain.com/bookings",
                    successURL: "https://yourdomain.com/success"
                }
            });
        });
    </script>
</body>
</html>

React Integration

Using the widget in a React application:

import { useEffect } from 'react';

function BookingWidget() {
    useEffect(() => {
        const script = document.createElement('script');
        script.src = 'https://widget.bookingsystem.se/res_widget_script.iife.js';
        script.async = true;

        script.onload = () => {
            if (window.Widget) {
                window.Widget.mount({
                    containerID: "vaylo-widget",
                    type: "default",
                    locale: "en",
                    currencyCode: "SEK",
                    itemPerPage: 10,
                    dateFormat: "dd MMM, yyyy",
                    redirects: {
                        searchURL: "https://yourdomain.com/search",
                        bookingURL: "https://yourdomain.com/bookings",
                        successURL: "https://yourdomain.com/success"
                    }
                });
            }
        };

        document.head.appendChild(script);

        return () => {
            // Cleanup if needed
            document.head.removeChild(script);
        };
    }, []);

    return (
        <div
            id="vaylo-widget"
            style={{ width: '1200px', maxWidth: '100%', margin: '0 auto' }}
        />
    );
}

export default BookingWidget;

Vue.js Integration

Using the widget in a Vue.js application:

<template>
    <div id="vaylo-widget" style="width: 1200px; max-width: 100%; margin: 0 auto;"></div>
</template>

<script>
export default {
    name: 'BookingWidget',
    mounted() {
        const script = document.createElement('script');
        script.src = 'https://widget.bookingsystem.se/res_widget_script.iife.js';
        script.async = true;

        script.onload = () => {
            if (window.Widget) {
                window.Widget.mount({
                    containerID: "vaylo-widget",
                    type: "default",
                    locale: this.$i18n?.locale || "en",
                    currencyCode: "SEK",
                    itemPerPage: 10,
                    dateFormat: "dd MMM, yyyy",
                    redirects: {
                        searchURL: "https://yourdomain.com/search",
                        bookingURL: "https://yourdomain.com/bookings",
                        successURL: "https://yourdomain.com/success"
                    }
                });
            }
        };

        document.head.appendChild(script);
    },
    beforeUnmount() {
        // Cleanup if needed
    }
};
</script>

With Custom Theme

Applying custom colors and fonts:

<script>
window.addEventListener("load", function () {
    Widget.mount({
        containerID: "vaylo-widget",
        type: "default",
        locale: "en",
        currencyCode: "SEK",
        itemPerPage: 10,
        dateFormat: "dd MMM, yyyy",
        theme: {
            color: {
                themeColor: "#8b5cf6",
                textColor: "#1e1b4b",
                secondaryTextColor: "#64748b",
                backgroundColor: "#ffffff",
                foregroundColor: "#faf5ff",
                borderColor: "#e9d5ff"
            },
            font: {
                default: "Poppins",
                heading: "Playfair Display"
            },
            size: {
                heading: 32,
                title: 22,
                regular: 16,
                default: 14
            },
            headerHeight: 80
        },
        redirects: {
            searchURL: "https://yourdomain.com/search",
            bookingURL: "https://yourdomain.com/bookings",
            successURL: "https://yourdomain.com/success"
        }
    });
});
</script>

Advanced Usage

Custom Search Filters

Control which search filters are available to users:

Widget.mount({
    containerID: "vaylo-widget",
    locale: "en",
    currencyCode: "SEK",
    itemPerPage: 10,
    dateFormat: "dd MMM, yyyy",
    // Only enable specific search filters
    searchKeys: [
        "country",
        "category",
        "from_departure_date",
        "to_departure_date"
    ],
    redirects: {
        searchURL: "https://yourdomain.com/search",
        bookingURL: "https://yourdomain.com/bookings",
        successURL: "https://yourdomain.com/success"
    }
});
Important: Make sure search keys match exactly. Available options are: "tour_tag", "tags", "category", "country", "location", "destination", "passenger_types", "number_of_passengers", "from_departure_date", "to_departure_date", "pickup_locations", "departure_date"

Multiple Widgets on One Page

Display different widget configurations on the same page:

<!-- First Widget: Summer Tours -->
<div id="summer-tours-widget"></div>

<!-- Second Widget: Winter Tours -->
<div id="winter-tours-widget"></div>

<script>
window.addEventListener("load", function () {
    // Summer tours widget
    Widget.mount({
        containerID: "summer-tours-widget",
        locale: "en",
        currencyCode: "SEK",
        itemPerPage: 6,
        dateFormat: "dd MMM, yyyy",
        redirects: {
            searchURL: "https://yourdomain.com/search?type=summer"
        }
    });

    // Winter tours widget
    Widget.mount({
        containerID: "winter-tours-widget",
        locale: "en",
        currencyCode: "SEK",
        itemPerPage: 6,
        dateFormat: "dd MMM, yyyy",
        redirects: {
            searchURL: "https://yourdomain.com/search?type=winter"
        }
    });
});
</script>

Date Range Configuration

Control the date range for available tours using the departureFrom and duration parameters. These settings determine which tour dates are displayed to users.

How It Works

The date range is calculated as follows:

  • Start Date: Specified by departureFrom (format: YYYY-MM-DD)
  • End Date: Automatically calculated as departureFrom + duration months
  • Default Behavior: If not specified, the widget shows all available future dates

Parameter Details

Parameter Type Description
departureFrom string Starting date for tour availability in YYYY-MM-DD format (e.g., "2025-04-01")
duration number Number of months from the start date to display tours (e.g., 12 for one year)

Example 1: Fixed Date Range (12 Months)

Display tours from April 1, 2025, through March 31, 2026:

Widget.mount({
    containerID: "vaylo-widget",
    locale: "en",
    currencyCode: "SEK",
    itemPerPage: 10,
    dateFormat: "dd MMM, yyyy",
    departureFrom: "2025-04-01",
    duration: 12,
    redirects: {
        searchURL: "https://yourdomain.com/search",
        bookingURL: "https://yourdomain.com/bookings",
        successURL: "https://yourdomain.com/success"
    }
});

Example 2: Dynamic Date Range

Set the start date dynamically to today's date:

const today = new Date().toISOString().split('T')[0]; // Format: YYYY-MM-DD

Widget.mount({
    containerID: "vaylo-widget",
    locale: "en",
    currencyCode: "SEK",
    departureFrom: today,
    duration: 12,
    redirects: {
        searchURL: "https://yourdomain.com/search",
        bookingURL: "https://yourdomain.com/bookings",
        successURL: "https://yourdomain.com/success"
    }
});

Best Practices

  • Plan Ahead: Set a date range that aligns with your tour planning and booking cycles
  • Consider Lead Time: Account for how far in advance customers typically book tours
  • Regular Updates: If using fixed dates, remember to update them periodically
  • Test Coverage: Ensure your date range covers all tours you want to display
Note: Tours outside the specified date range will not be displayed, even if they are available in your system. Ensure your date range covers all tours you want to offer.