TUTORIAL · PINE SCRIPT · JULY 2026

Pine Script alert() for webhooks, done right.

TradingView gives you three different ways to fire an alert from code — and picking the wrong one is why so many webhook setups fire on-screen popups but never move an order. This guide sorts out alertcondition() vs alert() vs alert_message, shows copy-paste payloads for each, and lists the four pitfalls that silently break automation.

The three alert mechanisms, in one minute

  • alertcondition() — indicators only. The message is written in the alert dialog when you create the alert; the script cannot change it later. Fine for static payloads.
  • alert() — indicators and strategies. The message is built in code at runtime, so it can contain live values (price, ticker, computed lot). Create the alert with the condition Any alert() function call.
  • alert_message — strategies only. You attach a message to each strategy.entry() / strategy.exit() and reference it in the dialog with the placeholder {{strategy.order.alert_message}}. One alert covers every order your strategy places.

alert(): dynamic JSON from an indicator or strategy

This is the most flexible route. Build the exact JSON your bridge expects — the payload below is SignalForge's documented format (full reference), but the technique is identical for any webhook receiver:

//@version=6
indicator("Webhook alerts demo", overlay = true)

crossUp = ta.crossover(ta.ema(close, 9), ta.ema(close, 21))

if crossUp
    alert('{"action":"buy","symbol":"' + syminfo.ticker + '","lot":0.01,"sl":50,"tp":100}',
          alert.freq_once_per_bar_close)

Two details do the heavy lifting. syminfo.ticker makes the same script work on every chart without editing the message. And alert.freq_once_per_bar_close fires only on confirmed bars — the single most important flag in this whole guide (see pitfalls).

alert_message: one alert for a whole strategy

//@version=6
strategy("Strategy webhook demo", overlay = true)

longCond = ta.crossover(ta.ema(close, 9), ta.ema(close, 21))

if longCond
    strategy.entry("L", strategy.long,
         alert_message = '{"action":"buy","symbol":"' + syminfo.ticker + '","lot":0.01}')

strategy.exit("XL", "L", loss = 500, profit = 1000,
     alert_message = '{"action":"close","symbol":"' + syminfo.ticker + '"}')

Then create ONE alert on the strategy, choose Order fills events, and put exactly this in the message box:

{{strategy.order.alert_message}}

Every fill now sends its own attached payload. If you prefer to build the message in the dialog instead, the generic placeholders work too: {{ticker}}, {{close}}, {{strategy.order.action}}, {{strategy.order.contracts}}.

The four pitfalls that silently kill webhook automation

1. Firing intrabar (repaint bait)

With alert.freq_once_per_bar or realtime conditions, your alert can fire on a signal that disappears when the bar closes — the backtest looks nothing like live fills. Use alert.freq_once_per_bar_close unless you have a specific reason not to.

2. Broken JSON from string concatenation

One missing quote around a concatenated value — "lot":' + str.tostring(lot) + ' vs "lot":"' + ... + '" — and the receiver drops the message. Numbers go unquoted, strings quoted, and an na value turns your payload into garbage mid-string. Paste the exact output into our free webhook tester and see what a bridge would actually parse before going live.

3. The alert dialog is not wired

The webhook URL lives in the alert's Notifications tab and must be re-saved every time you edit the alert. And an alert() call only reaches the outside world if the alert was created with Any alert() function call — a popup on screen proves nothing about the webhook.

4. Free TradingView plan

Webhook notifications need a paid plan (Essential and up). If the checkbox is greyed out, that is the answer — more silent failure modes in our 12-fix troubleshooting guide.

Do not want to write Pine at all? The AI Script Builder turns a plain-English description into a complete, validated Pine Script v6 strategy with the webhook payload already wired for MT5 — 100 strategies/month on the $4.99 Starter plan. Describe, paste, automate.

FAQ

What is the difference between alert() and alertcondition()?

alertcondition() registers a condition whose message is fixed in the alert dialog; alert() sends a message built at runtime in code. For dynamic webhook payloads (live prices, tickers, computed sizes) you want alert() or alert_message.

Can one alert cover all my strategy's orders?

Yes: attach alert_message to each entry/exit and create a single alert on Order fills events with {{strategy.order.alert_message}} as the message.

What payload format does the bridge need?

SignalForge parses JSON ({"action":"buy","symbol":"EURUSD","lot":0.01}), key=value and PineConnector-style comma messages. Fifteen ready payloads by use case are in the JSON payload library.

Author: Benjamin SF is the founder of SignalForge and an expert in trading algorithm automation. He builds and operates the SignalForge bridge for prop-firm traders and maintains its public latency benchmark (187 ms median).

Automate your TradingView signals on MT5

SignalForge routes your alerts to MetaTrader 5 in milliseconds. 14-day free trial, no card required.

SignalForge AI is an order-execution tool. We do not provide investment advice. Trading involves risk of loss.