Skip to main content
If you already use Segment as your event pipeline, this is the lowest-effort way to put outcome data behind your AI conversations. Every analytics.track(...) call you’ve already written keeps flowing to your existing destinations and reaches Greenflash, where it’s mapped into a business event and used to tell which conversation patterns lead to real outcomes.

How it works

Segment has a built-in Webhooks destination that POSTs each message to one or more URLs. Greenflash gives you a per-product URL to add as one of those URLs. The flow:
  1. Your app calls analytics.track('Order Completed', { revenue: 49 }) (or any other event).
  2. Segment routes the message to its configured destinations, including Greenflash.
  3. Greenflash authenticates the URL token, maps the Segment message to a Greenflash business event, infers positive / negative / neutral influence, and attaches it to the product you connected.
  4. The next conversation analysis Greenflash runs has those events as outcome context.
Your Segment instrumentation stays the source of truth. Greenflash sees a copy of the messages your existing destinations already see.

Before you start

  • A Greenflash product to enrich with Segment events. Create one under Settings → Products if you don’t have one.
  • Owner / source admin access in Segment so you can add a destination to a source.
  • (Optional) Segment Functions or a Cloud Mode destination if you want to batch messages before forwarding.

Setup

1. Create the connection in Greenflash

  1. Open Settings → Connect → Events in the Greenflash web app.
  2. Click Connect on the Segment card.
  3. Pick the product the stream should feed and click Create source.
  4. Copy the destination URL. Greenflash shows it once. If you lose it, rotate the token from the connection row and update Segment.
The URL is the secret. Store it in Segment and your secrets manager — anyone who has it can write events into the connected product.

2. Add the Webhook destination in Segment

  1. In Segment, open the source you want to forward from and go to Destinations → Add Destination.
  2. Search for Webhooks (the built-in webhook destination) and add it.
  3. In the destination settings, paste the Greenflash URL into one of the Webhook URL slots. Leave the method as POST.
  4. Under the destination’s event settings, configure which message types forward. We recommend forwarding only track events — Greenflash drops identify, group, and alias server-side because they describe user traits rather than business actions, so filtering them at the Segment side saves request volume. page and screen events are accepted if you want them.
  5. Enable the destination. The connection row in Greenflash flips to Active on the first event.
Multiple sources? Add the same Webhook URL to every source whose events you want to forward. Or set up one Greenflash connection per product, each with its own URL, and wire them to different Segment sources.

3. Send a test event

Fire a track event from your app, replay one from the Segment Source debugger, or post directly to the URL to confirm the round trip:
curl -X POST "<YOUR_GREENFLASH_URL>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "track",
    "event": "Order Completed",
    "userId": "user_test_123",
    "messageId": "msg_test_001",
    "timestamp": "2026-05-18T12:00:00Z",
    "properties": {
      "revenue": 49.0,
      "plan": "pro"
    }
  }'
A successful request returns:
{ "received": 1, "accepted": 1, "dropped": 0 }
If received is 0, the payload didn’t match the Segment message shape — check your Segment Function output or webhook template.

How events are mapped

Greenflash applies these defaults to every Segment track message:
Segment fieldGreenflash field
eventeventType
userId (falls back to anonymousId)externalUserId
timestampeventAt
messageIdinsertId (prefixed segment:) — used for idempotency
properties.revenue (or properties.price * properties.quantity)value (with valueType: currency)
properties (entire object)properties (preserved verbatim)

Identity hints (used for user & organization attribution)

Greenflash reads a handful of fields from context.traits / traits / properties to attach the event to the right user and organization. Sending these means Greenflash can auto-create the user / org if it hasn’t seen them yet.
Segment fieldGreenflash field
context.traits.email (or traits.email, or properties.email)userHints.email
context.traits.name (or traits.name, or properties.name)userHints.name
context.groupId (or traits.organization_id, or properties.organization_id)externalOrganizationId
traits.organization_name / traits.company (or the same under properties)organizationHints.name

Attribution: how events tie to users, orgs, and conversations

Users. Events match an existing Greenflash user by externalUserId (= Segment userId, falling back to anonymousId) first, then by email. If no match exists and the message carries an email, Greenflash upserts a new user automatically. Anonymous events (no email) keep userId = null rather than creating a row per anon ID. Organizations. Same idea, scoped to externalOrganizationId. Org upsert only runs when context.groupId (or equivalent) is present — never by name. Conversations. Add gf_conversation_id to properties to attach the event to a specific Greenflash conversation. Otherwise, the event auto-attaches to the user’s most-recent conversation in this product within the last 15 minutes; if that doesn’t match, conversationId stays null.
Users and orgs auto-created from analytics carry properties.created_from = 'analytics' and properties.source = 'segment'. When you later identify them via the Greenflash SDK using the same externalUserId, the existing row is reused.

Other Segment message types

  • page / screen — accepted. The name field becomes the Greenflash event name; if no name is set, the type itself ('page' or 'screen') is used.
  • identify, group, alias — silently dropped. These describe user properties, not behaviors. Move the trait change into a track call if you want it in Greenflash.

Influence (positive / negative / neutral)

  • Positive when revenue > 0, or the event name matches signup, signed_up, upgrade, purchase, subscribe, convert, activate, complete, or order_completed.
  • Negative when revenue < 0, or the event name matches churn, cancel, unsubscribe, refund, downgrade, delete, failed, or error.
  • Neutral otherwise.
Matching is case-insensitive and works across snake_case, kebab-case, PascalCase, and the Title Case Segment conventionally uses (Order Completed, Signed Up).

Batched payloads

Segment Functions and some Cloud Mode destinations send { batch: [{ ... }, { ... }] } instead of one message per request. Greenflash accepts both shapes and ingests one event per message in the batch.

Override the defaults

Add any of these magic properties inside the event’s properties and Greenflash will respect them — no Greenflash-side configuration needed.
PropertyEffect
gf_event_typeOverride the Greenflash event name (the original Segment name stays in properties)
gf_influenceForce positive, negative, or neutral
gf_quality_impact_scoreNumeric override from -1.0 to 1.0 — fine-grained weight
gf_valueOverride the event value (string or number)
gf_value_typeOne of currency, numeric, text, boolean
gf_conversation_idAttach this event to a specific Greenflash conversation (externalConversationId)
Example:
analytics.track('Workspace Activated', {
  workspace_id: 'ws_42',
  gf_influence: 'positive',
  gf_quality_impact_score: 0.7,
});

Filtering: what to forward

Filter on the Segment side, not inside Greenflash. Segment was built around filtering at the source — destination event filters, source schema controls, Destination Functions — all of which are more expressive than anything we’d build into Greenflash. We deliberately don’t expose a denylist UI: the only Greenflash-side knob is the magic-property overrides above, applied per event in properties. Some practical choices:
  • Destination event filters (built-in, free tier) — allow specific track event names, drop the rest. Set once, no code.
  • Source schema controls (Business plan) — block events at the source so they never reach any destination.
  • Destination Functions — write a small JS function that decides per message whether to forward, or rewrites payloads (great for adding gf_* overrides).
Forward Signed Up, Trial Started, Activated, Subscription Started, Subscription Upgraded, Subscription Cancelled. Greenflash infers influence from these names automatically.
Forward Order Completed, Order Refunded, Cart Abandoned. Include revenue or both price and quantity so Greenflash can value-weight outcomes. Refunds should arrive with negative revenue.
Don’t want to disable the Segment destination for a short outage or experiment? Pause the connection from its row in Settings → Connect → Events. The Greenflash receiver returns 204 while paused so Segment stops retrying. Re-enable to resume — no token rotation, no Segment change.

Response codes & limits

CodeMeaning
200Payload received and processed. Body includes received, accepted, dropped.
204Connection is paused or disconnected in Greenflash. Returned deliberately so Segment stops retrying.
400Payload didn’t match the Segment message schema, or JSON was invalid.
401URL token is invalid, the connection has been rotated, or the optional shared secret header is missing / wrong.
404Provider segment of the URL is wrong (e.g. you pointed Segment at the /posthog/ URL).
413More than 1,000 messages in a single batch. Split the batch on the Segment side.
500Greenflash couldn’t look up the connection. Safe to retry.

Security

The URL is path-authenticated: the token segment is generated per connection, stored only as a scrypt hash, and verified in constant time on every request. Greenflash does not verify Segment’s native X-Webhook-Signature HMAC. The destination’s signing key would have to be configured per-connection, and the URL token already provides a stronger boundary. For defense in depth, you can configure a shared secret alongside the URL token. The secret is communicated to Greenflash on every request via a custom HTTP header — there’s no body field or query parameter.
  1. In Segment, open your Webhook destination and go to Headers.
  2. Add a header with name x-greenflash-secret and value <your-secret> (any string you pick, 8+ characters).
  3. Provide the same secret to Greenflash on the connection so we can match it.
Once configured, Greenflash rejects any request whose x-greenflash-secret header is missing or doesn’t match with 401. Rotating the URL invalidates the previous token immediately. Events sent to the old URL return 401. Update the URL on the Segment Webhook destination to resume delivery.

Troubleshooting

  • The destination is enabled and the source is firing — check the Segment Source debugger for live events.
  • The URL has no trailing slash.
  • You pasted the URL into the right Webhook URL slot (the destination supports up to five).
  • Your destination’s event filter isn’t excluding everything.
That’s intentional. Greenflash only ingests track, page, and screen — trait updates are dropped. Move the trait change into a track call (e.g. analytics.track('Profile Updated', { plan: 'pro' })) if you want it in Greenflash.
The batch contained more than 1,000 messages. Chunk the batch on the Segment Function side — Greenflash drops the entire batch above the cap rather than partially ingesting it.
Open the Segment row under Settings → Connect → Events and click Rotate URL. The old token is invalidated immediately. Paste the new URL into the Segment Webhook destination.
Greenflash deduplicates on the segment:<messageId> insert id. As long as Segment sends a stable messageId per message, retries won’t create duplicates.

Next

How Greenflash uses events

What changes in your analyses once events start flowing.

Public Events API

Skip the webhook and post events directly if you want full control.