From d0e2da6826ab069f77b6281aa988cf4f0f2afa4e Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Tue, 18 Nov 2025 21:52:21 -0800 Subject: [PATCH 1/3] Record lead commissions/workflows in attributeViaPromoCode --- .../webhook/checkout-session-completed.ts | 116 +++++++++++------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts b/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts index 2c0c82805f5..1aebf8b5eba 100644 --- a/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts +++ b/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts @@ -58,7 +58,6 @@ export async function checkoutSessionCompleted( let clickEvent: ClickEventTB | null = null; let leadEvent: LeadEventTB | undefined; let linkId: string | undefined; - let shouldSendLeadWebhook = true; /* for stripe checkout links: @@ -193,7 +192,6 @@ export async function checkoutSessionCompleted( }); if (promoCodeResponse) { ({ linkId, customer, clickEvent, leadEvent } = promoCodeResponse); - shouldSendLeadWebhook = false; } else { return `Failed to attribute via promotion code ${promotionCodeId}, skipping...`; } @@ -237,7 +235,6 @@ export async function checkoutSessionCompleted( }); if (promoCodeResponse) { ({ linkId, customer, clickEvent, leadEvent } = promoCodeResponse); - shouldSendLeadWebhook = false; } else { return `Failed to attribute via promotion code ${promotionCodeId}, skipping...`; } @@ -361,13 +358,6 @@ export async function checkoutSessionCompleted( id: link.id, }, data: { - // if the clickEvent variable exists, it means that a new lead was created - ...(clickEvent && { - leads: { - increment: 1, - }, - lastLeadAt: new Date(), - }), ...(firstConversionFlag && { conversions: { increment: 1, @@ -384,19 +374,19 @@ export async function checkoutSessionCompleted( include: includeTags, }), - // update workspace sales usage + // update workspace usage prisma.project.update({ where: { id: customer.projectId, }, data: { usage: { - increment: clickEvent ? 2 : 1, + increment: 1, }, }, }), - // update customer sales count + // update customer stats prisma.customer.update({ where: { id: customer.id, @@ -462,44 +452,12 @@ export async function checkoutSessionCompleted( programId: link.programId, eventType: "sale", }), - // same logic as lead.created webhook below: - // if the clickEvent variable exists and there was no existing customer before, - // we need to trigger the leadRecorded workflow - clickEvent && - !existingCustomer && - executeWorkflows({ - trigger: WorkflowTrigger.leadRecorded, - context: { - programId: link.programId, - partnerId: link.partnerId, - current: { - leads: 1, - }, - }, - }), ]), ); } waitUntil( (async () => { - // if the clickEvent variable exists and there was no existing customer before, - // we send a lead.created webhook - if (clickEvent && !existingCustomer && shouldSendLeadWebhook) { - await sendWorkspaceWebhook({ - trigger: "lead.created", - workspace, - data: transformLeadEventData({ - ...clickEvent, - eventName: "Checkout session completed", - link: linkUpdated, - customer, - partner: webhookPartner, - metadata: null, - }), - }); - } - // send workspace webhook await sendWorkspaceWebhook({ trigger: "sale.created", @@ -553,6 +511,7 @@ async function attributeViaPromoCode({ id: true, stripeConnectId: true, defaultProgramId: true, + webhookEnabled: true, }, }); @@ -638,6 +597,73 @@ async function attributeViaPromoCode({ await recordLead(leadEvent); + // record lead side effects (link stats, partner commissions, workflows, workspace webhook) + waitUntil( + (async () => { + const linkUpdated = await prisma.link.update({ + where: { + id: link.id, + }, + data: { + leads: { + increment: 1, + }, + lastLeadAt: new Date(), + }, + }); + + let webhookPartner: WebhookPartner | undefined; + if (link.programId && link.partnerId) { + await Promise.allSettled([ + createPartnerCommission({ + event: "lead", + programId: link.programId, + partnerId: link.partnerId, + linkId: link.id, + eventId: leadEvent.event_id, + customerId: customer.id, + quantity: 1, + context: { + customer: { + country: customer.country, + }, + }, + }).then((res) => { + webhookPartner = res.webhookPartner; + }), + + executeWorkflows({ + trigger: WorkflowTrigger.leadRecorded, + context: { + programId: link.programId, + partnerId: link.partnerId, + current: { + leads: 1, + }, + }, + }), + syncPartnerLinksStats({ + partnerId: link.partnerId, + programId: link.programId, + eventType: "lead", + }), + ]); + } + await sendWorkspaceWebhook({ + trigger: "lead.created", + workspace, + data: transformLeadEventData({ + ...leadEvent, + eventName: "Checkout session completed", + link: linkUpdated, + customer, + partner: webhookPartner, + metadata: null, + }), + }); + })(), + ); + return { linkId, customer, From 3ce2c3051135163ebd9cc02eb9f0934ab4da08f5 Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Tue, 18 Nov 2025 22:02:40 -0800 Subject: [PATCH 2/3] incrementLinkLeads --- .../webhook/checkout-session-completed.ts | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts b/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts index 1aebf8b5eba..114a6469e4d 100644 --- a/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts +++ b/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts @@ -146,6 +146,7 @@ export async function checkoutSessionCompleted( if (!existingCustomer) { await recordLead(leadEvent); + waitUntil(incrementLinkLeads(clickEvent.link_id)); } linkId = clickEvent.link_id; @@ -600,17 +601,7 @@ async function attributeViaPromoCode({ // record lead side effects (link stats, partner commissions, workflows, workspace webhook) waitUntil( (async () => { - const linkUpdated = await prisma.link.update({ - where: { - id: link.id, - }, - data: { - leads: { - increment: 1, - }, - lastLeadAt: new Date(), - }, - }); + const linkUpdated = await incrementLinkLeads(link.id); let webhookPartner: WebhookPartner | undefined; if (link.programId && link.partnerId) { @@ -671,3 +662,17 @@ async function attributeViaPromoCode({ leadEvent, }; } + +async function incrementLinkLeads(linkId: string) { + return await prisma.link.update({ + where: { + id: linkId, + }, + data: { + leads: { + increment: 1, + }, + lastLeadAt: new Date(), + }, + }); +} From c67c4e1e5cea7f5fa214b9c2198bcaf6d29344f9 Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Tue, 18 Nov 2025 22:03:19 -0800 Subject: [PATCH 3/3] includeTags --- .../stripe/integration/webhook/checkout-session-completed.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts b/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts index 114a6469e4d..ab8e52c20ae 100644 --- a/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts +++ b/apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts @@ -664,7 +664,7 @@ async function attributeViaPromoCode({ } async function incrementLinkLeads(linkId: string) { - return await prisma.link.update({ + return prisma.link.update({ where: { id: linkId, }, @@ -674,5 +674,6 @@ async function incrementLinkLeads(linkId: string) { }, lastLeadAt: new Date(), }, + include: includeTags, }); }