Back to blog
Article

Customer Integration Portals: Hand-Built vs Embedded

By Aylon··6 min read

Every B2B SaaS needs an integrations UI eventually. Here's what the hand-built version looks like vs the embedded-portal alternative.

Every B2B SaaS reaches the point where customers want to configure their own integrations. "Hey, can I set up the webhook URL myself?" "Can I add my own warehouse credentials?" "Can I see the delivery log for my own destinations?" The answer is yes, and the implementation choice is whether you build the UI yourself or embed one.

The DIY scope

A customer-facing integrations UI isn't a small feature. The minimum surface:

  • Destinations CRUD. A list view, a create flow per destination type, an edit flow, a delete flow with confirmation. For each destination type, webhooks, S3, BigQuery, Snowflake, Kafka, etc., a separate form with the right fields, the right validation, and a connection-test button.

  • Credential storage. Encryption at rest, masked display, rotation flow, audit log entries.

  • Routing rules. A UI to add filters per destination, event type sets, payload-field comparisons, tier conditions.

  • Delivery log. A paginated table of delivery attempts. Filterable by destination, event type, status, time window. Detail view per attempt with full request/response payloads.

  • DLQ view. A separate table of dead-lettered deliveries. Inspection, bulk actions, replay triggers.

  • Replay UI. A scope picker (single delivery, time window, whole DLQ), a preview, a progress indicator, a results view.

  • Health indicators. Per-destination health (healthy, degraded, failing). Alerts when destinations go unhealthy.

  • Theming. Match your app's design system, colors, typography, spacing, component shapes.

  • Accessibility. Keyboard navigation, screen reader support, focus management, ARIA labels.

That's roughly 12–16 distinct UI surfaces. Estimate 4–6 months of frontend engineering to ship a credible v1.

What goes wrong with DIY

The DIY path has predictable failure modes:

Half-built ships. Teams build the webhook destination form first because it's the most common type, then ship before building the S3 / BigQuery / Kafka forms. Customers wanting other destination types are stuck.

Theming drift. The integrations UI gets built by a small team in a corner of the codebase. Six months later, your design system updates and the integrations UI doesn't follow. Customers see a UI that looks like a different product.

Operational debt. Every destination type's form needs its own validation, connection-test, error messaging. When the underlying adapter changes, the form needs to change too. Drift is constant.

Audit log gaps. The customer-facing UI surfaces some of the platform's data, but rarely all of it. Customers ask for things ("show me the response body of attempt 3") that require backend changes to surface in the UI.

The customer's first impression. The integrations UI is what enterprise prospects see during their evaluation. A polished one wins deals; a half-built one loses them.

The embedded-portal alternative

The embed model: a React component you mount inside your existing dashboard. You issue a session token scoped to the signed-in customer; the component renders the destinations UI scoped to that token.

What you ship:

<PushrailEmbed token={sessionToken} />

What the customer sees: a fully-featured integrations UI inside your app, with your theme, scoped to their tenant. They configure destinations, view delivery logs, replay failures, without leaving your app, without you maintaining the UI.

What the platform handles: every form, every validation, every adapter, every credential type, the delivery log surface, the DLQ, replay, audit. When a new destination type ships on the platform, it shows up in the portal automatically.

When DIY makes sense

The embedded path doesn't fit every product. DIY makes sense when:

  • The integrations UI is a competitive differentiator (rare, usually it's table stakes).
  • You need custom workflows that don't fit the embed's shape (e.g., compound destinations that aggregate events before forwarding).
  • You have a design language that explicitly forbids embedded UIs (rare; most modern design systems are theme-driven enough).
  • You have a frontend team with bandwidth to maintain it indefinitely.

For most B2B SaaS, none of these apply. The integrations UI is plumbing the product needs but doesn't sell with. The embedded path is the rational call.

Theming the embed

The embed needs to look like part of your app, not a guest from another planet. Modern embeds (including Pushrail's) read your design tokens (colors, typography, spacing, border radius, shadows) and apply them to every component. Customers see their dashboard's look-and-feel, not the platform's.

The result is indistinguishable from a hand-built UI for the user, with none of the maintenance burden for you.

Auth model

The embed needs an authorization model that's narrow enough to be safe:

  • Session token scoped to one customer (sub-tenant).
  • Short TTL (15 minutes typical), refreshed by your backend on demand.
  • Token grants no permissions beyond reading + writing data for that customer.
  • Revocation is immediate (your backend stops refreshing).

The customer can do anything they're allowed to do; they can't do anything they're not.

How Pushrail does it

Pushrail's embedded portal is a React component (@pushrail/embed-react) that renders the destinations + routing + delivery-log UI scoped to the session token you issue. The integration is three steps: install the component, issue a token from your backend, pass the token to the component. The customer sees a portal that looks like part of your app.

Up next in the series: build vs buy webhook infrastructure, an honest framework for which side of the line your product belongs on.

Ready to stop building delivery infrastructure?

Start free. Send your first event in under 5 minutes.

Protected by reCAPTCHA, Google's Privacy Policy and Terms apply.