
Fold direct mail into your SMS and email campaigns by leveraging your Klaviyo segments.
Connecting one app is easy. Designing a repeatable system that can support CRMs, ecommerce tools, webhooks, custom APIs, attribution, automation triggers, and future integrations without redesigning everything each time? That is where the fun starts.
Design one reusable integration framework where connecting third-party apps feels familiar, fast, and trustworthy even when the underlying APIs, fields, and business logic are different.
Customer data lived across 6 separate tools and every connector was a one-off build. 32% of customers already automate from an integration and ~$350K of mail/month runs on that data—yet 12 tickets/month asked for new connectors and 16/month came from users stuck setting one up (3 in 10 couldn't finish), pulling in CS, Sales, and engineering. (Figures from internal product analytics, rounded.)
Led the UX strategy and end-to-end design for one reusable integration framework—systems thinking over a shared connect → test → attribute → manage lifecycle—so a new connector ships as configuration, not a redesign. With a PM and a developer.
Per-connector lead time fell from 3–4 weeks to ~2. In the first 3-week parallel batch we shipped 4 new connectors—including Salesforce, requested by a client worth ~500K mails.
One management screen for connected accounts, their status and sync details, attribution setup, and the next action—so every connector lives in the same place.
Manage Integration — connected accounts with status and sync details, plus add-account, automation, and attribution actions
LettrLabs' vision is to be a one-stop shop for direct mail—but customers keep their leads, purchases, jobs, and CRM activity across many platforms. Every new connector had been its own build, so the same slow, expensive path repeated each time.
My reframing: this wasn't "add one more app." It was the gap between how a new integration should reach a customer and how it actually did.
Expected vs. actual integration journey
Expected
Customers, engineering, and business agree on which integrations are worth building, guided by what customers actually request.
Devs focus on a proper data pipeline and reuse one consistent workflow for every integration instead of reinventing the setup.
Once released, the connector is familiar and self-serve—the customer connects and starts automating within a week.
Reality
A customer asks for an integration, and it takes at least a month just to reach management and get prioritized—before any design or build begins.
Devs research the data pipeline and work with product to design the data model and satisfy each API's quirks—a fresh, custom effort every time.
They finally use it—but it's another unfamiliar process, so they run into problems or difficulty, and support gets pulled right back in.
The support queue and the analytics said the same thing: integrations were already core to how customers got value—but the way we built and set them up didn't scale. Before designing a screen, I let the evidence point at the pattern.
The strongest signal wasn't that any one screen looked wrong. It was that connecting an app kept stalling—so I audited every blocker and paired it with the fix the reusable pattern shipped.
Six connectors already existed as one-off builds. The reusable pattern let us add four more—including Salesforce, requested by a client worth ~500K mails—in a single three-week run. Each one is the same card, the same flow, a different source.

Fold direct mail into your SMS and email campaigns by leveraging your Klaviyo segments.

Retarget Shopify customers—first-time buyers, win-back segments, and more—straight into print.

Sync Salesforce contacts and pipeline stages to trigger direct-mail automations.

Automate your sending through Zapier's workflow-automation platform and 6,000+ apps.

Reveal anonymous website traffic and retarget those visitors with LettrLabs LeadReveal.

Automatically target storm-affected homeowners in your service area the moment a storm hits. Powered by HailTrace.

Trigger mailers off HubSpot lifecycle stages, list membership, and deal activity.

Automatically reach new movers in your area the week they arrive.

Integrate and automate your sending directly through the LettrLabs Open API.

Target customers automatically based on Housecall Pro jobs and service history.

Sync ServiceTitan jobs and customer records to launch automated field-service campaigns.

Push and pull events in real time and automate your sending through LettrLabs Webhooks.

Build a target audience by searching recipients directly—no upstream source required.

Automate mail sending to any recipient list with a simple CSV upload.

Automatically target properties based on new building-permit activity.

Sync AccuLynx roofing jobs and customer records to trigger automated direct-mail campaigns.
The four “New” connectors were added in the first 3-week run on the reusable pattern; the rest pre-existed as separate one-off builds.
The first design was far more powerful. To connect a CRM like Salesforce, you'd browse the entire schema, hand-map every object and field to the attribution model, define conversion/lead/exclude rules, then run a full extract-and-load pipeline into SQL. It could model almost anything—and that was exactly the problem.
V1 could model anything but assumed every user was a data engineer. Two simpler replacements looked elegant and quietly failed real Salesforce orgs: auto-inferred mappings guessed wrong on custom objects and renamed fields, and a single attribution slider couldn't represent two objects—Lead and Opportunity—with non-linear stages. Good ideas to kill.
The least clever version held up. You connect with credentials, then attribution becomes its own explicit step: confirm which statuses count as a Lead, a Conversion, or Job Complete, with a live warning if the choice would attribute nothing. A checkbox grid handles the pipelines and non-linear stages the slider couldn't.
| The job | V1 — powerful, complex | Shipped — simple & explicit |
|---|---|---|
| Find the data | Browse the full CRM schema and pick objects | Connect with credentials; the connection exposes what's needed |
| Map it | Hand-map event/customer objects + every field | Confirm which statuses count—explicit, a few clicks |
| Attribution | Define conversion/lead/exclude rules up front | Confirm Lead / Conversion stages, warned if nothing would attribute |
| Move the data | Configure & run an extract-load (dbt/SQL) pipeline | The connection tests and syncs on its own |
| How it felt | Like data engineering | Like signing in |
This is the through-line of the whole project: the reusable pattern below is what's left after deciding what the user should never have to care about.
The reusable pattern shown on a real connector (Housecall Pro): one entry point, a credentialed connect step that tests before it proceeds, explicit connecting/connected states, a management list for multiple accounts, and attribution setup as a separate job.

Only the essentials—name, Client ID, masked Client Secret—then Test and Continue before anything is saved.

The wait is explained: credentials are being verified and objects/fields discovered—not a dead spinner.

Success isn't the end—it routes straight to the next action (Customize Attribution).

Configuration is its own step: name the automation and pick a trigger before Save & Continue.

Every connected account on one surface—status (Active / Sync in Progress), last sync, Finish Setup, Customize Attribution, Add New Account, and Remove.
Because the same pattern has to hold across very different APIs, the safety lives in validation—catching problems at entry instead of after a broken sync.
| Field / step | Validation added | Why it matters |
|---|---|---|
| Connection identity & credentials | Name, format-checked Client ID, and a masked Client Secret are required; the secret is never shown again after save. | Accounts stay legible and bad or exposed credentials are caught at entry. |
| Test before save | A live connection test plus object and field discovery must pass before the user can continue. | No half-connected accounts; failures appear early enough to recover. |
| Account identity & status | Tenant IDs are unique, duplicates are blocked, and every account shows sync state with a last-updated time. | People can trust which source is connected and how fresh its data is. |
| Setup completion | Attribution is required before activation; the automation has to be named and tied to a valid trigger. | Automations are not launched on undefined, half-configured data. |
| Destructive change | Removing a connected account requires an explicit confirmation. | Changes that may affect live automations stay deliberate. |
I made the cost of each call visible so PM, engineering, and I could align faster.
How much should the connect step ask for up front?
Exposing every object and field was powerful, but it turned setup into a data-engineering task—3 in 10 users stalled before finishing.
Reduced connect to the few required inputs—name, Client ID, masked secret—tested before anything saves; deeper mapping became a separate, optional step.
Use AI to pre-suggest field mappings so even the optional step gets faster.
Connect and attribution—one flow, or two?
One flow felt continuous, but attribution carries different business logic and risk than authentication.
Split them: connect stays lightweight and universal; attribution is its own explicit job, shown only to users who need it.
Infer attribution defaults per connector, keeping the explicit step as the override.
Build each connector custom, or one reusable shell?
Custom screens fit each API perfectly, but every new app restarted design and engineering—6 one-off builds, 3–4 weeks each.
One reusable lifecycle where logo, name, fields, and attributes are configuration—so a connector ships as setup, not a redesign. Four shipped in a three-week parallel batch.
A connector "manifest" so a new source can be added with no new design at all.
Where should connection status live?
Keeping status on the detail page was simplest, but users lost track of what was active, syncing, or failed across many accounts.
Surfaced status in the account list and in-app notifications—active, sync-in-progress, failed, or ready—beyond a single screen.
Proactive alerts when a sync breaks, before it silently pauses an automation.
The win wasn't a prettier connect screen. It was a workflow that matched how the business, engineering, and customers actually add a source.
The shipped connect → test → confirm → manage flow validates credentials before save and makes each next action explicit. Completion and ticket reduction are the measures to validate with live usage.
Per-connector lead time fell from 3–4 weeks to ~2, and the first parallel batch shipped 4 new connectors in three weeks—including the Salesforce one a ~500K-mail client was waiting on.
Instead of researching and building each connector from scratch, engineering slots new sources into a stable lifecycle—logo, name, fields, and attributes as configuration.
The reusable pattern shipped across four new connectors—Salesforce, ServiceTitan, HubSpot, and Housecall Pro—and is designed to support future sources as configuration rather than a redesign.
The baseline was 16 setup tickets a month and 3 in 10 users unable to finish alone. The new flow gives that work a clear measurement plan: connection completion, setup tickets, and time to first automation.
The framework links account setup to attribution, automation, and analytics. The opportunity is to expand the $350K/month integration-data base through more completed, well-configured connections—not to claim that growth before it is measured.
My first assumption was that connecting integrations would require many fields and a lot of visible configuration. But after working through the flow with the team, the better answer was the simpler one: ask for only what is essential, validate it clearly, and let the backend do the heavy lifting.
Version 2 would refine syncing status, add stronger search for integrations, broaden the supported credential types, and use AI to help preselect fields for automation, data merge, and attribution setup.
"This project taught me that good platform design is not about showing all the data. It is about knowing which data matters, hiding the rest, and making the next integration easier than the last."