No results for ""
Alerts & Notifications
Scripts can surface events to the user through TD.UI. Two methods are available, and they are meant for different jobs:
TD.UI.showAlert(message, type)
A quick status toast, such as "Script started" or "Subscribe failed". Best for confirming script state to the user.
TD.UI.notify({ ... })
Market and strategy alerts. Delivers an in-app alert card, a browser (OS desktop) notification, or both, with smart routing, rate limiting and grouping.
await them and wrap them in try/catch like any other platform call (Rules 3 and 15).showAlert — TD.UI.showAlert
Shows a toast to surface success or failure to the user.
await TD.UI.showAlert("Your message here", "success");
Alert types: "success", "error", "info", "warning".
notify — TD.UI.notify
Sends a notification from a script to two possible surfaces:
In-app alert card
Added to the Alert Manager stack in the top-right corner of the spreadsheet. Cards stay until the user dismisses them (up to 50 cards).
Browser (OS) notification
A native desktop popup raised through the browser's Notification API. Visible even when the user is in another window.
Syntax
const result = await TD.UI.notify({
title: "Breakout Alert", // required
body: "RELIANCE crossed 3050.00", // optional
toast: true, // optional, default true
browser: true, // optional, default true
tag: "reliance-breakout", // optional, default null
urgent: false, // optional, default false
});
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
title |
string | Required | Headline of the notification. Cannot be empty; an error is thrown if it is missing. |
body |
string | "" |
Details such as price, quantity or the reason the alert fired. |
toast |
boolean | true |
Deliver to the in-app alert card stack. Set false to disable. |
browser |
boolean | true |
Deliver as an OS desktop notification. Set false to disable. |
tag |
string | null |
Notifications with the same tag replace each other instead of stacking. |
urgent |
boolean | false |
Skips the 2-second pacing window and raises its own OS popup immediately. |
Return Values
The promise resolves to a string telling you which channel was reached.
| Value | Meaning |
|---|---|
'browser' |
Raised as an individual OS desktop popup. |
'queued' |
An OS popup was already raised in the last 2 seconds, so this one is held and merged into a digest popup. |
'toast' |
Delivered as an in-app alert card only (either browser: false, or the tab was in focus). |
'blocked' |
Browser notification was requested, but permission is denied or not granted in the browser's site settings. |
'none' |
Both toast: false and browser: false were set; nothing was shown. |
notify resolves to 'blocked' and an informational warning appears in the script console. Check for it in onStart so the user can be told early.Choosing Where It Is Delivered
The toast and browser flags give three useful modes.
In-app card only
toast: true, browser: false
No permission needed. Works instantly. Cards persist until dismissed.
Browser (OS) only
toast: false, browser: true
Needs notification permission. Delivered even when the spreadsheet tab is in focus.
Smart default (both)
toast: true, browser: true
The platform picks the channel based on whether the user is looking at the tab.
How the smart default routes
| User state | What happens | Resolves to |
|---|---|---|
| Tab is visible and focused | In-app card only. The OS popup is suppressed to avoid a duplicate alert on a screen the user is already watching. | 'toast' |
| Tab is in the background, minimized or hidden | Card is added to the stack for when the user returns, and an OS notification is raised (or queued for a digest). | 'browser' / 'queued' |
toast: false turns off this focus check, so a browser-only notification appears whether or not the tab is in focus.Rate Limiting & Digests
Ticks and 1-minute bars can fire many times per second. To avoid flooding the operating system, the browser channel is paced per script.
Pacing window
One OS popup every 2 seconds per script.
Queue & digest
Extra notifications in that window are queued (up to 100) and merged into one summary popup.
Single item kept
If only one item was queued, its original title and body are shown, not a generic summary.
Title: "4 notifications" Body: "NIFTY, RELIANCE, TCS, +1 more"
urgent and tag
urgent: true
Skips the 2-second pacing window and shows its own individual OS popup immediately. Resolves to 'browser' instead of 'queued'.
Use for: stop-loss hit, margin call, broker disconnect.
Avoid for: routine price ticks. Too many urgent popups cause the browser to throttle the site.
tag: "..."
Notifications sharing a tag replace each other in the OS notification center instead of stacking.
Use for: status that evolves, such as "trailing-sl-nifty" or "feed-status".
Avoid for: separate signals (trade logs). A static tag makes each new signal overwrite the previous one.
Complete Examples
1. In-app card only — strong candle close
Alerts once when a 1-min bar closes near its high. The lastAlertTs guard prevents repeat alerts for the same bar.
const SYMBOLS = ["RELIANCE"];
let symbolMap = {};
let lastAlertTs = {};
TD.on("bar1min", async (data) => {
try {
const name = symbolMap[data[0]] || data[0];
const high = parseFloat(data[3]);
const low = parseFloat(data[4]);
const close = parseFloat(data[5]);
if (close > high - (high - low) * 0.1 && lastAlertTs[name] !== data[1]) {
lastAlertTs[name] = data[1];
await TD.UI.notify({
title: name + " - Bullish Candle Close",
body: "1-min bar closed strong at " + close,
toast: true,
browser: false,
});
}
} catch (err) {
TD.log("Bar error: " + err.message);
}
});
TD.onStart = async () => {
try {
symbolMap = {};
lastAlertTs = {};
const response = await TD.Feed.addSymbols(SYMBOLS);
if (!response.success) throw new Error(response.message);
for (const sym of response.symbollist) {
symbolMap[sym[1]] = sym[0];
}
} catch (err) {
TD.log("Start error: " + err.message);
}
};
TD.onStop = async () => {
await TD.Feed.removeSymbols(SYMBOLS);
};
TD.onError = (err) => {
TD.log("Error: " + err.message);
};
2. Browser only — permission check on start
Sends a desktop notification when the script starts and tells the user if notifications are blocked.
TD.onStart = async () => {
try {
const status = await TD.UI.notify({
title: "Script Engine Started",
body: "Real-time monitoring is active.",
toast: false,
browser: true,
});
if (status === "blocked") {
TD.log("Notifications are blocked. Allow them in the browser site settings.");
await TD.UI.showAlert("Browser notifications are blocked for this site", "warning");
}
} catch (err) {
TD.log("Start error: " + err.message);
}
};
TD.onError = (err) => {
TD.log("Error: " + err.message);
};
3. Urgent — stop-loss hit
Fires one immediate OS popup the first time LTP falls to or below the stop level. The triggered flag keeps the tick handler from alerting on every tick.
const SYMBOLS = ["RELIANCE"];
const STOP_LOSS = 1300;
let symbolMap = {};
let triggered = false;
TD.on("tick", async (data) => {
try {
if (triggered) return;
const name = symbolMap[data[0]];
if (!name) return;
const ltp = parseFloat(data[2]);
if (ltp <= STOP_LOSS) {
triggered = true;
await TD.UI.notify({
title: name + " Stop-Loss Hit",
body: "LTP " + ltp + " is at or below " + STOP_LOSS,
urgent: true,
});
}
} catch (err) {
TD.log("Tick error: " + err.message);
}
});
TD.onStart = async () => {
try {
triggered = false;
symbolMap = {};
const response = await TD.Feed.addSymbols(SYMBOLS);
if (!response.success) throw new Error(response.message);
for (const sym of response.symbollist) {
symbolMap[sym[1]] = sym[0];
}
} catch (err) {
TD.log("Start error: " + err.message);
}
};
TD.onStop = async () => {
await TD.Feed.removeSymbols(SYMBOLS);
};
TD.onError = (err) => {
TD.log("Error: " + err.message);
};
4. Tag — one updating notification per symbol
Every 5-min bar replaces the previous notification for that symbol instead of stacking new ones.
const SYMBOLS = ["NIFTY 50", "RELIANCE"];
let symbolMap = {};
TD.on("bar5min", async (data) => {
try {
const name = symbolMap[data[0]] || data[0];
await TD.UI.notify({
title: name + " 5-min Close",
body: "Close: " + parseFloat(data[5]),
tag: "bar5-" + name, // same symbol replaces the previous notification
});
} catch (err) {
TD.log("Bar error: " + err.message);
}
});
TD.onStart = async () => {
try {
symbolMap = {};
const response = await TD.Feed.addSymbols(SYMBOLS);
if (!response.success) throw new Error(response.message);
for (const sym of response.symbollist) {
symbolMap[sym[1]] = sym[0];
}
} catch (err) {
TD.log("Start error: " + err.message);
}
};
TD.onStop = async () => {
await TD.Feed.removeSymbols(SYMBOLS);
};
TD.onError = (err) => {
TD.log("Error: " + err.message);
};
Do & Avoid
Alert on a state change
Track a flag or last-alerted timestamp so a condition notifies once, not on every tick or bar where it stays true.
Handle 'blocked'
Check the return value at least once in onStart and tell the user how to allow notifications.
Prefer bar events for alerts
Evaluate conditions in bar1min / bar5min where possible. Use tick only for time-critical levels.
Put the symbol name in the title
Digest popups list titles, so "RELIANCE - Breakout" reads better than "Breakout". Resolve names with symbolMap.
Notifying on every tick
A condition that stays true will fire on every tick. This fills the 50-card stack and floods the OS queue.
Marking routine alerts urgent
Reserve urgent: true for critical events only.
One static tag for distinct signals
Each new signal would overwrite and hide the previous one. Include the symbol or signal id in the tag, or omit it.
Using console.log / console.warn
Log with TD.log() so output reaches the console panel and session log.
Which Settings Should I Use?
| I want to... | Use |
|---|---|
| Confirm script started or failed | TD.UI.showAlert(msg, type) |
| Show a persistent card in the sheet, no permission needed | notify({ toast: true, browser: false }) |
| Always raise a desktop popup, even if the tab is in focus | notify({ toast: false, browser: true }) |
| Card when watching, desktop popup when away | notify({ title, body }) (default) |
| Critical event that must not be delayed or merged | urgent: true |
| One notification that keeps updating | tag: "..." |
Quick Checklist Before Using notify
titleis a non-empty string- The call is
awaited and wrapped in try/catch - Values from tick/bar events are parsed with
parseFloat()before comparing - A flag or timestamp guard stops the same condition from notifying repeatedly
urgentis used only for critical eventstagis either unique per signal or intentionally shared for an evolving status- The
'blocked'result is handled if browser delivery matters
Empowering traders and analysts with high-performance real-time market data directly within their spreadsheets.
Resources
Support
© 2026 TrueData Market Data Services LLP. All rights reserved.