TrueData TrueData Sheets
search
Searching...
functions Formulas
menu_book Pages
manage_search Content Match
search_off

No results for ""

Loading Content
notifications_active

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.

info Both methods are async. Always 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:

view_agenda 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).

desktop_windows 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.
warning Browser notifications need the site's notification permission set to Allow. When it is not, 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'
info Setting 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.

1

Pacing window

One OS popup every 2 seconds per script.

2

Queue & digest

Extra notifications in that window are queued (up to 100) and merged into one summary popup.

3

Single item kept

If only one item was queued, its original title and body are shown, not a generic summary.

Example digest popup
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

check_circle

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.

check_circle

Handle 'blocked'

Check the return value at least once in onStart and tell the user how to allow notifications.

check_circle

Prefer bar events for alerts

Evaluate conditions in bar1min / bar5min where possible. Use tick only for time-critical levels.

check_circle

Put the symbol name in the title

Digest popups list titles, so "RELIANCE - Breakout" reads better than "Breakout". Resolve names with symbolMap.

cancel

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.

cancel

Marking routine alerts urgent

Reserve urgent: true for critical events only.

cancel

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.

cancel

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

  • check_boxtitle is a non-empty string
  • check_boxThe call is awaited and wrapped in try/catch
  • check_boxValues from tick/bar events are parsed with parseFloat() before comparing
  • check_boxA flag or timestamp guard stops the same condition from notifying repeatedly
  • check_boxurgent is used only for critical events
  • check_boxtag is either unique per signal or intentionally shared for an evolving status
  • check_boxThe 'blocked' result is handled if browser delivery matters
Truedata Icon Sheets by Truedata

Empowering traders and analysts with high-performance real-time market data directly within their spreadsheets.

© 2026 TrueData Market Data Services LLP. All rights reserved.