WrapLongURL
Shortens a long URL for email clients that truncate long hyperlinks. Runtime-proven on a live Marketing Cloud Engagement CloudPage — outside a send the argument comes back byte for byte unchanged, whatever its length.
Syntax
WrapLongURL(url) → string
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
url |
string | number | Yes | URL to shorten |
Example
%%[
VAR @link
SET @link = WrapLongURL(@veryLongTrackingUrl)
]%%
<a href="%%=v(@link)=%%">Read more</a>
In an email send this yields a short platform link that forwards to the original address. On a CloudPage it does not: a URL built to 1048 characters came back at exactly 1048 characters, character for character the input. Test the shortening in a send, not on a page.
Return value
string — the shortened URL when the call happens during a send; in any other context the supplied value unchanged.
The value domain is open, so there is no set of sentinel values to test for. Outside a send the return value is simply the argument, so a caller cannot tell from the result alone whether shortening happened.
Behaviour
Outside a send nothing is shortened. A URL assembled to 1048 characters — well past the documented 975-character threshold — was returned at the same length and compared equal to the input in the same render. This is the point worth remembering: a CloudPage will never show you the shortened form, so a page render is not a valid test of the feature.
Determinism follows from that. Two calls with the same input in one render returned identical strings. That is a property of the pass-through, not evidence of a stable shortening token.
A URL already below the threshold comes back unchanged — a 27-character URL rendered at length 27. This is the one part of the documented behaviour a page can confirm.
Nothing is validated. An empty string answers empty at length zero, a word that is not a URL at all comes back unchanged, and a bare number comes back as its decimal digits. None of these aborts, so a malformed value passes straight through into your markup.
Exactly one argument. A zero-argument call and a two-argument call each abort the request with HTTP 422.
Show test script
%%[
VAR @b, @s, @long, @short, @u1, @u2
SET @b = RequestParameter("b")
/* known-good control: renders on every request, so a run of HTTP 422s
can be told apart from a broken deploy */
OutputLine(Concat("CTRL=[", Uppercase("ok"), "]"))
OutputLine(Concat("GATE=[", @b, "]"))
/* a URL well past the documented 975-character threshold, built here so
the length is printed rather than assumed; called twice in one render */
IF @b == "wlu" THEN
OutputLine(Concat("--- wlu start ---"))
SET @s = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"
SET @s = Concat(@s, @s)
SET @s = Concat(@s, @s)
SET @s = Concat(@s, @s)
SET @s = Concat(@s, @s)
SET @long = Concat("https://example.com/p?q=", @s)
OutputLine(Concat("WLU_IN_LEN=[", Length(@long), "]"))
SET @u1 = WrapLongURL(@long)
SET @u2 = WrapLongURL(@long)
OutputLine(Concat("WLU_OUT_LEN=[", Length(@u1), "]"))
OutputLine(Concat("WLU_SAME=[", IIf(@u1 == @u2, "identical", "different"), "]"))
OutputLine(Concat("WLU_UNCHANGED=[", IIf(@u1 == @long, "unchanged", "changed"), "]"))
OutputLine(Concat("--- wlu done ---"))
ENDIF
/* a URL already below the threshold */
IF @b == "wlushort" THEN
OutputLine(Concat("--- wlushort start ---"))
SET @short = "https://example.com/a/b?x=1"
SET @u1 = WrapLongURL(@short)
OutputLine(Concat("WLU_SHORT_OUT=[", @u1, "] LEN=[", Length(@u1), "]"))
OutputLine(Concat("WLU_SHORT_UNCHANGED=[", IIf(@u1 == @short, "unchanged", "changed"), "]"))
OutputLine(Concat("--- wlushort done ---"))
ENDIF
/* values that are not URLs at all: none of them is rejected */
IF @b == "wluempty" THEN
OutputLine(Concat("--- wluempty start ---"))
SET @u1 = WrapLongURL("")
OutputLine(Concat("WLU_EMPTY=[", @u1, "] LEN=[", Length(@u1), "]"))
OutputLine(Concat("--- wluempty done ---"))
ENDIF
IF @b == "wlunonurl" THEN
OutputLine(Concat("--- wlunonurl start ---"))
SET @u1 = WrapLongURL("not-a-url-at-all")
OutputLine(Concat("WLU_NONURL=[", @u1, "] LEN=[", Length(@u1), "]"))
OutputLine(Concat("--- wlunonurl done ---"))
ENDIF
IF @b == "wlunum" THEN
OutputLine(Concat("--- wlunum start ---"))
SET @u1 = WrapLongURL(12345)
OutputLine(Concat("WLU_NUM=[", @u1, "] LEN=[", Length(@u1), "]"))
OutputLine(Concat("--- wlunum done ---"))
ENDIF
/* argument counts the signature does not allow: each aborts its own
branch with HTTP 422 while every branch above still renders */
IF @b == "wlu0" THEN
OutputLine(Concat("WLU0_START=[x]"))
OutputLine(Concat("WLU0=[", WrapLongURL(), "]"))
ENDIF
IF @b == "wlu2" THEN
OutputLine(Concat("WLU2_START=[x]"))
OutputLine(Concat("WLU2=[", WrapLongURL("https://example.com/a", "https://example.com/b"), "]"))
ENDIF
]%%
Differs from official docs
The official reference states the shortening unconditionally: a URL longer than 975 characters comes back as a short link that redirects to the original. That did not happen in any page render. The community guide supplies the missing condition — shortening is applied when the message is sent — which explains the gap, but the official page does not mention it, so a reader of that page alone will draw the wrong conclusion.
Availability
| Platform | Available |
|---|---|
| Marketing Cloud Engagement | Yes |
| Marketing Cloud Next | No |
See also
- RedirectTo — the other send-context link function, likewise a pass-through on a page
- v — outputs the result inline
- Differs from docs: no shortening outside a send
- Official reference · ampscript.guide