TrialSignal Integration Guide

Behavioural insight for trial users.

Contents

1. Overview

TrialSignal helps you understand how your trial users behave: pageviews, engagement and high-intent actions (like clicking “Upgrade”).

There are three core pieces:

  1. Backend collector (trialsignal.io/collect) – receives JSON from your app.
  2. Tracker script (trialsignal.io/tracker.js) – handles pageviews + trial state.
  3. Custom event helper (tsTrack()) – lets you log key actions.

2. Quick start

Paste this snippet into your app layout / template so it appears on every page (usually just before </head> or at the top of <body>).

<!-- TrialSignal.io -->
<script>
!function(w,d,_,endpoint){
    // Init config
    w.tsAnalytics = {
        key: "ts_Cf9OSCZiLzvMajszVhuz0KaIuHgyTprzcsXtE61XoCOXPN2r7Bg6gkcCiwwj73GR",
        userId: "83dcefb7",
        userEmail: "Pencil Function Bands",
        trial: {
            status: "converted",
            type: "14-day trial",
            startedAt: "2019-11-28 11:26:26",
            endsAt: "2020-05-28",
            convertedAt: "2020-04-24 14:18:31 00:00:00",
            plan: "ultimate_gbp_monthly"
        }
    };

    // Global tsTrack() for custom events
    w.tsTrack = function(name, props){
        if (!w.tsAnalytics || !w.tsAnalytics.key) return;

        try {
            var payload = {
                project_key: w.tsAnalytics.key,
                event_type: "event",
                user: {
                    id: w.tsAnalytics.userId || null,
                    label: w.tsAnalytics.userEmail || null
                },
                event: {
                    name: name,
                    properties: props || {}
                },
                ts: new Date().toISOString()
            };

            // Always use fetch. No sendBeacon.
            fetch(endpoint, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(payload),
                keepalive: true,
                credentials: "omit"  
            }).catch(function(){});
        } catch(err){}
    };

    // Load tracker.js (pageviews + trial sync)
    var s = d.createElement("script");
    s.async = 1;
    s.src = "https://trialsignal.io/tracker.js?v=1";
    d.head.appendChild(s);

}(window, document, 0, "https://trialsignal.io/collect");
</script>
Where to get your key?
Use the public key configured for your TrialSignal project and replace YOUR_PUBLIC_KEY_HERE.

3. Automatic pageview tracking

Once tracker.js is loaded, it automatically sends a pageview event on page load.

What the tracker sends

tracker.js calls the backend with a payload like:

{
  "project_key": "YOUR_PUBLIC_KEY_HERE",
  "event_type":  "pageview",
  "session_id":  "ts_analytics_sess_value",
  "user": {
    "id":    123,
    "label": "[email protected]"
  },
  "page": {
    "path":     "/pricing",
    "url":      "https://yourapp.com/pricing",
    "referrer": "https://google.com"
  },
  "ts":         "2025-12-08T15:26:15.864Z",
  "user_agent": "Mozilla/5.0 ...",
  "device":     "Desktop"  // Desktop | Mobile | Tablet
}

Sessions

The backend stores sessions in analytics_session, and pageviews in analytics_pageview, including IP (packed), user agent, device, and country where available.

4. Tracking trial state

TrialSignal keeps a single trial record per user in analytics_trial. This is updated via trial_state events.

How it’s sent

On page load, if you pass a trial object and a userId, the tracker will send:

{
  "project_key": "YOUR_PUBLIC_KEY_HERE",
  "event_type":  "trial_state",
  "user": {
    "id":    123,
    "label": "[email protected]"
  },
  "trial": {
    "status":       "trialing",       // or 'converted', 'expired', 'cancelled', etc.
    "type":         "standard_1mth",
    "started_at":   "2025-12-08T15:26:15.864Z",
    "ends_at":      "2026-01-10T15:26:15.864Z",
    "converted_at": null,
    "plan":         null
  },
  "ts": "2025-12-08T15:26:15.864Z"
}

Backend behaviour

Important: user_id is required for trial_state events. If it’s missing, the backend returns 400 user_id required for trial_state.

5. Tracking custom events

Use tsTrack(name, properties) wherever you want to log a meaningful action (e.g. “clicked upgrade”, “created first project”, etc.).

Example: upgrade button click

<button id="upgrade-btn">Upgrade to Ultimate</button>

<script>
  document.getElementById('upgrade-btn')?.addEventListener('click', function () {
    window.tsTrack && window.tsTrack('clicked_upgrade_button', {
      location: 'pricing_page',
      plan:     'ultimate'
    });
  });
</script>

What the helper sends

tsTrack() sends an event payload to the same /collect endpoint:

{
  "project_key": "YOUR_PUBLIC_KEY_HERE",
  "event_type":  "event",
  "user": {
    "id":    123,
    "label": "[email protected]"
  },
  "event": {
    "name":       "clicked_upgrade_button",
    "properties": {
      "location": "pricing_page",
      "plan":     "ultimate"
    }
  },
  "ts": "2025-12-08T15:26:15.864Z"
}

Backend behaviour

6. Recommended usage patterns

6.1. Initialise after login

After a user logs in (or when you know who they are), render the snippet with their userId, userEmail, and trial information. This ensures:

6.2. Update trial on key lifecycle events

6.3. Use a small set of consistent event names

Keep names lowercase and snake_case – it makes reporting and filtering easier.

6.4. Error handling

The backend will respond with JSON – on hard errors you’ll see {"ok": false, "error": "..."}. For unknown event_type values, it just returns {"ok": true, "ignored": true}.