feat: store ads clickid when creating an account (#25763)
* feat: store ads clickid when creating an account * fix: type check * fix: google campaignId not being added to stripe * remove tracking in stripe app
This commit is contained in:
+4
-1
@@ -509,4 +509,7 @@ SEED_PLATFORM_OAUTH_CLIENT_SECRET=
|
||||
ENABLE_ASYNC_TASKER="false" # set to "true" to enable
|
||||
TRIGGER_SECRET_KEY=
|
||||
TRIGGER_API_URL=https://api.trigger.dev
|
||||
TRIGGER_DEV_PROJECT_REF=
|
||||
TRIGGER_DEV_PROJECT_REF=
|
||||
|
||||
GOOGLE_ADS_ENABLED=1 # To enable Google Ads tracking (gclid)
|
||||
LINKEDIN_ADS_ENABLED=1 # To enable LinkedIn Ads tracking (li_fat_id)
|
||||
|
||||
@@ -2,12 +2,14 @@ import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { getServerSession } from "@calcom/feature-auth/lib/getServerSession";
|
||||
import { getOptions } from "@calcom/feature-auth/lib/next-auth-options";
|
||||
import { getTrackingFromCookies } from "@calcom/lib/tracking";
|
||||
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const session = await getServerSession({
|
||||
req: context.req,
|
||||
authOptions: getOptions({
|
||||
getDubId: () => context.req.cookies.dub_id || context.req.cookies.dclid,
|
||||
getTrackingData: () => getTrackingFromCookies(context.req.cookies),
|
||||
}),
|
||||
});
|
||||
// Disable this check if we ever make this self serve.
|
||||
|
||||
@@ -2,9 +2,17 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import NextAuth from "next-auth";
|
||||
|
||||
import { getOptions } from "@calcom/features/auth/lib/next-auth-options";
|
||||
import { getTrackingFromCookies } from "@calcom/lib/tracking";
|
||||
|
||||
// pass req to NextAuth: https://github.com/nextauthjs/next-auth/discussions/469
|
||||
const handler = (req: NextApiRequest, res: NextApiResponse) =>
|
||||
NextAuth(req, res, getOptions({ getDubId: () => req.cookies.dub_id || req.cookies.dclid }));
|
||||
NextAuth(
|
||||
req,
|
||||
res,
|
||||
getOptions({
|
||||
getDubId: () => req.cookies.dub_id || req.cookies.dclid,
|
||||
getTrackingData: () => getTrackingFromCookies(req.cookies),
|
||||
})
|
||||
);
|
||||
|
||||
export default handler;
|
||||
|
||||
@@ -5,7 +5,6 @@ import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/li
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { checkPremiumUsername } from "@calcom/features/ee/common/lib/checkPremiumUsername";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getTrackingFromCookies } from "@calcom/lib/tracking";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
@@ -40,8 +39,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
return;
|
||||
}
|
||||
|
||||
const tracking = getTrackingFromCookies(req.cookies);
|
||||
|
||||
const return_url = `${WEBAPP_URL}/api/integrations/stripepayment/paymentCallback?checkoutSessionId={CHECKOUT_SESSION_ID}&callbackUrl=${callbackUrl}`;
|
||||
const createSessionParams: Stripe.Checkout.SessionCreateParams = {
|
||||
mode: "subscription",
|
||||
@@ -58,8 +55,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
metadata: {
|
||||
userId: userId.toString(),
|
||||
intentUsername,
|
||||
...(tracking?.googleAds?.gclid && { gclid: tracking.googleAds.gclid, campaignId: tracking.googleAds.campaignId }),
|
||||
...(tracking?.linkedInAds?.liFatId && { liFatId: tracking.linkedInAds.liFatId, linkedInCampaignId: tracking.linkedInAds?.campaignId }),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ import GoogleProvider from "next-auth/providers/google";
|
||||
import { updateProfilePhotoGoogle } from "@calcom/app-store/_utils/oauth/updateProfilePhotoGoogle";
|
||||
import GoogleCalendarService from "@calcom/app-store/googlecalendar/lib/CalendarService";
|
||||
import { LicenseKeySingleton } from "@calcom/ee/common/server/LicenseKeyService";
|
||||
import { getBillingProviderService } from "@calcom/features/ee/billing/di/containers/Billing";
|
||||
import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository";
|
||||
import type { TrackingData } from "@calcom/lib/tracking";
|
||||
import { DeploymentRepository } from "@calcom/features/ee/deployment/repositories/DeploymentRepository";
|
||||
import createUsersAndConnectToOrg from "@calcom/features/ee/dsync/lib/users/createUsersAndConnectToOrg";
|
||||
import ImpersonationProvider from "@calcom/features/ee/impersonation/lib/ImpersonationProvider";
|
||||
@@ -456,9 +458,12 @@ const mapIdentityProvider = (providerName: string) => {
|
||||
|
||||
export const getOptions = ({
|
||||
getDubId,
|
||||
getTrackingData,
|
||||
}: {
|
||||
/** so we can extract the Dub cookie in both pages and app routers */
|
||||
getDubId: () => string | undefined;
|
||||
/** Ad tracking data for Stripe customer metadata */
|
||||
getTrackingData: () => TrackingData;
|
||||
}): AuthOptions => ({
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
@@ -596,14 +601,14 @@ export const getOptions = ({
|
||||
org:
|
||||
profileOrg && !profileOrg.isPlatform
|
||||
? {
|
||||
id: profileOrg.id,
|
||||
name: profileOrg.name,
|
||||
slug: profileOrg.slug ?? profileOrg.requestedSlug ?? "",
|
||||
logoUrl: profileOrg.logoUrl,
|
||||
fullDomain: getOrgFullOrigin(profileOrg.slug ?? profileOrg.requestedSlug ?? ""),
|
||||
domainSuffix: subdomainSuffix(),
|
||||
role: orgRole as MembershipRole, // It can't be undefined if we have a profileOrg
|
||||
}
|
||||
id: profileOrg.id,
|
||||
name: profileOrg.name,
|
||||
slug: profileOrg.slug ?? profileOrg.requestedSlug ?? "",
|
||||
logoUrl: profileOrg.logoUrl,
|
||||
fullDomain: getOrgFullOrigin(profileOrg.slug ?? profileOrg.requestedSlug ?? ""),
|
||||
domainSuffix: subdomainSuffix(),
|
||||
role: orgRole as MembershipRole, // It can't be undefined if we have a profileOrg
|
||||
}
|
||||
: null,
|
||||
} as JWT;
|
||||
};
|
||||
@@ -1066,11 +1071,12 @@ export const getOptions = ({
|
||||
const { orgUsername, orgId } = await checkIfUserShouldBelongToOrg(idP, user.email);
|
||||
|
||||
try {
|
||||
const newUsername = orgId ? slugify(orgUsername) : usernameSlug(user.name);
|
||||
const newUser = await prisma.user.create({
|
||||
data: {
|
||||
// Slugify the incoming name and append a few random characters to
|
||||
// prevent conflicts for users with the same name.
|
||||
username: orgId ? slugify(orgUsername) : usernameSlug(user.name),
|
||||
username: newUsername,
|
||||
emailVerified: new Date(Date.now()),
|
||||
name: user.name,
|
||||
...(user.image && { avatarUrl: user.image }),
|
||||
@@ -1094,6 +1100,40 @@ export const getOptions = ({
|
||||
);
|
||||
await calcomAdapter.linkAccount(linkAccountNewUserData);
|
||||
|
||||
waitUntil(
|
||||
(async () => {
|
||||
try {
|
||||
const tracking = getTrackingData();
|
||||
const billingService = getBillingProviderService();
|
||||
const customer = await billingService.createCustomer({
|
||||
email: newUser.email,
|
||||
metadata: {
|
||||
email: newUser.email,
|
||||
username: newUser.username ?? newUsername,
|
||||
...(tracking.googleAds?.gclid && {
|
||||
gclid: tracking.googleAds.gclid,
|
||||
campaignId: tracking.googleAds.campaignId,
|
||||
}),
|
||||
...(tracking.linkedInAds?.liFatId && {
|
||||
liFatId: tracking.linkedInAds.liFatId,
|
||||
linkedInCampaignId: tracking.linkedInAds.campaignId,
|
||||
}),
|
||||
},
|
||||
});
|
||||
await prisma.user.update({
|
||||
where: { id: newUser.id },
|
||||
data: {
|
||||
metadata: {
|
||||
stripeCustomerId: customer.stripeCustomerId,
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
log.error("Failed to create Stripe customer with tracking", err);
|
||||
}
|
||||
})()
|
||||
);
|
||||
|
||||
if (account.twoFactorEnabled) {
|
||||
return loginWithTotp(newUser.email);
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { CustomNextApiHandler } from "@calcom/lib/server/username";
|
||||
import { usernameHandler } from "@calcom/lib/server/username";
|
||||
import { getTrackingFromCookies } from "@calcom/lib/tracking";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { CreationSource } from "@calcom/prisma/enums";
|
||||
import { IdentityProvider } from "@calcom/prisma/enums";
|
||||
@@ -105,13 +106,24 @@ const handler: CustomNextApiHandler = async (body, usernameStatus) => {
|
||||
username = usernameAndEmailValidation.username;
|
||||
}
|
||||
|
||||
// Create the customer in Stripe
|
||||
// Create the customer in Stripe with ad tracking metadata
|
||||
const cookieStore = await cookies();
|
||||
const cookiesObj = Object.fromEntries(cookieStore.getAll().map((c) => [c.name, c.value]));
|
||||
const tracking = getTrackingFromCookies(cookiesObj);
|
||||
|
||||
const customer = await billingService.createCustomer({
|
||||
email,
|
||||
metadata: {
|
||||
email /* Stripe customer email can be changed, so we add this to keep track of which email was used to signup */,
|
||||
username,
|
||||
...(tracking.googleAds?.gclid && {
|
||||
gclid: tracking.googleAds.gclid,
|
||||
campaignId: tracking.googleAds.campaignId,
|
||||
}),
|
||||
...(tracking.linkedInAds?.liFatId && {
|
||||
liFatId: tracking.linkedInAds.liFatId,
|
||||
linkedInCampaignId: tracking.linkedInAds.campaignId,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -24,14 +24,14 @@ export function getTrackingFromCookies(cookies?: NextApiRequest["cookies"]): Tra
|
||||
if (process.env.GOOGLE_ADS_ENABLED === "1" && cookies.gclid) {
|
||||
tracking.googleAds = {
|
||||
gclid: cookies.gclid,
|
||||
...(cookies.gad_campaignid && { campaignId: cookies.gad_campaignid }),
|
||||
...(cookies.gad_campaignId && { campaignId: cookies.gad_campaignId }),
|
||||
};
|
||||
}
|
||||
|
||||
if (process.env.LINKEDIN_ADS_ENABLED === "1" && cookies.li_fat_id) {
|
||||
tracking.linkedInAds = {
|
||||
liFatId: cookies.li_fat_id,
|
||||
...(cookies.li_campaignid && { campaignId: cookies.li_campaignid }),
|
||||
...(cookies.li_campaignId && { campaignId: cookies.li_campaignId }),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user