Skip to main content

Encoding + Hashing functions — Marketing Cloud AMPscript reference

URLEncode, Base64Encode/Decode, HTMLEncode, the RedirectTo tracking wrapper, plus SHA1/SHA256/SHA512/MD5 hashes and symmetric encryption. Each function pairs with a production failure shape — wrong URL escaping breaks tracking links, missing HTMLEncode opens XSS in CloudPages, MD5 used as security instead of as a tracking key.

Reference·Last updated 2026-05-19·Drafted by Lira · Edited by German Medina

The encoding and hashing surface is small but heavily-loaded: every tracking link, every signed payload, every CloudPage form rendering user input touches one of these functions. The failure shapes are mostly invisible — a URLEncode that didn't escape + produces a tracking link that silently breaks for some recipients, an HTMLEncode that wasn't applied makes a CloudPage vulnerable to XSS, an MD5 used as a security hash gives a false sense of integrity. None of them throw; all of them ship.

This page is the inventory plus the patterns the next person reading the code needs to know before changing anything.

Official syntax

Encoding

%%[
  /* URLEncode — percent-encode for URLs */
  SET @encoded = URLEncode(@rawValue)
  SET @encodedForm = URLEncode(@rawValue, 1)     /* 2nd arg = 1 → form-style (space → +) */
  SET @encodedUtf8 = URLEncode(@rawValue, 1, 1)  /* 3rd arg = 1 → UTF-8 mode */

  /* Base64 — encoding */
  SET @b64 = Base64Encode(@rawValue)
  SET @b64Url = Base64Encode(@rawValue, 1)       /* URL-safe variant: - and _ instead of + and / */
  SET @b64Utf8 = Base64Encode(@rawValue, 1, 1)   /* URL-safe + UTF-8 */

  SET @decoded = Base64Decode(@b64)
  SET @decodedUrl = Base64Decode(@b64Url, 1)     /* must match the encode flag */

  /* HTML entity encoding — critical for CloudPage user-input rendering */
  SET @safe = HTMLEncode(@userInput)
  /* "<script>" → "&lt;script&gt;" */
]%%

<!-- Render user input inside HTML — always HTMLEncode -->
<p>You searched for: %%=v(@safe)=%%</p>

Tracking wrappers

%%[
  /* RedirectTo — wraps a URL through MC's redirect + tracking layer.
     The returned URL records a click event when followed. */
  SET @trackedUrl = RedirectTo(@finalUrl)
]%%

<a href="%%=v(@trackedUrl)=%%">Click here</a>
<!-- BeginImpressionRegion + EndImpressionRegion — tracks impressions
     of a block of content (CloudPages only; not used in email body). -->
%%[ BeginImpressionRegion("hero-promo") ]%%
<div>...hero content...</div>
%%[ EndImpressionRegion() ]%%
%%[
  /* TreatAsContent — re-parses a string as AMPscript. Used when AMPscript
     is stored in a DE column (admin-editable templates) and rendered later.
     Dangerous: never pass user input to TreatAsContent — template injection. */
  SET @templateBody = Lookup("de_email_templates", "Body", "TemplateId", @templateId)
  SET @rendered = TreatAsContent(@templateBody)
]%%

Hashing

%%[
  /* Standard hash functions — output is hex string */
  SET @sha1   = SHA1(@payload)        /* 40-char hex */
  SET @sha256 = SHA256(@payload)      /* 64-char hex */
  SET @sha512 = SHA512(@payload)      /* 128-char hex */
  SET @md5    = MD5(@payload)         /* 32-char hex — NOT for security */

  /* HMAC — keyed hashes for tamper resistance.
     Availability varies by tenant; verify on your tenant before relying. */
  SET @hmacSha256 = HMACSHA256(@payload, @secretKey)
]%%

Symmetric encryption

%%[
  /* EncryptSymmetric — uses .NET symmetric algorithm with a named key
     stored at the tenant level (Setup → Key Management). The keyName arg
     references the tenant key, not the key value itself — safer than
     inline key material. */
  SET @cipher = EncryptSymmetric(@plaintext, "AES", "myKeyName", @null, @null, @null, @null)
  SET @plain  = DecryptSymmetric(@cipher,    "AES", "myKeyName", @null, @null, @null, @null)
]%%

The supported set:

| Function | Purpose | Notes | |---|---|---| | URLEncode(s [, formStyle [, asUtf8]]) | Percent-encode for URLs | 2nd arg = form-style (space → +); 3rd arg = UTF-8 mode | | Base64Encode(s [, urlSafe [, asUtf8]]) | Base64 encode | URL-safe variant uses - and _ | | Base64Decode(s [, urlSafe [, asUtf8]]) | Base64 decode | Must match the encode flag | | HTMLEncode(s) | Escape HTML entities | The XSS defense for CloudPage user input | | RedirectTo(url) | Wrap URL through MC's click-tracking redirect | Returns a tracked URL | | BeginImpressionRegion(name) / EndImpressionRegion() | Track impressions of a content block | CloudPages only | | TreatAsContent(s) | Re-parse a string as AMPscript | Template injection risk if s is user input | | SHA1(s) / SHA256(s) / SHA512(s) | Cryptographic hash | Hex string output | | MD5(s) | Legacy hash | Not for security; common for tracking keys | | HMACSHA256(s, key) (and SHA1/SHA512 variants) | Keyed hash for tamper resistance | Tenant-dependent availability | | EncryptSymmetric(value, algo, keyName, ...) | Symmetric encryption with tenant-managed key | Algo: AES; keyName references Setup → Key Management | | DecryptSymmetric(value, algo, keyName, ...) | Symmetric decryption | Must match the encrypt args exactly |

Reference:

What survives in production

URLEncode default vs form-style — pick the one your destination expects

The 2nd argument switches between two URL-encoding conventions:

  • Default (no 2nd arg or 0): percent-encodes spaces as %20. Standard RFC 3986 URL component encoding.
  • Form-style (1): encodes spaces as +. Standard application/x-www-form-urlencoded.
%%[
  SET @s = "hello world"

  SET @rfc   = URLEncode(@s)         /* → "hello%20world" */
  SET @form  = URLEncode(@s, 1)      /* → "hello+world"   */
]%%

The two are interchangeable for most browser-decoded contexts, but some downstream systems (especially older APIs and tracking endpoints) only accept one. The hand-off failure: an existing CloudPage uses form-style encoding; a new dev clones the link logic to a new context without checking; the new context's downstream rejects + characters as literal pluses; emails go out with broken links.

The Cleon convention: use default (RFC 3986) unless the destination explicitly requires form-style. Comment the choice when form-style is needed.

Base64Encode URL-safe vs standard — + and / break query strings

Standard Base64 uses the alphabet [A-Z][a-z][0-9]+/. The + and / characters have special meaning in URLs (+ = space in form encoding, / = path separator). A standard Base64 value embedded directly in a query string transports incorrectly unless the encoder is set to URL-safe.

%%[
  SET @raw = "subscriberKey=abc123|action=optout"

  /* AT RISK — contains + or / that breaks in a URL */
  SET @std = Base64Encode(@raw)
  /* "c3Vic2NyaWJlcktleT1hYmMxMjN8YWN0aW9uPW9wdG91dA==" — might be fine here */

  /* DURABLE — URL-safe variant uses - and _ instead of + and / */
  SET @urlSafe = Base64Encode(@raw, 1)

  /* The decode side must match the encode side */
  SET @backToRaw = Base64Decode(@urlSafe, 1)
]%%

The hand-off failure: encode side uses URL-safe, decode side uses default. The + and / characters that should have been - and _ are interpreted as the wrong characters, base64 decoding fails silently, payload becomes garbage. The Cleon convention: when you ship Base64Encode, ship the matching Base64Decode in the same change, with the same flag value, and a comment linking them.

HTMLEncode is the XSS defense for CloudPage user input

Any time a CloudPage renders text that originated outside Marketing Cloud — a form field, a URL parameter, a Lookup result that came from an inbound webhook — pass it through HTMLEncode before output. Without that, a payload containing <script> tags executes in the recipient's browser.

%%[
  SET @search = RequestParameter("q")

  /* DANGEROUS — renders raw input; "<script>alert(1)</script>" executes */
]%%
<p>You searched for: %%=v(@search)=%%</p>

<!-- vs -->

%%[
  SET @search = RequestParameter("q")
  SET @safe = HTMLEncode(@search)

  /* DURABLE — entities are escaped; "<script>" renders as text */
]%%
<p>You searched for: %%=v(@safe)=%%</p>

The Cleon rule: anything that comes from outside the audience-build SQL Activity is "user input". URL parameters, form submissions, webhook payloads, even DE columns populated by a CloudPage user — all of them get HTMLEncode before rendering to HTML. The defense is wrapping at the render layer, not trusting upstream sanitation.

For attribute contexts (<a href="...">, <input value="...">), HTMLEncode is not enough on its own — escape the quote characters explicitly and use URLEncode for href values that include any user-controlled segment.

RedirectTo is the underused tracking wrapper

RedirectTo wraps a URL through MC's redirect + click-tracking layer. The returned URL records a click event when followed; without it, the link is invisible to MC's reporting.

%%[
  /* The link works without RedirectTo, but no click event fires */
  SET @plain = @ctaUrl

  /* DURABLE — click is tracked, reportable in Email Studio */
  SET @tracked = RedirectTo(@ctaUrl)
]%%

<a href="%%=v(@tracked)=%%">Click here</a>

The default behavior of the Email Studio link wrapper handles most static <a> tags automatically. RedirectTo is for dynamically-constructed URLs built from AMPscript variables — those bypass the automatic wrapping and need explicit tracking. The hand-off failure: a CTA was hard-coded last quarter (auto-tracked), gets refactored into an AMPscript-built URL for a personalization variant, click metrics drop to zero, and nobody connects the drop to the refactor for weeks.

TreatAsContent is a template injection risk — never on user input

TreatAsContent re-parses a string as AMPscript. Useful for storing AMPscript-templated content in a DE column (admin-editable templates, dynamic email blocks) and rendering at send time. Catastrophic if the source string comes from user input.

%%[
  /* SAFE — admin-curated template stored in a DE only writeable by trusted users */
  SET @body = Lookup("de_email_templates", "Body", "TemplateId", @templateId)
  SET @rendered = TreatAsContent(@body)

  /* DANGEROUS — user-controlled content passed to TreatAsContent
     allows the user to inject AMPscript that runs at render time,
     reads other recipients' data, makes Cloud-write calls, etc. */
  SET @userTemplate = RequestParameter("template")
  SET @rendered = TreatAsContent(@userTemplate)   /* NEVER */
]%%

The Cleon rule: TreatAsContent is whitelist-only. Document every call site with a comment naming the trusted source. Code review rejects any new TreatAsContent call that doesn't trace back to a DE only writeable by trusted users (admin UI, SQL Activity, internal automation).

MD5 is for tracking keys, not security

MD5 is cryptographically broken and unsuitable for any integrity or authentication use. It still has one legitimate AMPscript use: generating short, stable, deterministic identifiers for tracking pixels and analytics keys.

%%[
  /* LEGITIMATE — MD5 of subscriber + send produces a stable, short
     identifier for cross-system tracking. No security claim. */
  SET @trackingKey = MD5(Concat(_subscriberKey, "-", _jobid))

  /* NEVER — MD5 cannot prove the payload is untampered */
  SET @signature = MD5(Concat(@payload, @secret))   /* not a security signature */
]%%

For tamper-resistance, use HMACSHA256(payload, key) if your tenant supports it. The HMAC family takes a key argument and produces a hash that's verifiable only by someone holding the key. The hand-off failure: a previous dev used MD5(payload + secret) as a "signature"; a new dev assumes the existing pattern is sound and ships more code on top of it. The whole tower of code is signing nothing.

Hash outputs are hex strings — fixed length per algorithm

%%[
  SET @s = "hello"
  SET @sha256 = SHA256(@s)
  /* Always 64 characters of hex: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 */

  /* Useful for fixed-width DE columns: SHA256 fits in NVARCHAR(64). */
  /* Useful for query-string transport: hex is URL-safe by default. */
]%%

Hash output is hex by default, not raw bytes — no Base64 needed for transport. The fixed-width property is useful for DE schema design: a column meant to hold a SHA256 can be NVARCHAR(64), no nulls.

EncryptSymmetric / DecryptSymmetric — key management is the hard part

The encryption functions reference a tenant-managed key stored in Setup → Key Management, not an inline key string. The keyName arg looks up the key by configured name; the actual key material never appears in your AMPscript.

%%[
  /* The "myKeyName" is the key's configured name in Setup, NOT the key value.
     This avoids inline key material in DE columns or in code reviews. */
  SET @cipher = EncryptSymmetric(@pii, "AES", "myKeyName",
                                 @null, @null, @null, @null)

  /* Decrypt args must match exactly */
  SET @plain = DecryptSymmetric(@cipher, "AES", "myKeyName",
                                @null, @null, @null, @null)
]%%

The hand-off failure: the key is rotated in Setup → Key Management; existing ciphertext in DEs becomes undecryptable. AMPscript doesn't carry version metadata on encrypted values — you have to track key version in a separate DE column to support rotation.

The Cleon rule: if you reach for EncryptSymmetric, you've likely already crossed into territory where AMPscript is the wrong tool. Encrypt outside MC, store the ciphertext + key version in the DE, render it through AMPscript only if needed. Don't make the email body a cryptographic primitive.

Quick decision

Use URLEncode (default) when:

  • Building a URL path or query string component. Use form-style (1) only when the destination requires it.

Use Base64Encode(s, 1) URL-safe variant when:

  • The encoded value goes into a query string. Match the decode flag on the receiving side.

Use HTMLEncode when:

  • Rendering any text that originated outside the audience-build SQL Activity. Treat URL parameters, form input, webhook payloads, and CloudPage-form-written DE columns as untrusted.

Use RedirectTo when:

  • The link URL is dynamically built from AMPscript and needs click tracking. Static <a> tags in email bodies are auto-tracked.

Use TreatAsContent only when:

  • The source is a DE column writeable only by trusted users. Whitelist-only. Comment the trusted source on every call.

Use SHA256 (or SHA512) when:

  • You need a deterministic fingerprint of a payload for non-security purposes (cache keys, deduplication, idempotency tokens).

Use HMACSHA256(payload, key) when:

  • You need a tamper-resistant signature. Confirm tenant support before relying.

Use MD5 only when:

  • Generating short, stable, non-security identifiers. Never as a signature.

Move encryption outside MC when:

  • Anything more than the simplest "obfuscate a value in transit" use case. AMPscript symmetric encryption lacks the key-rotation tooling production crypto needs.

Related

Catalog progress: with this page, AMPscript reference is complete (8 reference pages + gotchas). Remaining: Style Guide (decision-framework) + 3 how-to debugging snippets. After AMPscript closes, Config subcategory opens.