Send email from FullStory with Volanea by using FullStory’s segment-based webhook automation as the behavioral trigger and a small server-side relay as the delivery layer. This approach does not require a native FullStory app or marketplace plugin, and it keeps your Volanea API key out of browser code and out of event data.

What this integration does

FullStory is designed to help teams understand product behavior: sessions, frustration signals, events, conversions, and the users or sessions that match a saved segment. Volanea is the sending layer in this workflow. The connection lets you act on a behavior that FullStory has identified without trying to turn a session-replay tool into an email delivery system.

A practical example is a customer who reaches a high-intent segment after viewing pricing repeatedly, completing key product actions, and still not activating a feature. Rather than manually exporting a list, a FullStory automation can notify your server when the relevant segment condition is met. Your server can apply business rules and send an appropriate transactional or lifecycle message through Volanea.

The important distinction is that FullStory is the source of the behavioral signal, not the source of truth for email consent, campaign eligibility, or contact data. Your relay should enrich and validate the signal before it calls the email API.

This guide uses the FullStory automation trigger commonly described as a user entering a segment. The resulting flow is:

  1. A user meets the criteria for a saved FullStory segment.
  2. A FullStory automation sends an outbound webhook to your HTTPS endpoint.
  3. Your endpoint verifies the request, maps the webhook body to a contact in your application, and decides whether an email is allowed.
  4. The endpoint calls Volanea’s REST email endpoint.
  5. Volanea accepts the message for delivery and returns a send identifier that you record for troubleshooting and deduplication.

This is intentionally a server-to-server integration. It is not a client-side JavaScript integration, and it is not a way to expose a sending credential in a FullStory snippet, a browser environment variable, or a public frontend bundle.

FullStory capability: use an automation webhook, not a native app

Volanea does not ship a native FullStory listing, installed app, or marketplace connector. Do not look for a one-click Volanea integration in FullStory, and do not treat FullStory session data as if it were a mailing list.

The workable direct route is FullStory’s outbound webhook capability in an automation. Configure an automation around a segment, with the behavioral condition expressed in the segment and a webhook as the action. The concrete trigger is when a user enters the selected FullStory segment.

That wording matters. A segment is a rule-based group, not necessarily a CRM pipeline stage or a form submission. For example, your segment might identify users who:

  • completed an onboarding event but did not complete an activation event;
  • encountered a defined frustration pattern during checkout;
  • viewed a help or pricing area several times in a defined period; or
  • matched an account, user-property, or event-property condition that you have already instrumented.

The automation fires when FullStory determines that the user enters that segment. It should not be treated as a guarantee that the person should receive marketing email. Segment membership is a product signal. Your own data must still decide whether the address exists, is verified, has the right consent status, and has not already received the message.

Why a relay belongs between FullStory and Volanea

Even when a webhook action supports custom headers, a relay is the safer production design. It gives you a place to authenticate FullStory, normalize incomplete data, look up a customer record, enforce suppression rules, make the Volanea API request, and return a fast response.

It also means FullStory does not need the Volanea credential at all. FullStory stores only a webhook URL and, where supported, a shared webhook secret or authorization value used to authenticate to your endpoint. The Volanea API key stays in your server’s secret manager or encrypted deployment environment.

A direct webhook-to-email-API design may look shorter, but it creates unnecessary exposure. Anyone with permission to inspect or alter the FullStory automation could potentially view or replace the authorization header. It also makes it difficult to use a contact ID to retrieve a verified, consented recipient from your own database.

Design the segment before you design the message

The strongest integration starts with a narrowly defined behavioral segment. “Visited the product” is too broad. “Reached activation step three, then had three failed attempts and no success event within 24 hours” is a behavioral rule that can justify a specific help message.

Start by writing the operating rule in plain language:

When an identified user enters the activation-stalled segment, send one support-oriented message only if the user has opted in to the relevant email category, has not completed activation, and has not received this message in the last seven days.

Then split that rule between the systems that can actually enforce it:

ResponsibilityBest location
Identify product behaviorFullStory segment
Decide whether a person can receive emailYour customer database or consent system
Resolve a stable recipient email addressYour customer database
Prevent repeated sendsYour relay database or queue
Send and observe deliveryVolanea

This division prevents a common failure mode: using an email address copied into a client-side FullStory user variable as if it were an authoritative and consented contact record. In many implementations, user identity information is deliberately minimized, redacted, unavailable to a specific role, or simply absent for anonymous sessions.

Choose a stable identifier

Pass a stable internal user or account identifier in the webhook whenever the FullStory automation’s webhook templating supports it. Do not make a raw email address your primary join key if you can avoid it. Email addresses change, may be absent, and are particularly sensitive data to distribute through observability systems.

A good minimal webhook event has these concepts:

  • an event identifier for idempotency;
  • the FullStory user identifier or your mapped application user identifier;
  • the segment identifier and human-readable segment name;
  • the time the segment action occurred; and
  • a session URL or session reference for support staff, if your privacy policy permits it.

The message content should come from your application and email template, not from unbounded text captured from a session. Treat every value from a webhook as untrusted input.

Configure the FullStory segment webhook

Create the segment first, test it against known sessions, and only then attach the automation. The exact availability of webhook automations and the fields available in a webhook template can depend on your FullStory subscription, permissions, configuration, and the data you have captured. If the webhook option is not available in your account, use the middleware alternative described later rather than assuming every plan exposes outbound HTTP actions.

In the FullStory automation, select the saved segment and configure the trigger for a user entering the segment. Set the action to send a webhook to an endpoint you control, such as:

https://events.example.com/fullstory/activation-stalled

Use HTTPS. Do not send events to a localhost URL, a browser endpoint, or a URL that contains the Volanea API key as a query parameter.

Where the webhook action allows a custom request body, configure a compact JSON body that contains only fields the relay needs. The following is the payload shape this guide configures FullStory to send. The placeholders represent FullStory webhook-template values available in your account; use the picker or documented template syntax in your FullStory UI rather than manually guessing token names.

{
  "event_id": "<FullStory webhook event identifier>",
  "occurred_at": "<event timestamp in ISO 8601 format>",
  "event_type": "user_entered_segment",
  "fullstory_user_id": "<FullStory user identifier>",
  "segment": {
    "id": "<segment identifier>",
    "name": "activation-stalled"
  },
  "session_url": "<FullStory session URL, when available>"
}

This is a deliberately narrow payload. It does not assume that an email address, display name, account plan, session URL, or every user property is available in every FullStory webhook context. It also makes the integration more resilient if your privacy configuration changes.

Add a header that authenticates FullStory to your relay. A simple option is a static secret header:

X-FullStory-Webhook-Secret: <long-random-secret>
Content-Type: application/json

Store that shared secret in FullStory’s server-side webhook configuration, not in code running in the browser. Store the matching value as FULLSTORY_WEBHOOK_SECRET in your relay’s secret manager. If FullStory provides a signed-webhook mechanism in your account, verify that signature according to its documentation instead of inventing a signature scheme.

Do not put Authorization: Bearer <Volanea API key> in the FullStory action. The webhook’s authorization belongs to the FullStory-to-relay hop. The Volanea key belongs only to the relay-to-Volanea hop.

The payload mapping and Volanea REST call

The FullStory webhook does not itself contain a safe, complete email-send request. The relay should use fullstory_user_id to look up a recipient in your database, confirm eligibility, and construct the Volanea request.

The example below is an Express handler. It shows the complete mapping: FullStory’s configured webhook payload enters the handler; the handler looks up a recipient; it creates an idempotency key; and it sends the message through Volanea’s REST API. Before deployment, compare the endpoint, request fields, and authentication format with the current email API reference and setup guides, since API versions and available sending features can change.

import crypto from "node:crypto";
import express from "express";

const app = express();
app.use(express.json({ type: "application/json", limit: "100kb" }));

function sameSecret(received, expected) {
  if (!received || !expected) return false;
  const a = Buffer.from(received);
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/fullstory/activation-stalled", async (req, res) => {
  // Authenticate the FullStory -> relay hop.
  if (!sameSecret(req.get("X-FullStory-Webhook-Secret"), process.env.FULLSTORY_WEBHOOK_SECRET)) {
    return res.status(401).json({ error: "unauthorized" });
  }

  const { event_id, event_type, fullstory_user_id, segment, occurred_at, session_url } = req.body;

  if (event_type !== "user_entered_segment" || !event_id || !fullstory_user_id || !segment?.id) {
    return res.status(400).json({ error: "invalid FullStory webhook payload" });
  }

  // Replace these functions with your database and queue implementations.
  // Claiming the event must be atomic: false means a retry was already handled.
  const firstDelivery = await database.claimWebhookEvent(event_id);
  if (!firstDelivery) return res.status(200).json({ status: "duplicate_ignored" });

  const user = await database.findUserByFullStoryId(fullstory_user_id);
  if (!user || !user.email || !user.lifecycleEmailOptIn || user.activationCompletedAt) {
    return res.status(200).json({ status: "not_eligible" });
  }

  const sentRecently = await database.hasSent(
    user.id,
    "activation-stalled-v1",
    7 * 24 * 60 * 60
  );
  if (sentRecently) return res.status(200).json({ status: "frequency_limited" });

  // FullStory -> Volanea field mapping:
  // fullstory_user_id -> database lookup -> user.email and user.firstName
  // segment.name      -> template context segment_name
  // occurred_at       -> template context behavior_detected_at
  // session_url       -> internal support context, not necessarily email content
  const emailPayload = {
    from: { email: "help@example.com", name: "Example Support" },
    to: [{ email: user.email, name: user.firstName || undefined }],
    subject: "Need a hand finishing setup?",
    html: `<p>Hi ${escapeHtml(user.firstName || "there")},</p>
           <p>It looks like setup may have taken longer than expected.</p>
           <p><a href="https://app.example.com/setup">Continue setup</a></p>`,
    text: `Hi ${user.firstName || "there"},\n\nNeed a hand finishing setup? Continue at https://app.example.com/setup`,
    headers: {
      "X-Application-Event": "activation-stalled-v1",
      "X-FullStory-Segment": String(segment.name || segment.id)
    }
  };

  const volaneaResponse = await fetch("https://api.volanea.com/v1/emails", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.VOLANEA_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `fullstory:${event_id}`
    },
    body: JSON.stringify(emailPayload)
  });

  const responseBody = await volaneaResponse.text();
  if (!volaneaResponse.ok) {
    await database.releaseWebhookEventForRetry(event_id, responseBody);
    return res.status(502).json({ error: "Volanea send failed" });
  }

  await database.recordSend({
    userId: user.id,
    messageType: "activation-stalled-v1",
    fullstoryEventId: event_id,
    fullstorySessionUrl: session_url || null,
    detectedAt: occurred_at || null,
    providerResponse: responseBody
  });

  return res.status(202).json({ status: "accepted" });
});

In production, use a template rather than assembling HTML directly in the handler. The inline HTML above exists only to make the API mapping visible. If any user-derived value appears in a message, HTML-escape it and keep it within defined length limits.

Also, queue the actual Volanea call when possible. A webhook handler that validates, persists an event, enqueues work, and returns a 202 quickly is more reliable than one that waits for a remote email provider during the inbound request.

Keep Volanea credentials out of client-visible configuration

There are two secrets in this architecture, and they serve different purposes.

The first is the FullStory webhook secret. It lives in the FullStory automation’s server-side webhook configuration and in the relay’s secret store. It lets the relay reject requests that did not originate from your configured FullStory action. Limit access to the automation configuration because a user who can edit its destination can redirect behavioral data.

The second is the Volanea API key. It lives only in the relay’s server-side secret manager, such as a cloud secret service, encrypted environment configuration, or deployment platform secret. It is read at runtime as VOLANEA_API_KEY. It must not live in:

  • a frontend .env variable compiled into a browser bundle;
  • a FullStory custom user property or event property;
  • a webhook URL query string;
  • source control, test fixtures, screenshots, or support tickets; or
  • a client-side serverless function that can be invoked without server-side authorization.

Use a sending key with the narrowest feasible scope, rotate it on a documented schedule, and revoke it immediately if its value appears in logs or source control. Ensure HTTP request logging redacts Authorization, webhook secret headers, recipient addresses, and message bodies.

Add consent, verification, and sending policy checks

A FullStory segment can identify an opportunity to communicate; it does not establish permission. Before sending, your relay should check the policy appropriate to the message type and jurisdiction.

For a purely transactional message, the eligibility rule may be tied to an account action: password recovery, receipt delivery, security notification, or a direct response to a support request. For lifecycle or promotional messaging, you normally need the applicable marketing consent record and an accessible unsubscribe path.

At a minimum, make these checks explicit in code or your queue worker:

  1. The application user maps to exactly one current recipient address.
  2. The recipient is not globally suppressed, bounced, or unsubscribed from the relevant category.
  3. The event is relevant now; the user has not already completed the action that prompted the message.
  4. The user has not exceeded the frequency cap for this message type.
  5. The recipient address is syntactically valid and, for higher-risk workflows, has passed your verification policy.

If you need to check an address before adding it to a workflow, use an address-verification process rather than trusting a form field or a replay identifier. A free email address verification tool can be useful for one-off checks, while production applications should apply validation and suppression rules consistently in their own data path.

When this breaks: retries, timeouts, and missing fields

The FullStory-to-relay-to-Volanea chain has two network boundaries, which means failures are expected rather than exceptional. Design each boundary to be safe to retry.

FullStory retries can create duplicate sends

A webhook sender may retry when it does not receive a timely successful response, when a connection fails, or when it receives a retryable server response. A retry can arrive after your relay has already sent the email but before your relay returned a response. If every delivery creates a new send, one behavioral event can produce multiple messages.

Use the FullStory webhook event identifier as the primary idempotency key when it is available. Store it in a database table with a unique constraint before you queue or send the message. Also retain a business-level cap such as one “activation stalled” message per user per seven days. The event-level key handles transport retries; the business-level key handles separate events that represent the same customer situation.

If the webhook payload does not expose a stable event identifier in your plan or configuration, build a deterministic fallback key from a stable user ID, segment ID, and normalized event time bucket. That is less precise, so use it only with a frequency cap and monitor for collisions.

Webhook timeouts should not block sending

Your endpoint should respond quickly. A slow database lookup, template render, or synchronous provider request can cause FullStory to regard the webhook as unsuccessful and retry it. Aim for the inbound handler to authenticate, validate, persist, enqueue, and return.

A robust sequence is:

  1. Verify the FullStory authentication header or supported signature.
  2. Validate the JSON schema and reject malformed input with a non-success response.
  3. Atomically record or claim the event ID.
  4. Put a compact job on a durable queue.
  5. Return a successful response promptly.
  6. Let a worker perform the customer lookup and Volanea request.

Return a non-success response only when you want the sender to retry or when the request is invalid. For a known duplicate, an ineligible user, or a message suppressed by your policy, return success after recording the outcome. Those are processed events, not transient transport errors.

Some expected fields may be absent

Do not assume every FullStory identity, property, or session field is available in every webhook context. Field availability can be affected by your FullStory plan, user identification practices, privacy configuration, role permissions, the event type, or whether the session is anonymous. A user can also enter a segment before a particular user variable has been set.

This is why the example uses fullstory_user_id as a lookup key and treats session_url as optional. Validate every required field at the relay boundary. If a field is absent, choose a deliberate outcome: discard the event as ineligible, queue it for reconciliation, or route it to internal review. Never substitute an empty address and never guess a recipient from a display name.

Provider acceptance is not inbox delivery

A successful Volanea API response means the provider accepted the request, not that the message has reached the inbox. Record the provider response and correlate it with your message type, but use delivery events, bounce handling, complaint handling, and suppression management to assess outcomes.

If the workflow begins sending at meaningful volume, monitor the rate at which FullStory events are received, eligible sends are queued, Volanea calls succeed, bounces occur, and users later complete the target action. A high behavioral-trigger rate with low conversion can indicate that the segment is too broad, the email is poorly timed, or the message is being sent to people who already resolved the problem.

Test the integration without emailing customers

Use a dedicated test segment, test user, and a mailbox you control. First verify that FullStory records the intended product behavior and that the test user enters the segment. Then inspect the relay’s redacted event log to verify the actual body received from FullStory.

Test these cases before enabling the production automation:

  • a correctly formed event for an eligible recipient;
  • the same event sent twice, to confirm idempotency;
  • an anonymous or unknown FullStory user;
  • a user without the required consent or with an active suppression;
  • an event after the user has already completed activation;
  • a simulated Volanea API failure; and
  • a delayed queue job that runs after the email is no longer relevant.

Avoid testing by copying production replay data into third-party tools. Keep test payloads minimal and synthetic, particularly where session URLs or user identifiers could reveal sensitive behavior.

If outbound webhooks are unavailable in your FullStory account

If your FullStory plan or configuration does not expose the outbound webhook automation action, do not claim that a direct API integration exists. Use a middleware workflow instead.

The exact alternative depends on the capabilities available to your account. A common pattern is to send an available FullStory alert or supported integration event into an automation platform, then invoke your own relay with an authenticated webhook. Zapier or Make can be useful for early validation, but they should still call a server-side endpoint you own rather than calling Volanea with a key stored in a broadly editable automation step.

The same safeguards apply: pass a stable user ID, perform consent and recipient lookup in your system, deduplicate events, and keep the Volanea credential in the relay. An automation platform does not remove the need for idempotency; it adds another system that can retry or replay a task.

For higher-volume or customer-critical sends, a durable queue and a small service are generally easier to audit than a chain of no-code steps. Use no-code middleware to prove the trigger and message logic, then move the policy and credential-bearing steps into code when the workflow becomes operationally important.

Operational guidance for behavior-triggered email

Behavior-triggered email often performs best when it is helpful, narrow, and reversible. The content should acknowledge the task, offer a next step, and avoid language that feels like surveillance. A message such as “Here’s a guide to finish setup” is usually safer than “We saw you struggle on this screen.”

Keep the FullStory signal out of the visible copy unless the recipient has a clear expectation of how that data is used. Use the event internally to choose the message and timing. Your privacy notice, consent model, and internal access controls should match the way you process behavioral data.

Treat the integration as a feedback loop. Review segment precision, opt-out rates, bounce rates, support outcomes, and downstream activation. If a segment starts producing too many messages, pause the automation first, then investigate the behavior rule and the relay’s eligibility logs.

Conclusion

To send email from FullStory with Volanea, use FullStory’s user enters segment automation trigger to send a narrow, authenticated webhook to infrastructure you control. Let the relay resolve the recipient, enforce consent and frequency rules, deduplicate retries, and make the Volanea REST call with a server-side API key.

That extra relay is not needless complexity. It is the boundary that makes a behavioral signal safe to turn into email: it protects credentials, prevents duplicate sends, handles incomplete webhook fields, and keeps product analytics separate from email eligibility.

FAQ

Does Volanea have a native FullStory integration?

No. Volanea does not provide a native FullStory marketplace app or plugin. Use FullStory’s outbound webhook automation where available, with a secure relay that calls Volanea’s API.

What starts the email send in FullStory?

The trigger is a user entering a saved FullStory segment. The segment defines the behavior; the automation sends the outbound webhook after FullStory determines that the user meets that segment’s criteria.

Should I put my Volanea API key in the FullStory webhook header?

No. Put only a FullStory-to-relay authentication secret in the webhook configuration. Keep the Volanea API key in your server-side secret manager and use it only when the relay calls Volanea.

How do I prevent duplicate emails after a webhook retry?

Store a unique FullStory event identifier before queuing or sending. Use that identifier as an idempotency key, and add a separate per-user frequency cap for the message type.

What if the FullStory webhook does not include an email address?

That is expected in many privacy-conscious implementations. Send a stable user identifier in the webhook, look up the current address in your application database, and skip the send when no eligible recipient exists.