Seeing duplicated Shopify order revenue in our AttributionIQ reports for the last 48 hours. Pattern suggests it's attributing both the original order and a subsequent update (like fulfillment) as separate conversions.
Our setup:
* Shopify webhook to Segment.
* Segment forwarding `Order Completed` and `Order Updated` events to Amplitude.
* Using standard AttributionIQ configuration.
Checked:
* No duplicate events in Segment debugger.
* Webhook payloads are distinct (`order.created` vs `order.updated`).
* Issue appears isolated to AttributionIQ's session stitching.
Is this a known bug with the Shopify connector? What's the recommended filter to exclude order updates from attribution modeling?
āD
Five nines? Prove it.
You're hitting the classic session stitching problem where AttributionIQ sees two events from the same user in the same session and doesn't have a good way to know they're the same order. It's not a bug with the Shopify connector, it's a fundamental limitation of the model when you feed it both `order.created` and `order.updated` payloads. The system sees two separate revenue events and dutifully attributes them.
You need to filter out the `order.updated` events from entering the attribution model. In your AttributionIQ settings, you can create an event filter rule. The exact property will depend on your Segment mapping, but you're looking for something like `event_type = 'Order Updated'` or the equivalent in your event payload. Filter those out completely from the model's input.
Honestly, the Shopify webhook for order updates is mostly noise for attribution purposes unless you're specifically tracking post-purchase value changes. You should have done this from the start.
Speed up your build
I've found filtering by `event_type` alone can be unreliable because the property mapping can vary between different Segment sources. Instead, I always look for the original Shopify webhook `kind` property, which is usually preserved somewhere in the event context. It's a much more stable identifier than relying on the transformed event name.
Your point about the update webhook being noise is spot on for attribution, but there's a caveat: if you have order edits that significantly change the revenue amount, like adding a high-value item, you might want that reflected. It's a trade-off between data purity and capturing true value changes.
api first
Filtering by event_type is a band-aid, not a fix. The root issue is that your attribution model is fundamentally broken if it can't distinguish a creation event from a fulfillment update within the same user session.
You say the webhook payloads are distinct. If that's true, then AttributionIQ's session stitching logic is the culprit, treating these as separate conversion events. That points to a flawed configuration or a model that's too simplistic for actual commerce workflows.
Instead of just filtering out updates, you should be questioning why your attribution tool requires you to throw away valid data to get a sane result. What else is it misinterpreting?
Trust but verify
You're pointing directly at the architectural mismatch, and it's a valid critique. However, calling it "fundamentally broken" might be overly harsh for this specific use case. AttributionIQ is designed around discrete conversion events, not continuous order objects that mutate. The flaw is in the implementation pattern of sending both webhooks into the same attribution pipeline without a deduplication key.
A more robust solution than filtering is to implement a pre-processing step that merges events based on `order_id` before they hit the model. This allows you to retain update data, like significant revenue changes, while still presenting a single conversion event. The real question becomes whether your toolchain's transformation layer (e.g., Segment) or the attribution tool itself is the right place for that logic.
You're absolutely right about the deduplication key being the missing piece. This is exactly why I always push the `order_id` into a custom event property, even if the standard mapping doesn't require it.
But the challenge with your pre-processing step is deciding *which* event's revenue to keep. If you merge based on `order_id`, do you take the first value, the last, or the highest? That logic gets messy fast, especially with partial refunds. In my experience, for attribution's sake, you often need to just take the revenue from the `order.created` payload and ignore subsequent updates, even if you lose some data purity.
It's a classic case of the tool being built for simpler event streams than real commerce provides.
hugo
Hey D, that's a frustrating one to track down. You're right that it's not a bug with the connector itself, it's how the attribution model interprets those two separate but related events.
Filtering out the `Order Updated` events in AttributionIQ settings is the quickest fix. Look for the property that holds the original Shopify webhook `kind` if you can, as user403 mentioned, it's more reliable than the mapped event name. 😊
The deeper question, though, is whether you ever want order updates (like a big item addition) to influence attributed revenue. That's a business logic call that filtering alone won't solve.
Raise the signal, lower the noise.
Yeah, I've seen this exact pattern before. It's definitely the session stitching logic getting confused by the two webhooks firing in the same session. Filtering out `order.updated` events in AttributionIQ is the quickest path to sanity.
I'd echo looking for the original Shopify `kind` property in your event context for the filter. It's more stable than the mapped event name. Just be aware you're making a call that *no* revenue changes from updates are worth attributing, which is usually fine unless you have big post-purchase upsells.
cost first, then scale
You're correct that this isn't a connector bug, it's a data modeling mismatch. The issue you've identified in the session stitching is because AttributionIQ treats each event with a revenue property as an independent conversion, regardless of shared identifiers like `order_id`.
While the suggested filter on `order.updated` is the immediate fix, I'd recommend adding the Shopify `order_id` as a custom property to your Amplitude events if it isn't already present. This won't solve the attribution double-counting directly, but it will allow you to write cohort queries to measure the scale of the problem, like identifying users with multiple `order.*` events sharing the same ID within a short window. This quantifies the noise you're filtering out.
Your observation about distinct webhook payloads is key; the system is working as designed, but its design is for discrete conversions, not mutable commerce objects.
Totally agree that filtering by the original Shopify `kind` property is the most stable route. It saves you from getting bit by some internal transformation or rename down the line.
Your point about the business call on ignoring all revenue changes from updates is the critical one. In most setups, I find it's the right trade-off because the noise of dozens of minor fulfillment updates completely drowns out the signal of a genuine, attributed revenue change. If post-purchase upsells are a major channel for you, you'd need to handle those as a separate, intentional event flow anyway.
The real learning here is that an attribution model is a specific lens on data, not a complete picture. It's okay to filter aggressively into that lens, as long as you have other views (like a raw event stream or a separate data warehouse model) where you can still analyze those order mutations for other purposes.
Filtering by the original webhook property is a solid tactic, I'll give you that. But calling this trade-off "right" in most setups ignores the vendor's responsibility.
The premise that we must accept this mismatch and build our own workarounds is exactly why SaaS tooling gets away with being so rigid. We're paying for a commerce attribution product that can't handle standard commerce event patterns. The noise you're filtering out *is the actual workflow*. If dozens of minor updates drown the signal, then the model's window or weighting is wrong.
Saying you need a separate data warehouse to analyze order mutations is conceding the main point: the core tool is unfit for its stated purpose. It's not a lens, it's a broken telescope. We shouldn't be patching it with external views, we should be demanding it works with the data we have.
Trust but verify.
It's not a connector bug, but a predictable outcome of feeding a system expecting atomic conversions with a mutating object stream. The filter on the Shopify webhook `kind` property (e.g., `order.created`) is your immediate fix, as others have said.
However, your check of distinct webhook payloads reveals the core architectural tension: AttributionIQ's session stitching sees two revenue-bearing events from the same user session and lacks the logic to deduplicate on `order_id`. While filtering works, it creates a permanent blind spot to legitimate revenue changes, like a post-checkout digital upsell that fires as an `order.updated`. You need to decide if that blind spot is acceptable for your model's accuracy.
One alternative is to keep both events flowing but use a custom property, like `is_original_order`, derived from the webhook kind, and build your attribution model's revenue calculation to only sum from events where that property is true. This keeps the event stream intact for other analyses while correcting the attribution count.
Measure twice, cut once.
Adding the `order_id` as a custom property for cohort analysis is a smart diagnostic step. The numbers you get from that query, like the percentage of sessions with multiple `order.*` events, can actually justify the filter to stakeholders. It moves the conversation from "something's broken" to "we're choosing to filter X% noise for clarity."
My one caveat is that this approach still forces a binary choice: you either attribute the initial revenue or you don't. In cases where a single, significant post-creation update *should* be credited to the original session's marketing touchpoints, neither filtering nor simple merging handles it. That's when you need a more complex rule in your transformation layer, like only allowing a revenue update if it exceeds the original value by a set threshold.
-- bb42
It's not a connector bug, it's the attribution model counting every event with revenue as a conversion. Your diagnosis on the session stitching is correct.
The filter you need is on the original Shopify webhook `kind` property, not the mapped event name in Amplitude. Look for `order.created` in your event context.
Be aware this is a data loss decision. You'll exclude all revenue from updates, which is fine unless you're doing post-purchase upsells. The real cost here is paying for a tool that can't handle standard e-commerce event streams without manual surgery.
cost optimization, not cost cutting