Trials

Let people try your app before they buy. KeyGrant has two kinds of trial: one your app starts on a device with no key, and a key you issue under a trial license model.

KindStarted byLength set by
A device trial The app, with no key; one per device The product's Trial length
A trial key You: a license key issued under a trial license model The model's Trial length, days

Device trials

The product's Trial length, on its Settings tab, sets how many days a device trial lasts.

At a glance

Trial length
0 to 3,650 days; 0 means no trial
A new product
14 days
Trials per device
One for each product
Its lease
Runs to the trial's end, licenses one device, covers every version

Your app starts the trial:

Main process
const status = await license.status();
if (status.state === "unlicensed") { const trial = await license.startTrial(); if (trial.state === "trial") { showTrialBanner(trial.trialDaysLeft); } else { // Trials are off, KeyGrant could not be reached, or this device's trial is over. showActivationWindow(); }} else if (status.state === "trial") { showTrialBanner(status.trialDaysLeft);}
  • KeyGrant keeps one trial per device for each product, identified by the device's fingerprint. Starting a trial again on the same device resumes the same trial, and its start date can only move earlier.
  • The trial ends Trial length days after it started. Its lease carries the product's Trial entitlements (see Editions & entitlements).
  • A device trial is not a license: it does not count toward your plan, and no webhooks are sent for it.

What startTrial() returns

startTrial() has no error result. It returns a status:

SituationResult
Trials are off (Trial length 0) or the product is archived, and the device has no trial on record It does not get one: unlicensed
The device already has a trial, on an archived product It gets the trial back, which runs to its end
The device already has a trial, and Trial length is 0 It gets the trial back, over: expired with reason trial
KeyGrant cannot be reached The status the device already has

Buying from the trial

Give the app a Buy button that opens your Stripe Payment Link.

Main process
import { shell } from "electron";
// The Buy button, while the app holds no key.shell.openExternal("https://buy.stripe.com/your-payment-link");
// The customer types the key from the delivery email:const result = await license.activate(enteredKey);if (result.ok) showThanks();
  1. The customer chooses Buy and pays.
  2. The checkout creates the key and delivers it (see Key delivery email).
  3. The customer types the key into the app, which activates it with activate(key).
  • The checkout must create a key, so the link's price is mapped to a model (see Map prices to license models).
  • For a customer who already holds a key, open upgradeUrl(link) instead, so the sale finds their key (see Sell an upgrade).
  • How a purchase counts in Analytics: see Analytics.

Device trial details

Changing the trial while trials run

status() and refresh() do not request a new trial lease while the device's trial lease is valid. A shorter Trial length ends a trial already past it once startTrial() runs again.

Note

If you change Trial length or Trial entitlements while trials run, also call startTrial() on a launch in a trial: the example above calls it only on a device with nothing stored.

Analytics

  • Analytics counts a device trial as Came back after day one when KeyGrant hears from it 24 hours or more after the trial started. A trial started less than 24 hours ago is left out of that step.
  • The SDK reports a launch in a trial itself. When status() answers trial and neither a report nor a startTrial() has been made in the last day, it tells KeyGrant the app ran, in the background.
  • status() neither waits for that request nor reads its answer, and does not fail offline, so your app needs no extra call. An app left running for days is counted again when it calls status() a day later.
  • A trial bought in its first day stops reporting once it holds a key, so it counts as bought but not as come back.
  • The trial funnel counts a trial under Bought a license once a key a checkout created is activated on the device that ran it, when the trial started before the purchase.
  • Each trial and each purchase counts once: a second key bought on the same device, or another key of the same purchase, is not counted again. A key an upgrade offer creates, or one you issue by hand, from your server or by import, is never counted.

The launch report is in @keygrant/electron 0.3.1, .NET and Rust 0.2.1, Swift and C++ 0.2.0, and Dart 0.1.0, its first version. An app on an earlier SDK is counted as come back only when it calls startTrial() again.

Seeing each trial

A product's Trials tab lists its device trials in a table, newest started first, 25 a page. Chips filter it to Running, Bought or Ended, a search finds a trial by the start of its device ID or IP address, the start of a license key, or any part of an email address, and every column header sorts the table: one press sorts by it, a second reverses it. Location sorts by the country's name, A to Z, then by IP address. Signals sorts by how many signals a row shows, and rows with the same number are newest first.

  • Status is Running while the trial is inside the trial length and no key has been bought from the device, Bought once one has, and Ended when the length has passed without a purchase. A bought trial says on which day of the trial the key was bought, or how long before the trial the device was licensed. Running counts as the Trials running figure on Home does.
  • Last seen, Version, and Location (the country and the IP address of the trial's last check-in) come from that check-in. A version in amber is older than the product's current version or the newest major your licensed customers run, whichever is higher.
  • License is the key bought from the device, or the one it is activated on, with the address it was sold to.
  • The IP address is cleared 30 days after that check-in. The country stays.
  • Signals are hints, never a verdict. +N on network means N other trials of the product last checked in from the same network in the past 30 days: the same IPv4 address, or the same IPv6 /64. Existing customer means the license shown was issued before the trial started, never counting a test key. Returned means the trial was still checking in a day or more after it started. Tor exit means the check-in came through the Tor network. Several trials on one network can be an office, a family or your own testing, as well as someone starting the trial again on new devices.
  • The address and country come from Cloudflare, never from your app, and KeyGrant never uses them to refuse a trial.

Keeping a trial through a reinstall

KeyGrant ties the trial to the device, so reinstalling the app resumes it. An SDK can also store the trial's start date somewhere that survives an uninstall, using a registry stash. The SDK sends the earliest trial start recorded on the device with each trial request.

  • .NET, Rust and C++: include a Windows registry stash.
  • Swift: uses a Keychain stash on iOS and iPadOS by default, and includes one to pass on macOS.
  • Dart: uses a Keychain stash on iOS and iPadOS by default.
  • Otherwise: the default stash stores nothing.

Each SDK's page shows how to set its stash (see SDKs).

Trial keys

A license model of type Trial issues trial keys, by hand or from your server. A trial key is activated like any key, and its status is licensed.

  • Length: the model's Trial length, days, from the day it is issued.
  • Devices and versions: the model's device limit and versions (every version unless set otherwise).
  • Entitlements: the model's, or the product's Trial entitlements when the model grants none.

A checkout never creates a trial key

A paid checkout on a trial model's Processor price it maps to creates a paid key of that model:

  • A perpetual key for a one-time price, and a subscription key when the price recurs.
  • It takes the model's device limit, versions and Offline days.
  • It takes only the model's own entitlements, never the product's Trial entitlements.

When a trial key ends

  • KeyGrant sends a trial.ending webhook within a day of the key having 3 days or fewer left (see Events).
  • The customer also gets the Trial ending email when the product's License delivery tab is set to KeyGrant sends them, its Trial ending email is on, and the key has an email address and is not a test license.