# Signals & subscriptions

Discovery helps accommodation providers win over travelers in the planning phase of the traveler journey. The goal is to spark conversations with travelers deciding where to go next, increasing conversion and revenue with impact tracked in real-time.

Third-party integrations, analytics, logging, and many other use cases can be supported through Discovery signals and subscriptions to enrich these conversations in a way that’s good for both brand and traveler.

[Set Signals](#set-signals) allow you to push data into Discovery.

[Get Signals](#get-signals) allow you to retrieve data from Discovery.

[Discovery Actions](#discovery-actions) allow you to make Discovery do something.

[Discovery Behaviors](#discovery-behaviors) allow you to customize and configure Discovery behavior.

[Signal Subscriptions](#signal-subscriptions) allow you to subscribe to real-time application signals

* [Discovery Signals](#discovery-events)
* [Experience Signals](#experience-signals)
* [Booking Engine Signals](#booking-engine-signals)

***

## Set Signals

When your website visitor chooses a category or page that can provide useful data and insight for Discovery, you can send a signal (via GTM, Javascript, etc.) so Discovery can respond with the appropriate context. This creates a seamless, cohesive experience as your visitor interacts with your website and Discovery.

<table><thead><tr><th width="238">Set Signal</th><th>What does this change?</th></tr></thead><tbody><tr><td><em><strong>PLAN</strong></em></td><td></td></tr><tr><td>adults</td><td>Default adults.</td></tr><tr><td>children</td><td>Default children.</td></tr><tr><td>endDate</td><td>Default departure date.</td></tr><tr><td>email</td><td>Planner email address.</td></tr><tr><td>first</td><td>Planner first name.</td></tr><tr><td>promoCode</td><td>Default promo/discount/group code.</td></tr><tr><td>rooms</td><td>Default number of rooms.</td></tr><tr><td>beds</td><td>Default number of beds.</td></tr><tr><td>startDate</td><td>Default arrival date.</td></tr><tr><td>language</td><td>Sets the Discovery language (if supported).</td></tr><tr><td><em><strong>PROPERTY</strong></em></td><td></td></tr><tr><td>property</td><td>Default plan location.</td></tr><tr><td>product</td><td>Default product. Requires property.</td></tr><tr><td>linkerValue</td><td><p>Passes an analytics linker value to associate the current session with a group booking or property code. This is typically used when a visitor arrives via a direct link that contains tracking parameters.</p><pre><code>linkerValue: {
  propertyCode: '10000',
  groupId: 'SUMMER2026'
}
</code></pre></td></tr><tr><td><em><strong>LOCATION</strong></em></td><td></td></tr><tr><td>country</td><td>Default country for map navigation.</td></tr><tr><td>region</td><td>Default region for map navigation. Requires country.</td></tr><tr><td>city</td><td>Default city for map navigation. Requires region.</td></tr></tbody></table>

#### Example

The sample code below passes signals from a specific website page to Discovery. In this example, if the visitor triggered Discovery from that page, the experience they see will be suited for planners looking for vacation rentals in Orlando.

```javascript
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    property: {
      property: 'my-prop',
      product: 'rentals'
    },
    location: {
      country: 'us',
      region: 'fl',
      city: 'orlando'
    }
  }
});
```

***

## Get Signals

Discovery will learn valuable signals as your visitor progresses through their travel planning on our application. You may want to pass these signals to your website or booking engine so that those experiences respond better to your visitors' interactions.

<table><thead><tr><th width="239">Get Signal</th><th>What does this return?</th></tr></thead><tbody><tr><td>plan</td><td><p>Callback is called with an object matching the following schema:</p><pre><code>{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "LanguageCode": {
      "type": "string"
    },
    "Beds": {
      "type": "integer"
    },
    "Rooms": {
      "type": "integer"
    },
    "Children": {
      "type": "integer"
    },
    "Adults": {
      "type": "integer"
    },
    "Email": {
      "type": "string"
    },
    "PlannerName": {
      "type": "string"
    },
    "StartDate": {
      "type": "string"
    },
    "EndDate": {
      "type": "string"
    },
    "DestinationName": {
      "type": "string"
    },
    "NamedRangeTitle": {
      "type": "string"
    },    "PropertyPhotoUrl": {
      "type": "string"
    },
    "PropertyName": {
      "type": "string"
    }
  },
  "required": [
    "LanguageCode",
    "Email",
    "PlannerName",
    "StartDate",
    "EndDate",
    "DestinationName",
    "NamedRangeTitle",
    "PropertyPhotoUrl",
    "PropertyName"
  ]
}
</code></pre></td></tr><tr><td>experiment</td><td><p>Returns the current experiment flag for the user. The callback receives a boolean:</p><ul><li><code>true</code> if the user is in the Discovery group.</li><li><code>false</code> if user is in the Control group.</li></ul><pre><code>(window.ftSignals = window.ftSignals || []).push({
  type: 'get',
  payload: {
    experiment: function(isExperiment) {
      console.log('User is in experiment:', isExperiment);
    }
  }
});
</code></pre></td></tr></tbody></table>

#### Example

The sample code below passes insight that Discovery learned about a travel planner into the booking engine using the call “prePopulateBookingEngine” with the full plan object.

```javascript
(window.ftSignals = window.ftSignals || []).push({
  type: 'get', 
  payload: {
    plan: prePopulateBookingEngine      
}});
```

***

```javascript
function logBookingEngineTransfer(e) {
 //Enter code to log the fact that the current user is being transferred to the booking engine
 //dataLayer.push({event:’Discovery.Transfer.Bookingengine’, …e});
}
(window.ftSignals = window.ftSignals || []).push({
  type: 'subscribe', 
  payload: {
    onDiscoveryTransfer: logBookingEngineTransfer
}});
```

***

## Discovery Actions

Action signals allow you to programmatically control the Discovery experience from your website. You can open, close, or trigger Discovery, track custom analytics events, and more.

| Action signal           | What it does                                                             |
| ----------------------- | ------------------------------------------------------------------------ |
| openDiscovery           | Opens the Discovery experience.                                          |
| closeDiscovery          | Closes the Discovery experience.                                         |
| revokeDiscovery         | Removes Discovery from the page entirely.                                |
| triggerDiscovery        | Triggers the Discovery flow (evaluates experiment and entry conditions). |
| bookingBarButtonClicked | Simulates a booking bar button click.                                    |
| setExperimentFlag       | Overrides the experiment flag for the current user.                      |
| trackAnalyticsEvent     | Fires a custom analytics event into Discovery's analytics pipeline.      |

#### Example 1: Open Discovery

The sample code below programmatically opens the Discovery experience on the page.

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'action',
  payload: {
    type: 'openDiscovery'
  }
});
```

#### Example 2: Track a Custom Analytics Event

The sample code below fires a custom analytics event through Discovery's analytics pipeline, which will be forwarded to all connected analytics providers (GTM, Adobe, etc.).

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'action',
  payload: {
    type: 'trackAnalyticsEvent',
    props: {
      category: 'engagement',
      action: 'cta-click',
      label: 'hero-banner',
      value: 1,
      data: { campaign: 'summer-2026' }
    }
  }
});
```

#### Example 3: Override Experiment Flag

The sample code below forces the current user into (or out of) the Discovery experiment.

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'action',
  payload: {
    type: 'setExperimentFlag',
    props: { flag: true }
  }
});
```

***

## Discovery Behaviors

Behavior signals allow you to customize how Discovery handles key interactions such as booking engine transfers and page context resolution. Behaviors are passed as part of a set signal and accept a static value, a promise, or a callback function.

<table><thead><tr><th width="266.59765625">Behavior signal</th><th>What it controls</th></tr></thead><tbody><tr><td>bookingEngineTransfer</td><td>Customizes how Discovery navigates the user to the booking engine.</td></tr><tr><td>discoveryPageContextSetter</td><td>Dynamically provides property and location context for the current page.</td></tr><tr><td>bookingEngineTransfer</td><td><p>Controls the booking engine transfer behavior.<br><br>Accepts an <code>ExternalNavigationConfig</code> object with the following options:<br></p><ul><li><p><code>method</code></p><ul><li>HTTP method for the transfer.</li><li>Supported values: <code>GET</code>, <code>POST</code></li></ul></li><li><p><code>queryParameters</code></p><ul><li>Additional query parameters to append to the booking engine URL</li></ul></li><li><p><code>fragmentParameters</code></p><ul><li>Additional query parameters to append to the booking engine URL.Additional fragment (hash) parameters to append to the booking engine URL.</li></ul></li><li><p><code>target</code></p><ul><li>Window target for navigation.</li><li>Supported values: <code>_self</code>, <code>_blank</code>, <code>_parent</code>, <code>_top</code></li></ul></li><li><p><code>customHandler</code></p><ul><li>A function that receives the full booking engine URL DTO for fully custom navigation handling.</li><li>Can return <code>void</code>, a URL string, or a promise.</li></ul></li></ul></td></tr></tbody></table>

#### Example 1: Add Query Parameters to Booking Engine Transfer

The sample code below appends custom tracking parameters to every booking engine transfer URL.

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    behaviors: {
      bookingEngineTransfer: {
        queryParameters: {
          utm_source: 'flipto',
          utm_medium: 'discovery'
        }
      }
    }
  }
});
```

#### Example 2: Open Booking Engine in a New Tab

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    behaviors: {
      bookingEngineTransfer: {
        target: '_blank'
      }
    }
  }
});
```

#### Example 3: Custom Booking Engine Transfer Handler

The sample code below provides a custom handler that intercepts the booking engine transfer entirely, allowing you to construct or redirect to a custom URL.

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    behaviors: {
      bookingEngineTransfer: {
        customHandler: function(dto) {
          // dto contains the full booking engine URL details
          // Return a URL string to redirect, or handle navigation yourself
          window.location.href = 'https://booking.example.com/reserve?id=' 
          + dto.propertyCode;
        }
      }
    }
  }
});
```

#### Example 4: Dynamic Booking Engine Transfer with a Callback

Behaviors also accept a callback function, which is called at transfer time. This is useful when the configuration depends on runtime state.

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    behaviors: {
      bookingEngineTransfer: function() {
        return {
          method: 'POST',
          queryParameters: {
            session: getSessionToken()
          },
          target: '_self'
        };
      }
    }
  }
});
```

#### Example 5: Page Context Setter

Allows your website to dynamically provide property and location context to Discovery based on the current page. This is useful when page context cannot be determined from a single static signal — for example, on single-page applications where the URL changes without a full page reload.

The callback receives no arguments and should return an object with `property` and/or `location`.

**Setting Static Page Context:**

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    behaviors: {
      discoveryPageContextSetter: {
        property: {
          property: 'my-resort',
          product: 'suites'
        },
        location: {
          country: 'us',
          region: 'fl',
          city: 'orlando'
        }
      }
    }
  }
});
```

**Dynamic Page Context with a Callback:**\
The sample code below uses a callback to resolve the current page context at the time Discovery needs it, which is useful for single page applications or pages where the context changes dynamically.

```
(window.ftSignals = window.ftSignals || []).push({
  type: 'set',
  payload: {
    behaviors: {
      discoveryPageContextSetter: function() {
        // Read context from the current page state
        var slug = document.querySelector('[data-property-slug]')?.getAttribute('data-property-slug');
        return {
          property: {
            property: slug
          }
        };
      }
    }
  }
});
```

## Signal Subscriptions

Flip.to allows websites to subscribe and receive signals about user behavior in real time. To subscribe to a particular signal, simply push one of the supported signals into “window\.ftSignals” and define the function to be called when the signal is triggered

#### Example 1: Discovery Open

The sample code below subscribes to the “onDiscoveryOpen” signal, which is triggered as soon as the user clicks one of the booking buttons to open Discovery. You can customize the code under “logDiscoveryOpen()” to log to your Analytics package each time Discovery is being opened on the website.

```javascript
function logDiscoveryOpen(e) {
 //Enter code to log the fact that the current user just opened Discovery   
 //dataLayer.push({event:’Discovery.Open’, …e});
}
(window.ftSignals = window.ftSignals || []).push({
  type: 'subscribe', 
  payload: {
    onDiscoveryOpen: logDiscoveryOpen
}});
```

#### Example 2: Booking Engine Transfer

The sample code below subscribes to the “onDiscoveryTransfer” signal, which is triggered just before Discovery sends a user to the Booking Engine. You can customize the code under “logBookingEngineTransfer()” to log this event into your analytics package.

***

### Discovery Signals

Discovery can also send data for specific events that happen during our traveler conversations. Subscribing to this data may be useful for analytics and to understand planner behaviors.

<table><thead><tr><th width="262">Subscription</th><th>When event fires</th></tr></thead><tbody><tr><td>onDiscoveryLoad</td><td>Upon Discovery script loading on the page.</td></tr><tr><td>onDiscoveryExperimentSet</td><td>Upon experiment (Flip.to or Control) being set for a new user.</td></tr><tr><td>onDiscoveryOpen</td><td>When the user triggers the opening of a Discovery experience (by clicking the booking button for instance).</td></tr><tr><td>onDiscoveryPlanChange</td><td>When user plan information changes (changing dates, etc.).</td></tr><tr><td>onDiscoveryTransfer</td><td>When the user is being sent to the booking engine.</td></tr><tr><td>onDiscoveryBootstrap</td><td>When the Discovery application has fully bootstrapped and is ready to receive signals. This is useful when you need to ensure Discovery is initialized before pushing signals.</td></tr></tbody></table>

#### Event Data

Each subscription notification call will pass the following data to its subscribers:

<table><thead><tr><th width="208.33333333333331">Attribute</th><th>Description</th></tr></thead><tbody><tr><td>source</td><td>The internal Flip.to Discovery ID, as a string (GUID).</td></tr><tr><td>experiment</td><td><p>Indicates which experiment the user falls under:</p><ul><li>Set to <code>'true'</code> for Discovery.</li><li>Set to <code>'false'</code> for the hotel’s own booking widget.</li></ul></td></tr><tr><td>mode</td><td><p><em>Optional</em><br>Context description for the event, which varies by event type.</p><p>Supported values are as follows:<br></p><p>onDiscoveryOpen</p><ul><li><p><code>planner-flow</code></p><ul><li>User opened Discovery through the standard planner flow (e.g. clicking a booking button).</li></ul></li><li><p><code>returning-user</code></p><ul><li>User is a returning visitor who previously interacted with Discovery.</li></ul></li><li><p><code>discovery-router</code></p><ul><li>User opened Discovery through the multi-property router flow.<br></li></ul></li></ul><p>onDiscoveryTransfer</p><ul><li><p><code>unveil</code></p><ul><li>Name and email revealed</li></ul></li><li><p><code>skip</code></p><ul><li>Discovery complete without unveiling</li></ul></li><li><p><code>bypass</code></p><ul><li>Discovery not shown</li></ul></li><li><p><code>continue</code></p><ul><li>Uuser already has a plan)</li></ul></li></ul></td></tr><tr><td>plan</td><td>Object to include all relevant information for the user's intended stay as follows:</td></tr><tr><td>checkinDate</td><td>Check-in date, as a date object.</td></tr><tr><td>checkoutDate</td><td>Check-out date, as a date object.</td></tr><tr><td>adults</td><td>Number of adults, if specified.</td></tr><tr><td>children</td><td>Number of children, if specified.</td></tr><tr><td>promoCode</td><td>The promo code, if any, as a string.</td></tr><tr><td>property</td><td>Object with data of current property. This includes the following attributes:</td></tr><tr><td>displayName</td><td>The property’s name, as a string.</td></tr><tr><td>slug</td><td>The property’s unique slug, as a string.</td></tr><tr><td>code</td><td>The property’s booking engine code, as a string.</td></tr><tr><td>id</td><td>The property’s internal id, as a string (GUID).</td></tr></tbody></table>

#### Example

```
source: "a99a9b5e-b551-41aa-b946-19350ceff89e"
experiment: true
mode: "unveil"
plan:
checkinDate: Wed Dec 15 2021 00:00:00 GMT-0500 (Eastern Standard Time) {}
checkoutDate: Sat Dec 18 2021 00:00:00 GMT-0500 (Eastern Standard Time) {}
adults: 2
children: 0
promoCode: holiday
property: {displayName: "Test Hotel", slug: "test-hotel", id: "5fd181b8-61c7-4194-bb78-566c1ca7de11", code: "10000"}
```

***

### Experience Signals

Discovery can also send data for specific events that happen during our traveler conversations. Subscribing to this data may be useful for analytics and to understand planner behaviors.

<table><thead><tr><th width="292">Subscription</th><th>When event fires</th></tr></thead><tbody><tr><td>OnDiscoveryExperienceOpen</td><td>Upon user clicking to view a particular experience</td></tr></tbody></table>

#### Event Data

Each subscription notification call will pass the following data to its subscribers:

<table><thead><tr><th width="208.33333333333331">Attribute</th><th>Description</th></tr></thead><tbody><tr><td>uuid</td><td>The internal Flip.to experienceID, as a string (GUID).</td></tr><tr><td>languageCode</td><td>The language code the user is currently using to view the event.</td></tr><tr><td>name</td><td>The experience name.</td></tr><tr><td>isRecurring</td><td>Indicates whether experience is recurring.</td></tr><tr><td>recurringStartDate</td><td>The start date of recurring experiences.</td></tr><tr><td>recurringStartDate</td><td>The end date of recurring experiences.</td></tr><tr><td>occurrences</td><td>The occurrences of this experience around the time of booking.<br><br>This will not provide dates that goes beyond more than 1 week before or after the user intended check-in and/or check-out dates</td></tr><tr><td>venue</td><td>The venue name in which experience is taking place.</td></tr><tr><td>tags</td><td>An array of all tags that are associated with the experience.<br><br>Tags are keywords to define the events, and are always defined in English.</td></tr></tbody></table>

#### Example

```
{
    "uuid": "95B7F6E7-50E4-4749-9A5B-2DE28E6BB624",
    "languageCode":"en",
    "name": "Madagascar the Musical",
    "isRecurring": false,
    "recurringStartDate": "2023-04-07T19:00:00",
    "recurringEndDate": "2023-04-07T00:00:00",
    "occurrences": [{ "startDate": "2023-04-07T00:00:00", "endDate": "2023-04-07T00:00:00" }],
    "venue": { "name": "Au-Rene Theater at the Broward Center"},
    "tags": ["performance_show", "theatre", "music", "kid_friendly"]
}
```

***

### Booking Engine Signals

After a website visitor submits their name and email address, Discovery sends them to the booking engine. Flip.to allows booking engines to subscribe and receive signals about each travel planner.

#### Example

The sample code below provides the travel planner's first name and email address to the booking engine, which can be used to populate form fields for example.

```javascript
function OnDiscoveryPlanInfo(planInfo){
    // Enter your code here to use the planner's first name and email 
}
(ftDatalayer = ftDatalayer || []).push({type: 'ft-get-signal', payload: {
key: 'planInfo',
value: OnDiscoveryPlanInfo
}});
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flip.to/docs/integrations/analytics/signals-and-subscriptions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
