The merge fields that help personalized SMS marketing are the ones a customer expects you to know: their first name, what they last bought from you, the name of the person texting them, and a number from their own area code. Anything that shows you know more than the relationship justifies, such as browsing history, location or life events, reads as creepy. A blank field that sends "Hi ," does more damage than no personalization at all.

This post covers which fields to use and which to drop, how blank and broken merge fields reach real phones, the segment-count cost personalization can add to a campaign, and why behavior is a better way to split a list than a name. The examples are illustrations with stated assumptions, not measured results.

Merge fields that earn replies

A text arrives on a phone between messages from friends and family. Personalization works when it makes your message read like it belongs in that thread, written by a person who knows the customer. It fails when it reads like a database printed a row.

First name

A first name is the minimum. It costs nothing, and it signals that the message was meant for this person. It only works if the data is clean. "Hi JENNIFER" from an all-caps import, or "Hi jennifer" from a lowercase web form, tells the reader the opposite: a machine filled this in. Clean the casing at import or at render time (there's code below).

Last purchase or last service

This field does the most work, because it gives the message a reason to exist. Compare these two:

  • "Hi Sam, 20% off this weekend at Northside Coffee."
  • "Hi Sam, the Ethiopia roast you ordered in March is back in stock. Want us to hold a bag?"

The second one can be answered. The customer can say yes, no or "make it two." A reply-able message is the whole point of SMS over email. Keep the reference to something the customer did with you and would remember doing: a product, a service date, an appointment type.

The rep's name

"It's Dana at Northside Plumbing" turns a broadcast into something that looks like a conversation. It also sets an expectation. If someone replies "thanks Dana," a person should see that reply. On Ready, replies land in the Inbox (and in GoHighLevel for connected accounts). Only use a rep's name if somebody actually reads the replies. A named sender who never answers is worse than an anonymous brand.

A local number

This one isn't a merge field in the copy, but it works like one. A text from your own area code looks like it came from a nearby business. Local presence sends from the account's number closest to the contact's area code. It is one switch for the whole account, so the same rule covers texts from the app, the API and GoHighLevel. In GoHighLevel, the Local presence switch is that same account switch. It has a listed price of $0.0015 for each segment of a delivered text. Every number still sits on your registered 10DLC campaign, so local presence chooses among registered numbers and does not get around registration. A local number looks familiar. We don't publish a reply-rate lift figure for it, so test it on your own list.

Fields that read creepy

The test is simple: would the customer be surprised that you know this, or that you'd say it in a text? If yes, leave it out.

FieldVerdictWhy
First name (cleaned)HelpsExpected; signals the text is meant for this person
Last product or serviceHelpsGives the message a reason and something to reply to
Rep or owner nameHelps, if someone reads repliesMakes it a conversation instead of a broadcast
Local numberHelpsLooks familiar; no change to the copy
City or neighborhoodUsually fineFine for service areas ("we're in Eastside Tuesday"); odd for ecommerce
Pages browsed or cart contentsOften backfires"We saw you looked at..." reads like surveillance
Exact order total or balanceBackfiresShows up on lock screens; private by default
Birthday or ageMixedFine if they gave it to you for that purpose; strange if inferred
Health, finance or family detailsNeverLock-screen exposure, and possibly regulated
Last name alone ("Mr. Okafor")Usually backfiresFormal in a casual channel; mismatches are common

Lock screens are the thing people forget. Your message shows up on a phone sitting face-up on a desk or in a car mount. A healthcare practice can have consent to text a patient and still breach HIPAA because of what the message body says. We covered that in the four fields never to include in a patient text. The same rule applies to everyone else, even without the legal stakes: don't put anything in a text you wouldn't want read over someone's shoulder.

Blank and broken merge fields: how "Hi ," happens

Every personalization tool has the same failure modes, and they all come from the data, not the template:

  1. Empty field. The contact came in from a form that didn't require a name. The result is "Hi , your order shipped."
  2. Unrendered token. The field name has a typo, or the tool doesn't support that field. The result is "Hi {{first_nme}}," sent to 5,000 people.
  3. Junk values. Some first-name fields hold "Test," "Owner," "Customer," "N/A," "." or the company name. The result is "Hi Owner."
  4. Wrong field mapped. A CSV column shift puts last names or email addresses where first names belong. The result is "Hi sam.k@example.com."
  5. Casing. All-caps or all-lowercase imports produce "Hi DANA."

None of these breaks the send. Each one breaks the reader's trust, and an obvious template failure gets screenshotted.

Guarding against blanks before you send

The fix has three parts. Write two versions of every template, one with the name and one without. Decide per contact which version is safe. Refuse to send anything that still contains a template token.

If you text through an app, use a fallback on each merge field. On Ready, write {{first_name|there}} and a contact with no first name gets "Hi there". If your tool doesn't offer one, split the campaign: send to "first name is not empty" with the named version, and to "first name is empty" with the plain version. Then preview a dozen real contacts before you hit send, not just the first one.

If you send from your own code, render the body yourself and check it before the API call. The bulk endpoint (POST /v1/messages/bulk) sends one body to many numbers. Per-contact copy therefore means one POST /v1/messages per contact:

const JUNK = /^(test|owner|customer|n\/a|na|unknown|none|x)$/i;

function cleanFirstName(raw) {
  const name = (raw || "").trim();
  if (name.length < 2 || name.length > 20 || JUNK.test(name) || /[@\d]/.test(name)) return null;
  // Only fix names that are ALL CAPS or all lowercase; leave "McDonald" alone
  if (name === name.toUpperCase() || name === name.toLowerCase()) {
    return name[0].toUpperCase() + name.slice(1).toLowerCase();
  }
  return name;
}

function renderBody(contact) {
  const name = cleanFirstName(contact.first_name);
  const body = name
    ? `Hi ${name}, it's Dana at Northside Plumbing. Your water heater service is due this month. Reply YES and we'll text you two times.`
    : `Hi, it's Dana at Northside Plumbing. Your water heater service is due this month. Reply YES and we'll text you two times.`;
  if (/[{}]/.test(body)) throw new Error(`Unrendered token for contact ${contact.id}`);
  return body;
}

const res = await fetch("https://api.tryready.com/v1/messages", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.READY_API_KEY,
    "Idempotency-Key": contact.sendKey, // a UUID generated once per contact per campaign, reused on retries
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ to: contact.phone, body: renderBody(contact), consent_attested: true })
});
if (!res.ok) {
  const { error, error_code } = await res.json();
  console.warn(`Not sent to ${contact.id}: ${error_code}: ${error}`);
}

Generate the Idempotency-Key once per contact per campaign and store it. A fresh UUID on every attempt defeats the point, because a retried request could then send twice. Opt-outs, numbers on your Ban list and known landlines are refused up front and not charged, so you don't need to filter those yourself. Full request details are in the messages API docs.

Personalization changes your segment count

Merge fields make each message a different length, and segments are billed. A single SMS segment holds 160 GSM-7 characters. Longer messages split into 153-character parts. One character outside GSM-7, such as an emoji, or letters like á or ł that aren't in the GSM-7 set, drops the limit to 70 characters (67 per part) for the whole message.

Worked example. Assumptions: a 5,000-contact campaign, and a template that comes to 155 characters with a typical first name. That is one segment for most people. Say 400 contacts have names with a non-GSM character, such as "María" or "Michał". Each of those 155-character messages becomes unicode and splits into 3 segments (155 ÷ 67, rounded up).

  • Without the accented names: 5,000 segments × $0.0075 = $38, plus 5,000 × $0.0045 in carrier fees.
  • With them: 4,600 + (400 × 3) = 5,800 segments × $0.0075 = $44, plus 5,800 × $0.0045.

That's 800 × $0.0075 = $6 more on the Standard rate. We'd pay it. Spelling someone's name correctly is worth two extra segments. The emoji case is the one to avoid: one 🎉 in the template turns all 5,000 messages into 3-segment unicode texts, so 15,000 × $0.0075 = $113 plus carrier fees, instead of the one-segment total above. The same thing happens when a long product name pushes a message from 158 to 163 characters. Check the length with your longest realistic values, not your shortest. On Ready, curly quotes, long dashes and ellipses are swapped for plain ones before sending, so those don't change the count. Accented letters and emoji do.

For how these costs net against revenue, see how to calculate SMS marketing ROI.

How to run personalized SMS marketing by behavior, not just name

A first name tells you nothing about what to say. Behavior does. A well-written "Hi Sam" sent to the wrong group is still the wrong message. Split your consented list by what people did:

  • Bought in the last 30 days: a thank-you, a care tip, or a "reply if anything's off" check. No promo.
  • Bought 60 to 120 days ago: a reorder or rebook prompt that names the last product or service.
  • Lapsed 6+ months: one plain "still want these texts?" message. A quiet opt-out is better than a spam complaint.
  • Replied to the last campaign: they're engaged, so a rep-signed, conversational message fits.
  • Signed up but never bought: they need the offer or the answer to their question, not a loyalty message.

Behavior segments also keep you sending fewer texts to people who don't want them. That protects deliverability as much as copy does. Carriers filter on content and complaint patterns even after your campaign is approved. Content-level filtering after approval explains why. Draft with AI and a Spam check in Ask AI can tighten the wording before it goes out. A segment that's too broad is a targeting problem, though, and no wording fixes that.

Two more points. Personalization doesn't replace consent. Every one of these segments should be people who opted in to your texts, and cold contacts belong on phone or mail. Ready also holds sends outside permitted local hours based on the recipient's area, so a campaign launched at 9 AM Eastern doesn't reach the West Coast at 6 AM. Behavior-timed sends still go through that check. Campaigns, drip campaigns and automations wait up to 24 hours for the window; a one-to-one or API text is held only if the window opens within 6 hours, otherwise it is refused and must be resent; a one-to-one reply to someone who texted you in the last 24 hours goes out at any hour.

The practical takeaway

Use the four fields people expect: first name, last purchase, rep name and a local number. Drop anything that would surprise the reader or embarrass them on a lock screen. Write a no-name version of every template, check for unrendered tokens before sending, and test message length with your longest real values. Split your list by what people did rather than who they are. Make sure every opt-out is honored; our opt-out guide covers the rules.

If you want to try this on Ready, sign up at tryready.com/signup. Your first 20 texts are free one-to-one sends, so use them to test your templates on your own phone before registering. The per-segment card is on the pricing page.

Frequently asked questions

Does using a first name in SMS marketing increase replies? It usually helps a little, but only when the name is clean and the message gives the person a reason to reply. A name on an irrelevant promo doesn't rescue it. Referencing what they last bought typically does more than the name alone.

What happens if a merge field is blank in a text message? The text goes out with a gap or a raw token, like "Hi ," or "Hi {{first_name}}." Most tools won't stop the send for you. Use a fallback value, split the campaign by whether the field is filled, or check the rendered body in code before sending.

What personalization is too creepy for SMS? Anything the customer didn't knowingly give you for this purpose, such as pages they browsed, their location or inferred life events. Also leave out anything private that would show on a lock screen, like balances or health details. If they'd be surprised you know it, don't text it.

Do merge fields make SMS more expensive? They can, because segments are billed and longer or unicode messages use more segments. A name with an accented letter like á, or an emoji anywhere in the template, switches the message to a 70-character limit. Test your template with your longest real values to see the true count.

Should I segment my SMS list by name or by behavior? Behavior. Purchase recency, replies and sign-up source tell you what to say, while a name only changes the greeting. Use the name inside behavior-based segments, not instead of them.