NAV Navbar
html
  • Introduction
  • Authentication
  • Getting Started
  • Custom Views & Styling
  • Search Widgets
  • Rental Widgets
  • Account Widgets
  • Custom Widgets
  • Creating Quotes & Bookings
  • Introduction

    The Trailblazer Widget library allows you to create fully custom search experiences that leverage the Trailblazer API for finding the perfect rental for your users. From there, transactions can be completed either from yoru own site, or by directing users through to the Outdoorsy checkout flow for processing.

    Authentication

    In order to leverage the widget library, you'll need to have a Partner ID provided from your account rep.

    Getting Started

    Widgets work by embedding themselves into elements that you provide on the page. To give you a quick example of how this works, we'll create an example project. We'll use Bootstrap for some basic styling, but this is NOT required to use the library - we're just using it for the grids as a demonstration.

    Load Dependencies

    You can drop these into the footer of your application

    <link rel="stylesheet" href="https://d1o5877uy6tsnd.cloudfront.net/sdk/v2/trailblazer-widget.css">
    <script type="text/javascript" src="https://d1o5877uy6tsnd.cloudfront.net/sdk/v2/trailblazer-widget.js"></script>
    

    To get started, you'll need to load the Trailblazer JS SDK and some base styles. The stylesheet provides some lightweight styling for core components like sliders and date pickers. You'll want to create a custom stylesheet to provide your own styling. Here are some skeleton stylesheets you can use to get started:

    Creating Widget Containers

    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div id="location-search"></div>
            </div>
        </div>
        <div class="row">
            <div class="col-sm-4">
                <div id="date-container"></div>
                <div id="vehicle-price"></div>
            </div>
            <div class="col-sm-8">
                <div id="rental-results"></div>
            </div>
        </div>
    </div>
    

    Widgets need to be given containers that they can be created inside of, so the first step is going to be creating a basic site structure for widgets to use. Here's an example, but you're welcome to do this however you'd like. We're going to assume you're using the bootstrap grid system for the demo, but it's not required.

    Initializing your App

    var trailblazer = Trailblazer({
        partnerId: {{yourID}},
        urlParams: true,
        currency: 'USD', //optional, controls pricing currency you get back
        locale: 'en-us', // optional, controls which checkout flow users are directed to for translations
        filtersChangedCallback: function(currentFilters) {
            // optional callback, if you provide one it allows
            // you to listen externally for filter changes
            // useful when creating your own custom components
        }
    });
    
    // Now that we've initialized the app, we can begin enabling the widgets we want
    
    // first we add the widget for displaying results
    trailblazer.addWidget(trailblazer.widgets.RentalList, "rental-results");
    
    // now lets add the search widgets
    trailblazer.addWidget(trailblazer.widgets.LocationSearch, "location-search");
    trailblazer.addWidget(trailblazer.widgets.PriceRange, "vehicle-price");
    trailblazer.addWidget(trailblazer.widgets.DatePicker, "date-container");
    
    trailblazer.start();
    
    

    Now that you've created a basic site skeleton, we'll include a new JS file where we add your widgets to the page

    It's a good idea to enable the urlParams feature, as that'll allow your renters to share links with friends to search results and also keep things like dates in sync between pages.

    Adding Widgets To The Page

    Once you've added your widgets, you'll just need to start up your app

    To finish adding widgets to your page, you can call the addWidget function on your app.

    Custom Views & Styling

    trailblazer.addWidget(widget, container-el, {
        cssClasses: {
            root: "custom-class",
            etc...
        }
    });
    
    <script type="text/html" id="result-template">
        <div class="col-sm-4">
            <a href="/rental/{{id}}">
                <div class="rental-result">
                <div class="rv-img">
                    <div class="rv-image-container">
                    <img src="{{primary_image_url}}" alt="{{name}} in {{home.city}}, {{home.state}}">
                    </div>
                    <div class="price">${{active_options.price_day}}<span class="price-info">/night</span></div>
                </div>
                <div class="rv-info">
                    <div class="rv-title">{{name}}</div>
                    <div class="rv-subtitle">
                    <span class="pull-right">
                        <i class='fa fa-heart favorites-count'></i> {{score}} / 5
                    </span>
                    {{location.city}}, {{location.state}}
                    </div>
                </div>
                </div>
            </a>
        </div>
    </script>
    
    var resultsTemplate = document.getElementById("result-template").innerHTML;
    
    trailblazer.addWidget(trailblazer.widgets.RentalList, "rental-container", {
        formatItem: function(singleItem) { return singleItem; },
        templates: {
            loading: 'loading now!',
            available: resultsTemplate
        },
    });
    

    You have access to all of the data we have stored for each rental, including:

    {
    "id": 1,
    "name": "2012 Forest River Primetime Tracer",
    "type": "trailer",
    "description": "description here",
    "vehicle_class": "",
    "vehicle_make": "Forest River",
    "vehicle_model": "Tracer",
    "slug": "/rv-rental/burrton_ks/2012_forest-river_tracer_1-listing",
    "partner_url": "https://redirect.outdoorsy.com?partner_id={{yourID}}&url=1"
    "vehicle_year": 2012,
    "vehicle_length": 34,
    "availability_set": false,
    "created": "2018-07-23T04:11:50.845213Z",
    "updated": "2018-08-01T02:16:38.659458Z",
    "owner_user_id": 394213,
    "published": true,
    "features": {
        "air_conditioner": true,
        "audio_inputs": true,
        "awning": true,
        "backup_camera": false,
        "beds_full": 0,
        "beds_king": 0,
        "beds_queen": 0,
        "beds_twin": 0,
        "bike_rack": false,
        "burning_man_friendly": true,
        "cd_player": true,
        "ceiling_fan": false,
        "dining_table": true,
        "extra_storage": true,
        "fuel_tank": 0,
        "fuel_type": "",
        "generator": false,
        "gray_tank": 0,
        "handicap_accessible": false,
        "heater": true,
        "hitch_weight": 0, ...
    },
    "sleeps": 10,
    "seatbelts": 0,
    "sleeps_adults": 0,
    "sleeps_kids": 0,
    "images": [{
        "id": 499049,
        "rental_id": 74746,
        "primary": true,
        "position": 0,
        "tags": "exterior",
        "description": "",
        "skip_enhance": false,
        "video": false,
        "urlSmall" : "https://link-here",
        "urlMedium" : "https://link-here",
        "urlLarge" : "https://link-here"}, ...
    ],
    "position": 0,
    "score": 0,
    "reviews_num": 0,
    "group_reviews_score": 0,
    "group_reviews_num": 0,
    "favorite_count": 0,
    "location": {
        "city": "Burrton",
        "state": "KS",
        "county": "",
        "country": "US",
        "zip": "67020",
        "lat": 38,
        "lng": -97.73
    },
    "locale": {
        "base_currency": "USD",
        "distance_unit": "miles",
        "weight_unit": "lbs",
        "length_unit": "feet",
        "liquid_unit": "gallons"
    },
    "security_deposit": 500,
    "use_day_pricing": false,
    "cancel_policy": "flexible",
    "minimum_days": 2,
    "active_options": {
        "date": "",
        "day_price": 150,
        "week_price": 770,
        "month_price": 3136,
        "cancel_policy": "flexible",
        "minimum_days": 0,
        "use_day_pricing": false,
        "instant_book": false
    },
    "cancel_text": "",
    "house_rules": "rules go here!",
    "mileage_usage_item": {
        "id": 65001,
        "name": "mileage",
        "unit": "mile",
        "included": 200,
        "included_period": "mile",
        "unlimited": true,
        "archived": false,
        "tax_rate_id": 0
    },
    "pickup_unavailable": {
        "sunday": false,
        "monday": false,
        "tuesday": false,
        "wednesday": false,
        "thursday": false,
        "friday": false,
        "saturday": false
    },
    "dropoff_unavailable": {
        "sunday": false,
        "monday": false,
        "tuesday": false,
        "wednesday": false,
        "thursday": false,
        "friday": false,
        "saturday": false
    },
    "primary_image": { image object ...},
    }
    

    One of the best features of the widget system is the ability to customize how search results are displayed. By default, Trailblazer provides a simple template to get you started, but you're welcome to override it with your own. The templating system uses Hogan.js for templates. Here are some basic examples to get you started.

    Customizing widgets

    All widgets provide at least some level of customization, either via CSS or custom templates.

    For CSS, you have the ability of using the provided trailblazer classes, or you can pass in your own. The basic structure for passing in your own classes is shown here.

    Each widget will specify the classes that are available for passing in. If you're looking for a starting point for creating your CSS changes, here are a few skeleton options you can leverage.

    Custom Templates

    Most widgets also allow you to pass in a template to take even more control over the widget interface. Templates must be a string, but it's common practice to define them in your HTML, and then pull them in as a var. Templates are written using Hogan.js, which provide all the functionality of Mustache templates.

    If you need to manipulate any data before it gets passed into your template, you'll also have access to a param called formatItem. formatItem takes in a single data object and returns a transformed one with any changes you'd like. We'll then pass that new data object into the template for rendering.

    Checkout the example to see how templates work.

    Custom Select or Checkbox filters

    Our select and checkbox filters provide a fairly robust level of customization out of the box. For most use cases, you should be able to work within those conventions without any trouble. If you need to create more custom components, then you always have the option of taking full control. To learn more, check out the Custom Widgets section of the documentation.

    Search Widgets

    Trailblazer provides several widgets out of the box, but also gives you the ability to define your own. We'll walk you through each of the options in this section.

    Search Results

    trailblazer.addWidget(trailblazer.widgets.RentalList, "rental-container", {
        formatItem: function(singleItem) { return singleItem; },
        templates: {
            available: "{{name}} - {{id}} -- {{currentPrice.day}}",
            loading: "Loading..."
        },
        filters: {},
        cssClasses: {
            root: ["test", "here"],
            singleItem: "rental-item"
        }
    });
    

    This is one of the main elements for a search interface, it allows you to set the templates for search results as well as triggers the initial rentals load. Without this widget, rentals will never display on your page.

    Options

    Search Metadata

    trailblazer.addWidget(trailblazer.widgets.Metadata, "metadata-container", {
        formatItem: function(singleItem) {return singleItem;}, // optional
        template: "Showing {{totalVisible}} of {{totalFiltered}} matching rentals"
    });
    

    Show metadata on the current set of search results, for example: "Showing 17 of 35 available rentals".

    Available Template Data

    Customization

    Date Picker

    trailblazer.addWidget(trailblazer.widgets.DateRange, "dates-container", {
        rentalId: 1426 // optional, only include if this is for a specific vehicle
    });
    

    The date picker allows your renters to select a date range they're interested in renting a vehicle for. If you include a rental ID when initializing, then we'll also load availability information so that renters know when the unit is free.

    Customization

    The main point of customization for the datepicker is going to be through CSS for adjusting colors. Check out the starter CSS file to learn more.

    Price Slider

    trailblazer.addWidget(trailblazer.widgets.PriceRange, "price-container", {
        cssClasses: {
            root: "rental-price",
            selectedValues: '',
            selectedMin: '',
            selectedMax: ''
        }
    });
    

    Allows you to filter results by price using a slider

    Customization

    Pagination

    trailblazer.addWidget(trailblazer.widgets.Pagination, "pagination-container", {
        perPage: 10,
        cssClasses: {
            container: "container",
            subcontainer: "subcontainer",
            activePage: "active-page"
        }
    });
    

    The pagination component adds a pagination bar to the page

    Customization

    The main point of customization for the pagination component is going to be through CSS.

    Checkbox Filters

    trailblazer.addWidget(trailblazer.widgets.CheckboxFilter, "checkbox-container", {
        apiFilters: function(selectedOptions, allOptions, apiObject) {
            return apiObject;
        },
        template: '{{label}}',
        selected: function(item, apiObject) {
            return true;
        },
        formatItem: function(singleItem) { return singleItem; },
        cssClasses: {
            root: "fuel-type-container",
            listItem: "fuel-type",
            listItemLabel: "fuel-type-label"
        },
        options: function(currentRentals, rentalMeta) {
            return [
                {
                    label: "Label here",
                    value: "Value here"
                }
            ]
        }
    });
    

    This widget allows you to use either a dynamic or static list of checklist items to filter results.

    Select Tag Filters

    trailblazer.addWidget(trailblazer.widgets.SelectFilter, "select-container", {
        multi: false, // indicates if multiple values can be selected
        apiFilters: function(selectedOptions, allOptions, apiObject) {
            return apiObject;
        },
        template: '{{label}}',
        selected: function(item, apiObject) {
            return true;
        },
        formatItem: function(singleItem) { return singleItem; },
        cssClasses: {
            root: "fuel-type-container",
            listItem: "fuel-type",
            listItemLabel: "fuel-type-label"
        },
        options: function(currentRentals, rentalMeta) {
            return [
                {
                    label: "Label here",
                    value: "Value here"
                }
            ]
        }
    });
    

    Provides a drop-down select tag with full text search and optional multiselect.

    Clear Filters

    trailblazer.clearFilters()
    

    For example, you could do this on a button click

    <a href="" id="clear-filters">Clear Filters</a>
    <script>
    $("#clear-filters").click(function(e) {
        e.preventDefault();
        trailblazer.clearFilters();
    });
    </script>
    

    At any time, you have the ability to clear the existing filters on the search results. To do so, you can call clearFilters on the Trailblazer library.

    Rental Widgets

    The following widgets are available fore specific rentals on the platform. They're useful when building out a landing page for a specific vehicle, perhaps after the user has already gone through search and is looking to make a booking.

    Quote Widget

    trailblazer.addWidget(trailblazer.widgets.Quote, "quote-container", {
        rentalId: 1426, //your rental ID
        formatItem: function(quoteResponse) { return quoteResponse; },
        template: {
         error: "{{error}}",
         noQuote: "before-quote-entered",
         quote: "see notes for quote templates"
        },
        cssClasses: {
            root: "base-class",
            lineItem: "trailblazer-line-item",
            lineItemDescription: "trailblazer-line-item-description",
            lineItemPrice: "trailblazer-line-item-price",
            lineTotal: "trailblazer-line-total",
            lineSubtotal: "trailblazer-line-subtotal",
            lineTax: "trailblazer-line-tax",
            lineServiceFee: "trailblazer-line-service-fee",
            error: "trailblazer-quote-error"
        }
    });
    

    Provides a quote widget that shows pricing information for selected dates

    Customization

    Date Picker

    trailblazer.addWidget(trailblazer.widgets.DateRange, "dates-container", {
        rentalId: 1426 // optional, only include if this is for a specific vehicle
    });
    

    The date picker allows your renters to select a date range they're interested in renting a vehicle for. If you include a rental ID when initializing, then we'll also load availability information so that renters know when the unit is free.

    Customization

    The main point of customization for the datepicker is going to be through CSS for adjusting colors. Check out the starter CSS file to learn more.

    Availability Calendar

    trailblazer.addWidget(trailblazer.widgets.DateRange, "availability-calendar-container", {
        rentalId: 1426,
        embedded: true,
        numberOfMonths: 2 // optional
    });
    

    You can also use the date picker to display an embedded availability calendar for your vehicles. Using the embedded availability calendar is very similar to the above date picker

    Customization

    In addition to the same CSS customization above for the date picker, you can also indicate the number of months you'd like to show by including a numberOfMonths config option. If you don't include one, we'll default to either 1 or 2 months depending on the screen size of the user. We recommend that you do something similar if you'd like to customize this. If you only indicate 3 months for example, there's a large likelihood that the calendar won't display correctly on mobile devices.

    List Add-Ons

    trailblazer.addWidget(trailblazer.widgets.AddonList, "addons-container", {
        rentalId: 1426, //your rental ID, required
        formatItem: function(singleAddon) { return singleAddon; },
        template: 'template string',
        filter: function(addOn) {
            // optional, allows you to filter add-ons so you only display the ones that match any criteria.
            // this will only show the add-on with an ID of 1, for example.
            return addOn.id === 1;
        }
    });
    

    Allows you to list all the available add-ons for this vehicle based on your Account settings.

    Customization

    Review List

    trailblazer.addWidget(trailblazer.widgets.ReviewList, "reviews-container", {
        rentalId: 1426, //your rental ID, this is optional. if omitted we'll load the user reviews for all rentals
        formatItem: function(singleReview) { return singleReview; },
        template: "review template",
        filters: {
            limit: 4, // return only 4 reviews
            score_gte: 4 // return only 4 and 5 star reviews
        }
    });
    

    Displays a list of reviews for a single rental or all rentals.

    Customization

    Account Widgets

    These widgets work on an individual account level. They're useful for building up a search page for your own rental company.

    Review List

    trailblazer.addWidget(trailblazer.widgets.ReviewList, "reviews-container", {
        rentalId: 1426, //your rental ID, this is optional. if omitted we'll load the user reviews for all rentals
        formatItem: function(singleReview) { return singleReview; },
        template: "review template",
        filters: {
            limit: 4, // return only 4 reviews
            score_gte: 4 // return only 4 and 5 star reviews
        }
    });
    

    Displays a list of reviews for a single rental or all rentals.

    Customization

    Location Filter

    trailblazer.addWidget(trailblazer.widgets.LocationList, "locations-container", {
        cssClasses: {
            root: "rental-location-container",
            listItem: "rental-location",
            listItemLabel: "rental-location-label"
        },
        formatItem: function(singleLocation) { return singleLocation; },
        template: 'template string'
    });
    

    Automatically loads available locations and allows filtering by one or many. Locations can be added/removed in your Wheelbase dashboard.

    Customization

    The cssClasses above are an optional way for you to take control over the classes used on the widget.

    You can also pass in a template as a string.

    Custom Widgets

    It's easy to extend the Trailbase widget system by hooking into some provided functionality to listen for data changes or emit new filter requests on rentals. Using these hooks, users have created custom date pickers, custom filter options for things like ratings/reviews and more.

    Filters changed callback

    var trailblazer = Trailblazer({
        partnerId: {{yourID}},
        urlParams: true,
        filtersChangedCallback: function(currentFilters) {
            // optional callback, if you provide one it allows
            // you to listen externally for filter changes
            // useful when creating your own custom components
        }
    });
    

    When initializing your Trailblazer app, you have the ability to specify a callback we'll use to notify you of any changes to the filter params. This could be useful for updating interfaces external to Trailblazer, tracking purposes, or anyting else you can imagine.

    Viewing current filters

    var currentFilters = trailblazer.getFilters();
    

    At any time, you have the ability to pull the current API filters stored within the Trailblazer library. This is often useful when paired with the ability to emit filter changes using a similar method documented below.

    Changing current filters

        var trailblazer = Trailblazer({partnerId: 123});
        var currentFilters = trailblazer.getFilters();
        currentFilters['length[gte]'] = 25;
        trailblazer.changeFilters(currentFilters);
    

    calling changeFilters on your trailblazer instance allows you to overwrite any filters currently in place in the library. Note that the existing state will be replaced by your new one, so it's useful to request the current filter state if you intend to preserve the majority of the current filters. Once you call the changeFilters function, all widgets within the interface will automatically reload to match the new state and new search results will be loaded from the server.

    Creating Quotes & Bookings

    The Trailblazer JS SDK provides the option to create custom quotes for your shoppers and initiate bookings without leaving your site. The bulk of the checkout process wills till be handled by Trailblazer, but the first step can be handled on your end to provide a more seamless interaction.

    Adding add-ons to a quote

    let addonId = 1; // the add-on's ID
    let addonCount = 1; // how many of this add-on we want
    trailblazer.addAddon(addonId, addonCount);
    

    For example, one HTML use case may be

    <div id="addon-1"></div>
    <div class="addon-1-button">
        <a href="" id="add-addon-1">Add to Trip</a>
    </div>
    
    <script>
     $("#add-addon-1").click(function(e) {
         e.preventDefault();
         trailblazer.addAddon(1, 1);
     });
    </script>
    

    If you'd like to create a shopping experience on your site for handling Add-ons, you can do so leveraging the addAddon API provided by Trailblazer. Here's a quick example of how you might accomplish that. Many users will pair this functionlaity with the AddonList widget covered above to create a dynamic experience for renters.

    Initializing bookings from your site

    Once you have your renters booking info and contact details, you can initiate a quote with the following command, which returns a promise:

     trailblazer.startBooking({
         firstName: "tim",
         lastName: "smith",
         email: "email@provider.com",
         phone: "555-555-5555",
         rentalId: 7,
         campaign: '',
         source: '',
         medium: ''
     }).then(function(url, bookingDetails) {
         console.log("booking details if you need them", bookingDetails);
         window.location.href = url;
     }).catch(function(error) {
         alert("There was an error creating your booking: " + error);
     });
    

    If you'd like to pass in your own add-ons and dates when creating a booking, you can do so as follows:

     trailblazer.startBooking({
         firstName: "tim",
         lastName: "smith",
         email: "email@provider.com",
         phone: "555-555-5555",
         rentalId: 7,
         from: 'YYYY-MM-DD',
         to: 'YYYY-MM-DD',
         items: [{id: 1, count: 2}],
         campaign: '',
         source: '',
         medium: ''
     }).then(function(url, bookingDetails) {
         console.log("booking details if you need them", bookingDetails);
         window.location.href = url;
     }).catch(function(error) {
         alert("There was an error creating your booking: " + error);
     });
    

    Once a user has customized their booking with add-ons, you have the ability to initiate a booking from your site. We won't dive into the specifics on how to start this process, as the options would be up to your team to decide on. You could create a form on your page to collect renter information, initiate a modal, have users already logged in, etc...

    We'll pull the information from the users cart to collect start date, end date and selected add-ons and create the quote. It'll then be up to you to forward the renter into the remainder of the checkout flow using the URL provided.

    If you don't want to go through the process of building up a quote using the addAddons functionality, you can also pass in any desired add-ons directly into the startBooking call.