feat: moving to dub partners

This commit is contained in:
Nevo David 2025-12-29 02:11:40 +07:00
parent e5a4c558dd
commit 00caa7ddc4
11 changed files with 80 additions and 47 deletions

View File

@ -13,7 +13,7 @@ import { VariableContextComponent } from '@gitroom/react/helpers/variable.contex
import { Fragment } from 'react';
import { PHProvider } from '@gitroom/react/helpers/posthog';
import UtmSaver from '@gitroom/helpers/utils/utm.saver';
import { ToltScript } from '@gitroom/frontend/components/layout/tolt.script';
import { DubAnalytics } from '@gitroom/frontend/components/layout/dubAnalytics';
import { FacebookComponent } from '@gitroom/frontend/components/layout/facebook.component';
import { headers } from 'next/headers';
import { headerName } from '@gitroom/react/translation/i18n.config';
@ -61,7 +61,7 @@ export default async function AppLayout({ children }: { children: ReactNode }) {
oauthLogoUrl={process.env.NEXT_PUBLIC_POSTIZ_OAUTH_LOGO_URL!}
oauthDisplayName={process.env.NEXT_PUBLIC_POSTIZ_OAUTH_DISPLAY_NAME!}
uploadDirectory={process.env.NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY!}
tolt={process.env.NEXT_PUBLIC_TOLT!}
dub={!!process.env.STRIPE_PUBLISHABLE_KEY}
facebookPixel={process.env.NEXT_PUBLIC_FACEBOOK_PIXEL!}
telegramBotName={process.env.TELEGRAM_BOT_NAME!}
neynarClientId={process.env.NEYNAR_CLIENT_ID!}
@ -82,7 +82,7 @@ export default async function AppLayout({ children }: { children: ReactNode }) {
<SentryComponent>
{/*<SetTimezone />*/}
<HtmlComponent />
<ToltScript />
<DubAnalytics />
<FacebookComponent />
<Plausible
domain={!!process.env.IS_GENERAL ? 'postiz.com' : 'gitroom.com'}

View File

@ -41,7 +41,7 @@ export default async function AppLayout({ children }: { children: ReactNode }) {
oauthLogoUrl={process.env.NEXT_PUBLIC_POSTIZ_OAUTH_LOGO_URL!}
oauthDisplayName={process.env.NEXT_PUBLIC_POSTIZ_OAUTH_DISPLAY_NAME!}
uploadDirectory={process.env.NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY!}
tolt={process.env.NEXT_PUBLIC_TOLT!}
dub={false}
facebookPixel={process.env.NEXT_PUBLIC_FACEBOOK_PIXEL!}
telegramBotName={process.env.TELEGRAM_BOT_NAME!}
neynarClientId={process.env.NEYNAR_CLIENT_ID!}

View File

@ -23,7 +23,7 @@ import {
} from '@gitroom/frontend/components/billing/faq.component';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { useUser } from '@gitroom/frontend/components/layout/user.context';
import { useTolt } from '@gitroom/frontend/components/layout/tolt.script';
import { useDubClickId } from '@gitroom/frontend/components/layout/dubAnalytics';
const ModeComponent = dynamic(
() => import('@gitroom/frontend/components/layout/mode.component'),
@ -45,12 +45,12 @@ const EmbeddedBilling = dynamic(
export const FirstBillingComponent = () => {
const { stripeClient } = useVariables();
const user = useUser();
const dub = useDubClickId();
const [stripe, setStripe] = useState<null | Promise<Stripe>>(null);
const [tier, setTier] = useState('STANDARD');
const [period, setPeriod] = useState('MONTHLY');
const fetch = useFetch();
const t = useT();
const tolt = useTolt();
useEffect(() => {
setStripe(loadStripe(stripeClient));
@ -63,7 +63,7 @@ export const FirstBillingComponent = () => {
body: JSON.stringify({
billing: tier,
period: period,
tolt: tolt(),
...(dub ? { dub } : {}),
}),
})
).json();
@ -156,7 +156,9 @@ export const FirstBillingComponent = () => {
</div>
<div className="flex px-[80px] tablet:px-[32px] mobile:!px-[16px] flex-1 flex-row tablet:flex-none tablet:flex-col-reverse">
<div className="flex-1 py-[40px] tablet:pt-[80px] flex flex-col pe-[40px] tablet:pe-0">
<div className="block tablet:hidden"><JoinOver /></div>
<div className="block tablet:hidden">
<JoinOver />
</div>
{!isLoading && data && stripe ? (
<>
<EmbeddedBilling stripe={stripe} secret={data.client_secret} />
@ -168,7 +170,9 @@ export const FirstBillingComponent = () => {
</div>
<div className="flex flex-col ps-[40px] tablet:!ps-[0] border-l border-newColColor py-[40px] mobile:!pt-[24px] tablet:border-none tablet:pb-0">
<div className="top-[20px] sticky">
<div className="hidden tablet:block"><JoinOver /></div>
<div className="hidden tablet:block">
<JoinOver />
</div>
<div className="flex mb-[24px] mobile:flex-col">
<div className="flex-1 text-[24px] font-[700]">
{t('billing_choose_plan', 'Choose a Plan')}

View File

@ -18,17 +18,16 @@ import { useUser } from '@gitroom/frontend/components/layout/user.context';
import { useRouter, useSearchParams } from 'next/navigation';
import { useVariables } from '@gitroom/react/helpers/variable.context';
import { useModals } from '@gitroom/frontend/components/layout/new-modal';
import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
import { Textarea } from '@gitroom/react/form/textarea';
import { useFireEvents } from '@gitroom/helpers/utils/use.fire.events';
import { useUtmUrl } from '@gitroom/helpers/utils/utm.saver';
import { useTolt } from '@gitroom/frontend/components/layout/tolt.script';
import { useTrack } from '@gitroom/react/helpers/use.track';
import { TrackEnum } from '@gitroom/nestjs-libraries/user/track.enum';
import { PurchaseCrypto } from '@gitroom/frontend/components/billing/purchase.crypto';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { FinishTrial } from '@gitroom/frontend/components/billing/finish.trial';
import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone';
import { useDubClickId } from '@gitroom/frontend/components/layout/dubAnalytics';
export const Prorate: FC<{
period: 'MONTHLY' | 'YEARLY';
@ -218,10 +217,10 @@ export const MainBillingComponent: FC<{
const fetch = useFetch();
const toast = useToaster();
const user = useUser();
const dub = useDubClickId();
const modal = useModals();
const router = useRouter();
const utm = useUtmUrl();
const tolt = useTolt();
const track = useTrack();
const t = useT();
const queryParams = useSearchParams();
@ -387,7 +386,7 @@ export const MainBillingComponent: FC<{
period: monthlyOrYearly === 'on' ? 'YEARLY' : 'MONTHLY',
utm,
billing,
tolt: tolt(),
...(dub ? { dub } : {}),
}),
})
).json();

View File

@ -0,0 +1,25 @@
'use client';
import { useVariables } from '@gitroom/react/helpers/variable.context';
import { Analytics as DubAnalyticsIn } from '@dub/analytics/react';
import { getCookie } from 'react-use-cookie';
export const DubAnalytics = () => {
const { dub } = useVariables();
if (!dub) return null;
return (
<DubAnalyticsIn
domainsConfig={{
refer: 'affiliate.postiz.com',
}}
/>
);
};
export const useDubClickId = () => {
const { dub } = useVariables();
if (!dub) return undefined;
const dubCookie = getCookie('dub_partner_data', '{}');
return JSON.parse(dubCookie)?.clickId || undefined;
};

View File

@ -1,17 +0,0 @@
'use client';
import { useVariables } from '@gitroom/react/helpers/variable.context';
import Script from 'next/script';
export const useTolt = () => {
return () => {
// @ts-ignore
return window?.tolt_referral || '';
};
};
export const ToltScript = () => {
const { tolt } = useVariables();
if (!tolt) return null;
return (
<Script async={true} src="https://cdn.tolt.io/tolt.js" data-tolt={tolt} />
);
};

View File

@ -9,5 +9,5 @@ export class BillingSubscribeDto {
utm: string;
tolt: string;
dub: string;
}

View File

@ -375,9 +375,19 @@ export class StripeService {
// @ts-ignore
apiVersion: '2025-03-31.basil',
});
if (body.dub) {
await stripeCustom.customers.update(customer, {
metadata: {
dubCustomerExternalId: userId,
dubClickId: body.dub,
},
});
}
const isUtm = body.utm ? `&utm_source=${body.utm}` : '';
// @ts-ignore
const { client_secret } = await stripeCustom.checkout.sessions.create({
// @ts-ignore
ui_mode: 'custom',
customer,
return_url:
@ -394,13 +404,6 @@ export class StripeService {
ud,
},
},
...(body.tolt
? {
metadata: {
tolt_referral: body.tolt,
},
}
: {}),
allow_promotion_codes: body.period === 'MONTHLY',
line_items: [
{
@ -423,6 +426,16 @@ export class StripeService {
allowTrial: boolean
) {
const isUtm = body.utm ? `&utm_source=${body.utm}` : '';
if (body.dub) {
await stripe.customers.update(customer, {
metadata: {
dubCustomerExternalId: userId,
dubClickId: body.dub,
},
});
}
const { url } = await stripe.checkout.sessions.create({
customer,
cancel_url: process.env['FRONTEND_URL'] + `/billing?cancel=true${isUtm}`,
@ -440,13 +453,6 @@ export class StripeService {
ud,
},
},
...(body.tolt
? {
metadata: {
tolt_referral: body.tolt,
},
}
: {}),
allow_promotion_codes: body.period === 'MONTHLY',
line_items: [
{

View File

@ -22,7 +22,7 @@ interface VariableContextInterface {
disableImageCompression: boolean;
disableXAnalytics: boolean;
language: string;
tolt: string;
dub: boolean;
transloadit: string[];
sentryDsn: string;
}
@ -46,7 +46,7 @@ const VariableContext = createContext({
disableImageCompression: false,
disableXAnalytics: false,
language: '',
tolt: '',
dub: false,
transloadit: [],
sentryDsn: '',
} as VariableContextInterface);

View File

@ -54,6 +54,7 @@
"@copilotkit/react-textarea": "1.10.6",
"@copilotkit/react-ui": "1.10.6",
"@copilotkit/runtime": "1.10.6",
"@dub/analytics": "^0.0.32",
"@hookform/resolvers": "^3.3.4",
"@langchain/community": "^0.3.40",
"@langchain/core": "^0.3.44",

View File

@ -42,6 +42,9 @@ importers:
'@copilotkit/runtime':
specifier: 1.10.6
version: 1.10.6(c9e743140f0883eda50bf44e0628c06c)
'@dub/analytics':
specifier: ^0.0.32
version: 0.0.32
'@hookform/resolvers':
specifier: ^3.3.4
version: 3.10.0(react-hook-form@7.69.0(react@18.3.1))
@ -1974,6 +1977,9 @@ packages:
resolution: {integrity: sha512-I3l7FdGRXluAS44/0NguwWlO83J18p0vlr2FYHrJkWdNYhgVoiYo61IXPqaOsL+vNxU1ZqMACzItGK3/KKDsdw==}
engines: {node: '>= 6'}
'@dub/analytics@0.0.32':
resolution: {integrity: sha512-jmZrgbArOX08/kz+hi1s9ggt0k64WzRErt6jM6TfuqUHlXQYNNNRcefvKrmd9vwmbvNGR/GxZnYeyco6Zyw4fg==}
'@emnapi/core@1.7.1':
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
@ -14998,6 +15004,9 @@ packages:
resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
engines: {node: '>= 18'}
server-only@0.0.1:
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
@ -19140,6 +19149,10 @@ snapshots:
tunnel-agent: 0.6.0
uuid: 8.3.2
'@dub/analytics@0.0.32':
dependencies:
server-only: 0.0.1
'@emnapi/core@1.7.1':
dependencies:
'@emnapi/wasi-threads': 1.1.0
@ -35803,6 +35816,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
server-only@0.0.1: {}
set-blocking@2.0.0: {}
set-function-length@1.2.2: