In-app SDK
Inside the app, every page of your site gets a small JavaScript object, window.EasyVial. There's nothing to install — the app injects it before your page scripts run.
window.EasyVial
| Member | Type | Description |
|---|---|---|
isApp | true | Always true inside the app. The object is undefined in normal browsers. |
version | number | SDK version. Currently 1. |
store | string | Your store slug. |
trackOrder(order) | (order: { id: string; orderKey: string }) => boolean | Links an order placed in the app to the customer's phone. Returns false if id or orderKey is missing. |
Readiness
The object is injected before your scripts, so it's normally available immediately. For single-page apps that render the confirmation page late, listen for easyvial:ready as a fallback:
JavaScript
function whenApp(fn) {
if (window.EasyVial) return fn(window.EasyVial);
window.addEventListener("easyvial:ready", () => fn(window.EasyVial), { once: true });
}
whenApp((app) => app.trackOrder({ id: order.number, orderKey: order.secretKey }));React / Next.js
TrackAppOrder.tsx
"use client";
import { useEffect } from "react";
declare global {
interface Window {
EasyVial?: {
isApp: true;
version: number;
store: string;
trackOrder(o: { id: string; orderKey: string }): boolean;
};
}
}
export function TrackAppOrder({ id, orderKey }: { id: string; orderKey: string }) {
useEffect(() => {
const send = () => window.EasyVial?.trackOrder({ id, orderKey });
if (window.EasyVial) send();
else window.addEventListener("easyvial:ready", send, { once: true });
}, [id, orderKey]);
return null;
}TypeScript types
easyvial.d.ts
export interface EasyVialOrder {
/** Your order number, as shown to the customer and sent to the Order API. */
id: string;
/** Per-order secret. Must match "order_key" in your Order API request. */
orderKey: string;
}
export interface EasyVialSDK {
readonly isApp: true;
readonly version: number;
readonly store: string;
trackOrder(order: EasyVialOrder): boolean;
}
declare global {
interface Window { EasyVial?: EasyVialSDK }
interface WindowEventMap { "easyvial:ready": Event }
}Other signals inside the app
| Signal | Value | Use it to |
|---|---|---|
| User agent | … EasyVial/0.1 | Detect the app server-side (e.g. skip your web age gate or app banner) |
| Landing query | utm_source=easyvial&utm_medium=app | Attribute sessions and orders to the app |
| Push taps | utm_medium=push&utm_campaign=<id> | Attribute orders to a specific push notification |
Behaviour you should know about
| Thing | Behaviour in the app |
|---|---|
| Links to other domains | Open inside the app (so payment pages work). target="_blank" links open in the phone's browser. |
| tel:, mailto:, sms: | Handed to the phone |
| Cookies / logins | Persist between app launches, separately from Safari/Chrome |
| Hidden elements | Selectors you list in Store setup → "Hide inside the app" are hidden with CSS (e.g. your header or cookie banner) |
| Vial QR codes | If a QR code links to your site, scanning it from COA Lookup opens that page in the Shop tab |
| Messages | trackOrder is only accepted from pages on your own domain |
Don't rely on
window.EasyVial for anything security-sensitive. It tells you the page is probably inside the app, nothing more. Authorisation always happens server-side via the signed Order API.