feat: moving to dub partners
This commit is contained in:
parent
e5a4c558dd
commit
00caa7ddc4
|
|
@ -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'}
|
||||
|
|
|
|||
|
|
@ -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!}
|
||||
|
|
|
|||
|
|
@ -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')}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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} />
|
||||
);
|
||||
};
|
||||
|
|
@ -9,5 +9,5 @@ export class BillingSubscribeDto {
|
|||
|
||||
utm: string;
|
||||
|
||||
tolt: string;
|
||||
dub: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue