Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The NetSuite Pro

The NetSuite Pro Logo The NetSuite Pro Logo

The NetSuite Pro Navigation

  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • NetSuite Customization
    • NetSuite Integration
    • NetSuite Advanced PDF Templates
    • NetSuite Reporting & Analytics Guide
    • Real-World NetSuite Examples
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask A Question
  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • NetSuite Customization
    • NetSuite Integration
    • NetSuite Advanced PDF Templates
    • NetSuite Reporting & Analytics Guide
    • Real-World NetSuite Examples
  • Blog
  • Contact Us
Home/ NetSuite + Slack Integration: The Complete Step-by-Step Guide/Step 4: Build Rich, Readable Slack Messages from NetSuite (Block Kit)

Step 4: Build Rich, Readable Slack Messages from NetSuite (Block Kit)

Part 6 of 13 in the NetSuite + Slack series
Time: 20 minutes  |  Level: Some SuiteScript helps
You will learn: How to turn plain text alerts into tidy messages with a reusable helper file.
You will need: The working alert from Step 2.

Plain text alerts work, but they get dull fast. Slack’s Block Kit lets you lay out messages with a header, tidy columns of facts and buttons, so people can understand an alert at a glance.

Good news: Block Kit is just JSON. If you can build an object in JavaScript, you can build a Block Kit message.

The building blocks you will use most

Block What it looks like When to use it
header Large bold title The first line of the alert
section with text A paragraph A sentence of context
section with fields Two neat columns Order number, customer, total, date
divider A thin line Separating sections
context Small grey text “Sent by NetSuite at 10:42”
actions Buttons Open in NetSuite, Approve, Reject

You can design and preview messages visually in Slack’s Block Kit Builder (search for it on api.slack.com), then copy the JSON across. That is the easiest way to get a layout you like.

A finished example

Here is what a “big order” alert looks like as Block Kit JSON:

{
  "text": "Big order received: SO-10482",
  "blocks": [
    {
      "type": "header",
      "text": { "type": "plain_text", "text": "Big order received" }
    },
    {
      "type": "section",
      "fields": [
        { "type": "mrkdwn", "text": "*Order*\nSO-10482" },
        { "type": "mrkdwn", "text": "*Customer*\nAcme Kitchens" },
        { "type": "mrkdwn", "text": "*Total*\n$14,200.00" },
        { "type": "mrkdwn", "text": "*Ship date*\nFriday, Oct 2" }
      ]
    },
    {
      "type": "actions",
      "elements": [
        {
          "type": "button",
          "text": { "type": "plain_text", "text": "Open in NetSuite" },
          "url": "https://1234567.app.netsuite.com/app/accounting/transactions/salesord.nl?id=5521"
        }
      ]
    },
    {
      "type": "context",
      "elements": [ { "type": "mrkdwn", "text": "Sent by NetSuite" } ]
    }
  ]
}

Notice the top-level text. Slack shows it in notifications and on devices that cannot render blocks, so always include a short, meaningful one.

Step-by-step: turn it into a reusable helper

Rather than pasting JSON into every script, create one small helper library that every alert can share. That keeps messages consistent and means you fix a problem in one place.

1. Create a library file

Create slack_lib.js in the File Cabinet:

/**
 * @NApiVersion 2.1
 * @NModuleScope SameAccount
 *
 * Small helper for building and sending Slack messages.
 */
define(['N/https', 'N/log'], (https, log) => {

  // Turn a list of [label, value] pairs into Block Kit "fields".
  const toFields = (pairs) =>
    pairs.map(([label, value]) => ({
      type: 'mrkdwn',
      text: '*' + label + '*\n' + (value === null || value === undefined || value === '' ? '-' : value)
    }));

  // Build a standard alert: header, fields, and an optional link button.
  const buildAlert = ({ title, summary, facts, linkUrl, linkLabel }) => {
    const blocks = [
      { type: 'header', text: { type: 'plain_text', text: title.substring(0, 150) } }
    ];

    if (facts && facts.length) {
      // Slack allows up to 10 fields per section.
      blocks.push({ type: 'section', fields: toFields(facts.slice(0, 10)) });
    }

    if (linkUrl) {
      blocks.push({
        type: 'actions',
        elements: [{
          type: 'button',
          text: { type: 'plain_text', text: linkLabel || 'Open in NetSuite' },
          url: linkUrl
        }]
      });
    }

    return { text: summary || title, blocks };
  };

  // Send a payload to an incoming webhook. Returns true if Slack accepted it.
  const postToWebhook = (webhookUrl, payload) => {
    const response = https.post({
      url: webhookUrl,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });

    if (response.code !== 200) {
      log.error('Slack webhook failed', response.code + ' ' + response.body);
      return false;
    }
    return true;
  };

  return { buildAlert, postToWebhook };
});

2. Use it from your User Event script

Change your define line to load the library using its File Cabinet path, or better, a path relative to your script:

define(['N/runtime', 'N/url', 'N/log', './slack_lib'],
  (runtime, url, log, slack) => {

    const afterSubmit = (context) => {
      try {
        if (context.type !== context.UserEventType.CREATE) return;

        const script     = runtime.getCurrentScript();
        const webhookUrl = script.getParameter({ name: 'custscript_slack_webhook_url' });
        const order      = context.newRecord;
        const total      = Number(order.getValue({ fieldId: 'total' })) || 0;
        if (total < 10000) return;

        const domain = url.resolveDomain({ hostType: url.HostType.APPLICATION });
        const path   = url.resolveRecord({ recordType: 'salesorder', recordId: order.id });

        const payload = slack.buildAlert({
          title:    'Big order received',
          summary:  'Big order received: ' + order.getValue({ fieldId: 'tranid' }),
          facts: [
            ['Order',     order.getValue({ fieldId: 'tranid' })],
            ['Customer',  order.getText({ fieldId: 'entity' })],
            ['Total',     '$' + total.toFixed(2)],
            ['Ship date', order.getText({ fieldId: 'shipdate' })]
          ],
          linkUrl: 'https://' + domain + path
        });

        slack.postToWebhook(webhookUrl, payload);
      } catch (e) {
        log.error('Slack alert failed', e.name + ': ' + e.message);
      }
    };

    return { afterSubmit };
  });

Two reminders. Keep the @NApiVersion and @NScriptType header comment at the top of the User Event script. And upload both files into the same folder, so the relative path ./slack_lib can find the library.

Tips for messages people actually like

  • Lead with what happened. “Big order received” beats “Notification”.
  • Put the most useful facts first. People skim the first two or three fields.
  • Always include a link back to NetSuite. It is the one thing people reliably want.
  • Use emoji sparingly. One consistent emoji per alert type helps people scan; a whole row of them looks like a party invitation.
  • Keep it short. If a message needs scrolling, it is really a report, not an alert.
  • Mention people carefully. In Slack, <@U12345678> pings a specific person and <!here> pings everyone online. Use them only where a reply is genuinely needed.

Escaping special characters

Slack treats &, < and > as special in mrkdwn text. If a customer name could contain them (for example “Smith & Sons”), replace them with &amp;, &lt; and &gt; before sending. A tiny helper does it:

const esc = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');

What is next

You can now send handsome alerts. Let us make them interactive: approve NetSuite records straight from Slack.


← Step 3: Keep Your Slack Secrets Safe in NetSuite
Series overview
Approve Purchase Orders and Other NetSuite Records Right From Slack →
Share
  • Facebook

Sidebar

Ask A Question

Stats

  • Questions 6
  • Answers 6
  • Best Answers 0
  • Users 9
  • Popular
  • Answers
  • Rocky

    Issue in running a client script in NetSuite SuiteScript 2.0 ...

    • 1 Answer
  • admin

    How can I send an email with an attachment in ...

    • 1 Answer
  • admin

    How do I avoid SSS_USAGE_LIMIT_EXCEEDED in a Map/Reduce script?

    • 1 Answer
  • admin
    admin added an answer The issue is usually caused by following Wrong script file… September 14, 2025 at 10:33 pm
  • admin
    admin added an answer Steps to send an Invoice PDF by email: define(['N/email', 'N/render',… August 28, 2025 at 3:05 am
  • admin
    admin added an answer This error means your script hit NetSuite’s governance usage limit… August 28, 2025 at 3:02 am

Top Members

Rocky

Rocky

  • 1 Question
  • 22 Points
Begginer
74gold

74gold

  • 0 Questions
  • 20 Points
Begginer
Sophie1022

Sophie1022

  • 0 Questions
  • 20 Points
Begginer

Trending Tags

clientscript netsuite scripting suitescript
  • The SuiteScript 1.0 scripts nobody remembers: Portlets, Mass Updates and Workflow ActionsSeptember 10, 2026
  • You’re on SuiteScript 2.0, not 1.0. Here’s what that actually buys you.September 9, 2026
  • Converting a SuiteScript 1.0 Suitelet to 2.1 (and the ones that were never really forms)September 8, 2026
  • Every NetSuite certification in 2026, and the rules that quietly changedSeptember 7, 2026
  • Converting a SuiteScript 1.0 Scheduled Script to a 2.1 Map/Reduce (and why a straight port is a mistake)September 7, 2026
  • Migrating a SuiteScript 1.0 RESTlet to SS2.1 + OAuth 2.0 before the 2027.1 deadlineAugust 15, 2026
  • How to convert a SuiteScript 1.0 User Event script to SuiteScript 2.1 (with real code)August 14, 2026
  • The complete SuiteScript 1.0 to 2.1 API cheat sheet: nlapiXxx β†’ N/moduleAugust 13, 2026
  • NetSuite Error Messages: Causes and FixesAugust 11, 2026
  • How to audit every SuiteScript 1.0 script in your NetSuite account (step by step)August 11, 2026

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Menu

  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • NetSuite Customization
    • NetSuite Integration
    • NetSuite Advanced PDF Templates
    • NetSuite Reporting & Analytics Guide
    • Real-World NetSuite Examples
  • Blog
  • Contact Us

Quick Links

  • NetSuite Scripting
  • NetSuite Customization
  • NetSuite Advanced PDF Template
  • NetSuite Integration
  • NetSuite Reporting & Analytics

Subscribe for NetSuite Insights....

Β© 2026 The NetSuite Pro. All Rights Reserved