Salesforce Marketing Cloud Customization

Salesforce Marketing Cloud Customization, Where Configuration Runs Out

Marketing Cloud customization is the work that begins where configuration stops: AMPscript and Server-Side JavaScript for send-time logic, CloudPages for hosted experiences, custom Journey Builder activities that call your own services mid-journey. Twopir Consulting builds that layer — and tells you when you do not need it, which is more often than most development partners will admit.

  • 12+ Years of CRM and platform development
  • 40+ Certified Salesforce, HubSpot and AI specialists
  • 98% Client retention rate
Customization Surfaces
WHERE CONFIGURATION RUNS OUT Dynamic content Rules the content editor cannot express AMPscript Send-time data lookups Values fetched as the message renders AMPscript / SSJS Hosted pages and forms Landing pages, captures, microsites CloudPages Mid-journey external calls Your service, inside the journey Custom activity Preference and consent Your obligations, your wording CloudPages + API TWOPIR DEVELOPMENT PRACTICE Configure First Code only where config cannot reach Documented What it does and why it exists Upgrade-Safe Survives three releases a year 2πr WHAT YOU AVOID Code nobody left in the building can maintain The single commonest finding in an inherited org A platform release that quietly breaks a send Custom code is where release risk actually lives
The First Question

Does This Requirement Actually Need Code?

Usually not. Marketing Cloud is more configurable than teams assume, and most requests that arrive described as customization are configuration nobody has found yet. Here is the honest version of where the line sits.

Common requirements and whether they need custom code
RequirementConfiguration can do itCode is genuinely needed when
Different content by segmentYes — dynamic content blocks in Content Builder handle rule-based variation without a line of AMPscript.The rule depends on a value that has to be calculated at send time, or on data that lives outside the sending data extension.
Personalized greeting and merge fieldsYes — personalization strings and attributes cover this natively.You need fallback logic, formatting, or a conditional that the content editor cannot express.
A landing page tied to a campaignSometimes — a simple page can be built in CloudPages with no code.The page reads or writes Marketing Cloud data, pre-fills from a link, or has to behave differently per visitor.
A preference centerA basic subscription center exists natively.You need channel-level preferences, regional consent wording, your own brand experience, or write-back to more than one data extension — which is most real requirements.
Calling another system mid-journeySometimes — a native activity may already exist for it.Your service has to be called, its response inspected, and the journey path decided on the result. That is a custom Journey Builder activity.
Complex audience logicUsually — SQL in Automation Studio handles more than people expect.The logic has to run at send time per recipient rather than at audience-build time.
Sending at a per-customer optimal timeYes — Einstein Send Time Optimization does this natively, using engagement history.Almost never. This is the clearest example of a requirement that gets custom-built by teams who did not know the feature existed.

Capabilities verified against Salesforce documentation Last reviewed 23 September 2026

What We Build

Four Places Marketing Cloud Is Genuinely Extensible

When the answer to the question above is that code is needed, these are the four surfaces it gets written on. Each has a different maintenance cost, and we say which before writing anything.

Send-Time Logic

AMPscript and Server-Side JavaScript

The scripting layer that runs as a message renders — looking up related records, formatting values, deciding what a given recipient sees. AMPscript covers the majority of it; SSJS is for the cases that need real programming constructs, and it is slower, so we reach for it second.

  • Conditional content beyond what dynamic blocks can express
  • Lookups into related data extensions at send time
  • Formatting: currency, dates, locale, safe fallbacks for missing values
  • Personalization that degrades gracefully rather than rendering blank
  • Reusable code snippets, so the same logic is not pasted into forty emails
Hosted Experiences

CloudPages: landing pages, forms and microsites

Pages hosted inside Marketing Cloud that can read and write platform data. Used well, they are how a customer updates their own record without anyone rekeying it; used badly, they become an unversioned website nobody owns.

  • Campaign landing pages that write directly into a data extension
  • Data capture forms with validation and duplicate handling
  • Pre-filled pages driven from a personalized link in an email
  • Event registration and confirmation flows
  • Hosted unsubscribe and preference experiences on your own branding
Journey Extension

Custom Journey Builder activities

An activity that appears in the Journey Builder canvas like any native one, but calls your service. This is how a journey asks a question of a system Marketing Cloud does not know about, and then branches on the answer.

  • Calling an external scoring, eligibility or inventory service mid-journey
  • Writing journey progress back into another system in real time
  • Branching a journey on a response from your own API
  • Custom activities with proper error handling, so a failed call does not strand a contact
  • Documented contracts, so the activity survives a change at the other end
Consent & Preference

Preference centers built to your obligations

The native subscription center handles the simple case. Most organizations are not the simple case — they send across several markets, on several channels, under several legal bases, and need the customer to be able to choose between them in language that matches their brand.

  • Channel-level and topic-level preference management
  • Regional consent wording and lawful-basis capture where required
  • Write-back to Marketing Cloud and to the CRM as the authoritative record
  • Honouring a global opt-out consistently across every business unit
  • Audit trail: what was consented to, when, and from which page
How We Write It

Four Rules We Hold Ourselves To When Writing Code in Your Org

Custom code in Marketing Cloud is a liability as well as an asset. It has no version control by default, no test framework, and it runs inside a platform that changes three times a year. Every line written today is something somebody has to understand in two years.

These four rules are what makes the difference between an extension and a hostage situation. They are also, bluntly, what we wish the previous partner had followed in most orgs we inherit.

Where the requirement turns out to be integration rather than customization, it belongs on the API and integrations page instead — different surface, different standards.

Configuration is attempted first, and the attempt is documented

Before any code is written, we establish in writing why configuration cannot meet the requirement. That note lives with the code. It is what lets the next person — including the next person at Twopir — know whether the custom block can now be retired because the platform has caught up, which it frequently has.

Nothing is hard-coded that could change

Data extension names, external keys, business unit IDs, endpoints and thresholds live in configuration the client can see and change, not buried in a script. An AMPscript block with a subscriber key pattern hard-coded into it is the reason a perfectly good migration fails eighteen months later.

Every block has an owner, a purpose and a failure mode

What it does, why it exists, what happens when the data it expects is missing, and who to call. Marketing Cloud gives you no place to put this, so we keep a code register alongside the org documentation and hand it over as a deliverable rather than as a favour.

It is written to survive three releases a year

Custom code is where platform-release risk actually concentrates. We avoid undocumented behavior, we do not depend on rendering quirks, and anything that touches an area Salesforce is actively changing gets flagged in the register so it is checked at each release rather than discovered when a send fails.

12+
Years delivering CRM and marketing platform transformation
40+
Certified specialists across Salesforce, HubSpot & AI
250+
Platform deployments delivered
98%
Client retention rate
Failure Modes

The Four Ways Custom Code Turns Into Debt

Every one of these is something we have been called in to unpick, and none of them looked like a mistake at the time. They are what happens when code is written to solve today's problem without anyone asking who maintains it.

If more than one sounds familiar, an audit that inventories the custom code in your org is usually the cheapest possible next step.

The block that does something nobody can explain — A piece of AMPscript that has been copied into a dozen emails, modified slightly in several of them, and whose author left two years ago. Nobody will touch it and nobody will delete it, so it propagates into every new template.

Custom code doing a job the platform now does natively — Built when the feature did not exist, kept because nobody revisited it. Send time optimization, engagement scoring and content selection are the usual suspects — all of which Einstein does natively, and better, using your own engagement history.

CloudPages as an unmanaged website — Pages accumulate with no versioning, no inventory and no owner. Some are still publicly reachable years after the campaign ended, occasionally still collecting data into a data extension nobody reads.

A custom activity with no failure path — An external call that works until the service at the other end is slow or down. Without error handling, contacts strand mid-journey, and because nothing alerts, the first sign is a customer asking why they never received the second email.

When to Look

Signs Your Org Has More Custom Code Than It Should

Custom code is not inherently a problem. Unowned, undocumented, unnecessary custom code is. These five signals distinguish the two, and every one of them is answerable with an inventory rather than a rebuild.

A change to an email requires a developer, because the content is assembled by a script rather than by the content editor.
Nobody can produce a list of the custom code in the org, so nobody can say what a platform release puts at risk.
The same logic exists in several slightly different versions across templates, and no one is certain which is current.
A CloudPage is still live and still collecting data from a campaign that ended more than a year ago.
Custom code is doing something the platform now does natively — and better — because it was written before the feature existed.
Common Questions

Questions About Custom Development

Configuration is building with what the platform gives you through its interface — data extensions, journeys, dynamic content blocks, automations. Customization is writing code that runs inside the platform: AMPscript, Server-Side JavaScript, CloudPages and custom Journey Builder activities.

The practical difference is maintenance. Configuration is inspectable by anyone with access and survives platform releases without attention. Code needs an owner, documentation and a release check, permanently. That is why the first question on any requirement is whether configuration can reach it.

AMPscript for the large majority of send-time work — it is purpose-built for rendering content, it is what most Marketing Cloud developers read fluently, and it performs better in the send context. Server-Side JavaScript is for cases that genuinely need programming constructs the scripting language does not offer, such as complex loops over structured data or JSON handling.

A useful heuristic: if a Marketing Cloud administrator could not read the block and say roughly what it does, ask whether the requirement really needs it. SSJS used for convenience rather than necessity is a maintenance cost with no matching benefit.

Yes — that is what a custom Journey Builder activity is for. It appears in the canvas alongside the native activities, calls your service, and the journey can branch on what comes back.

The decisions that take longer than the build are what happens when your service is slow or unavailable, how long the journey should wait, and where a contact goes if the call fails. An activity without an explicit failure path strands contacts silently, which is why we specify that behavior before writing the activity.

It can, and custom code is where release risk concentrates — which is precisely why we keep a register of every block in the org, what it depends on, and which platform areas it touches. At each of the three annual releases, that register is what gets checked, rather than hoping.

The code most likely to break is the code that depends on undocumented behavior or on rendering quirks. Written to documented behavior, most custom code is stable for years.

With an inventory, not a rewrite. An audit establishes what exists, what each piece does, what still runs and what is already dead. In most inherited orgs a meaningful share turns out to be unreferenced, duplicated, or doing something the platform now does natively.

Then it is a sequencing exercise: retire the unnecessary, document the necessary, and rewrite only what is both necessary and unmaintainable. Rewriting everything is rarely the right answer, and it is never the right first answer.

You own it, and you get it documented — what each block does, why it exists, what it depends on and how it fails. That register is a deliverable, not something you would have to ask for at the end of an engagement.

We would rather compete on whether the work is good than on whether you can leave. A development partner whose commercial position depends on you not understanding your own org is a partner with the wrong incentives.

Next Step

Tell Us the Requirement, Not the Technique

Describe what the customer should experience and we will tell you whether it needs code, what it costs to maintain if it does, and whether the platform already does it. Sometimes the useful answer is that you can stop paying for something you already have.

Serving: US | Canada | UK | UAE | Australia | New Zealand

Relatable? We should definitely talk.

What we'll cover:

From CRM and integrations to custom apps and complex system architecture — we help you scale without chaos.
  • Identify revenue leaks across CRM, integrations, and GTM
  • Design and optimize complex systems (CRM to Custom Apps)
  • Apply practical AI to improve operations and pipeline conversion
  • Eliminate silos and build a unified revenue system
  • Assess GTM performance and key bottlenecks
  • Align teams with clear processes and ownership
  • Define a scalable RevOps model
  • Improve forecasting and reporting
  • Review your HubSpot/Salesforce setup for scale