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:- Your app calls
analytics.track('Order Completed', { revenue: 49 })(or any other event). - Segment routes the message to its configured destinations, including Greenflash.
- 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.
- The next conversation analysis Greenflash runs has those events as outcome context.
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
- Open Settings → Connect → Events in the Greenflash web app.
- Click Connect on the Segment card.
- Pick the product the stream should feed and click Create source.
- Copy the destination URL. Greenflash shows it once. If you lose it, rotate the token from the connection row and update Segment.
2. Add the Webhook destination in Segment
- In Segment, open the source you want to forward from and go to Destinations → Add Destination.
- Search for Webhooks (the built-in
webhookdestination) and add it. - In the destination settings, paste the Greenflash URL into one of the Webhook URL slots. Leave the method as
POST. - Under the destination’s event settings, configure which message types forward. We recommend forwarding only
trackevents — Greenflash dropsidentify,group, andaliasserver-side because they describe user traits rather than business actions, so filtering them at the Segment side saves request volume.pageandscreenevents are accepted if you want them. - 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 atrack event from your app, replay one from the Segment Source debugger, or post directly to the URL to confirm the round trip:
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 Segmenttrack message:
| Segment field | Greenflash field |
|---|---|
event | eventType |
userId (falls back to anonymousId) | externalUserId |
timestamp | eventAt |
messageId | insertId (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 fromcontext.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 field | Greenflash 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 byexternalUserId (= 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 carryproperties.created_from = 'analytics'andproperties.source = 'segment'. When you later identify them via the Greenflash SDK using the sameexternalUserId, the existing row is reused.
Other Segment message types
page/screen— accepted. Thenamefield 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 atrackcall if you want it in Greenflash.
Influence (positive / negative / neutral)
- Positive when
revenue > 0, or the event name matchessignup,signed_up,upgrade,purchase,subscribe,convert,activate,complete, ororder_completed. - Negative when
revenue < 0, or the event name matcheschurn,cancel,unsubscribe,refund,downgrade,delete,failed, orerror. - Neutral otherwise.
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’sproperties and Greenflash will respect them — no Greenflash-side configuration needed.
| Property | Effect |
|---|---|
gf_event_type | Override the Greenflash event name (the original Segment name stays in properties) |
gf_influence | Force positive, negative, or neutral |
gf_quality_impact_score | Numeric override from -1.0 to 1.0 — fine-grained weight |
gf_value | Override the event value (string or number) |
gf_value_type | One of currency, numeric, text, boolean |
gf_conversation_id | Attach this event to a specific Greenflash conversation (externalConversationId) |
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 inproperties.
Some practical choices:
- Destination event filters (built-in, free tier) — allow specific
trackevent 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).
SaaS conversion
SaaS conversion
Forward
Signed Up, Trial Started, Activated, Subscription Started, Subscription Upgraded, Subscription Cancelled. Greenflash infers influence from these names automatically.E-commerce
E-commerce
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.Hard-mute a stream temporarily
Hard-mute a stream temporarily
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
| Code | Meaning |
|---|---|
200 | Payload received and processed. Body includes received, accepted, dropped. |
204 | Connection is paused or disconnected in Greenflash. Returned deliberately so Segment stops retrying. |
400 | Payload didn’t match the Segment message schema, or JSON was invalid. |
401 | URL token is invalid, the connection has been rotated, or the optional shared secret header is missing / wrong. |
404 | Provider segment of the URL is wrong (e.g. you pointed Segment at the /posthog/ URL). |
413 | More than 1,000 messages in a single batch. Split the batch on the Segment side. |
500 | Greenflash 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 ascrypt 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.
- In Segment, open your Webhook destination and go to Headers.
- Add a header with name
x-greenflash-secretand value<your-secret>(any string you pick, 8+ characters). - Provide the same secret to Greenflash on the connection so we can match it.
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
Connection still says ''Awaiting first event''
Connection still says ''Awaiting first event''
- 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.
`identify` / `group` events not appearing
`identify` / `group` events not appearing
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.Getting 413 errors from batched Functions
Getting 413 errors from batched Functions
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.
Lost the URL
Lost the URL
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.
Duplicate events
Duplicate events
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.

