added ga4 google analytics (#5126)
* added ga4 google analytics * added ga4 script as TODO * get analytics app working * Remove stale comment * Fix types Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
This commit is contained in:
parent
79df03de49
commit
9f1341e94e
|
@ -1,35 +1,40 @@
|
|||
import Script from "next/script";
|
||||
|
||||
import { getEventTypeAppData } from "@calcom/app-store/utils";
|
||||
import { trackingApps } from "./eventTypeAnalytics";
|
||||
|
||||
// TODO: Maintain it from config.json maybe
|
||||
const trackingApps: Record<string, Record<string, unknown>> = {
|
||||
fathom: {
|
||||
src: "https://cdn.usefathom.com/script.js",
|
||||
"data-site": "{TRACKING_ID}",
|
||||
},
|
||||
};
|
||||
export type AppScript = {attrs?: Record<string, string>} & ({src: undefined, content?: string} | {src?: string, content:undefined})
|
||||
|
||||
export default function BookingPageTagManager({
|
||||
eventType,
|
||||
}: {
|
||||
eventType: Parameters<typeof getEventTypeAppData>[0];
|
||||
}) {
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{Object.entries(trackingApps).map(([appId, scriptConfig]) => {
|
||||
const trackingId = getEventTypeAppData(eventType, "fathom")?.trackingId;
|
||||
const trackingId = getEventTypeAppData(eventType, appId as keyof typeof trackingApps)?.trackingId;
|
||||
if (!trackingId) {
|
||||
return null;
|
||||
}
|
||||
const parsedScriptConfig: Record<string, unknown> = {};
|
||||
Object.entries(scriptConfig).forEach(([name, value]) => {
|
||||
if (typeof value === "string") {
|
||||
value = value.replace("{TRACKING_ID}", trackingId);
|
||||
}
|
||||
parsedScriptConfig[name] = value;
|
||||
});
|
||||
return <Script key={appId} {...parsedScriptConfig} defer />;
|
||||
const parseValue = <T extends string|undefined, >(val: T ):T => val ? val.replace(/\{TRACKING_ID\}/g, trackingId) as T : val
|
||||
|
||||
return scriptConfig.scripts.map((script, index)=>{
|
||||
const parsedAttributes: NonNullable<AppScript["attrs"]> = {};
|
||||
const attrs = script.attrs || {};
|
||||
Object.entries(attrs).forEach(([name, value]) => {
|
||||
if (typeof value === "string") {
|
||||
value = parseValue(value)
|
||||
}
|
||||
parsedAttributes[name] = value;
|
||||
});
|
||||
|
||||
return <Script src={parseValue(script.src)} key={`${appId}-${index}`} {...{dangerouslySetInnerHTML:{
|
||||
__html: parseValue(script.content) || ""
|
||||
}, ...parsedAttributes}} defer />;
|
||||
})
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -34,6 +34,7 @@ export const AppSettingsComponentsMap = {
|
|||
};
|
||||
export const EventTypeAddonMap = {
|
||||
fathom: dynamic(() => import("./fathom/extensions/EventTypeAppCard")),
|
||||
ga4: dynamic(() => import("./ga4/extensions/EventTypeAppCard")),
|
||||
giphy: dynamic(() => import("./giphy/extensions/EventTypeAppCard")),
|
||||
qr_code: dynamic(() => import("./qr_code/extensions/EventTypeAppCard")),
|
||||
rainbow: dynamic(() => import("./rainbow/extensions/EventTypeAppCard")),
|
||||
|
|
|
@ -13,6 +13,7 @@ import { metadata as exchange2013calendar_meta } from "./exchange2013calendar/_m
|
|||
import { metadata as exchange2016calendar_meta } from "./exchange2016calendar/_metadata";
|
||||
import { metadata as exchangecalendar_meta } from "./exchangecalendar/_metadata";
|
||||
import { metadata as fathom_meta } from "./fathom/_metadata";
|
||||
import { metadata as ga4_meta } from "./ga4/_metadata";
|
||||
import { metadata as giphy_meta } from "./giphy/_metadata";
|
||||
import { metadata as googlecalendar_meta } from "./googlecalendar/_metadata";
|
||||
import { metadata as googlevideo_meta } from "./googlevideo/_metadata";
|
||||
|
@ -52,6 +53,7 @@ export const appStoreMetadata = {
|
|||
exchange2016calendar: exchange2016calendar_meta,
|
||||
exchangecalendar: exchangecalendar_meta,
|
||||
fathom: fathom_meta,
|
||||
ga4: ga4_meta,
|
||||
giphy: giphy_meta,
|
||||
googlecalendar: googlecalendar_meta,
|
||||
googlevideo: googlevideo_meta,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
**/
|
||||
import { appDataSchema as routing_forms_schema } from "./ee/routing-forms/zod";
|
||||
import { appDataSchema as fathom_schema } from "./fathom/zod";
|
||||
import { appDataSchema as ga4_schema } from "./ga4/zod";
|
||||
import { appDataSchema as giphy_schema } from "./giphy/zod";
|
||||
import { appDataSchema as qr_code_schema } from "./qr_code/zod";
|
||||
import { appDataSchema as rainbow_schema } from "./rainbow/zod";
|
||||
|
@ -12,6 +13,7 @@ import { appDataSchema as stripepayment_schema } from "./stripepayment/zod";
|
|||
export const appDataSchemas = {
|
||||
"routing-forms": routing_forms_schema,
|
||||
fathom: fathom_schema,
|
||||
ga4: ga4_schema,
|
||||
giphy: giphy_schema,
|
||||
qr_code: qr_code_schema,
|
||||
rainbow: rainbow_schema,
|
||||
|
|
|
@ -13,6 +13,7 @@ export const apiHandlers = {
|
|||
exchange2016calendar: import("./exchange2016calendar/api"),
|
||||
exchangecalendar: import("./exchangecalendar/api"),
|
||||
fathom: import("./fathom/api"),
|
||||
ga4: import("./ga4/api"),
|
||||
giphy: import("./giphy/api"),
|
||||
googlecalendar: import("./googlecalendar/api"),
|
||||
hubspotothercalendar: import("./hubspotothercalendar/api"),
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { AppScript } from "./BookingPageTagManager";
|
||||
import { appDataSchemas } from "./apps.schemas.generated";
|
||||
|
||||
// TODO: This config might be imported from {APP}/eventTypeAnalytics.ts.
|
||||
export const trackingApps: Partial<
|
||||
Record<
|
||||
keyof typeof appDataSchemas,
|
||||
{
|
||||
scripts: AppScript[];
|
||||
}
|
||||
>
|
||||
> = {
|
||||
fathom: {
|
||||
scripts: [
|
||||
{
|
||||
src: "https://cdn.usefathom.com/script.js",
|
||||
content: undefined,
|
||||
attrs: {
|
||||
"data-site": "{TRACKING_ID}",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
ga4: {
|
||||
scripts: [
|
||||
{
|
||||
src: "https://www.googletagmanager.com/gtag/js?id={TRACKING_ID}",
|
||||
content: undefined,
|
||||
attrs: {},
|
||||
},
|
||||
{
|
||||
src: undefined,
|
||||
content: `
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '{TRACKING_ID}');
|
||||
`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
|
@ -3,12 +3,11 @@ import { useState } from "react";
|
|||
import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext";
|
||||
import AppCard from "@calcom/app-store/_components/AppCard";
|
||||
import type { EventTypeAppCardComponent } from "@calcom/app-store/types";
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { Input, TextField } from "@calcom/ui/v2";
|
||||
import { TextField } from "@calcom/ui/v2";
|
||||
|
||||
import { appDataSchema } from "../zod";
|
||||
|
||||
const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ eventType, app }) {
|
||||
const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ app }) {
|
||||
const [getAppData, setAppData] = useAppContextWithSchema<typeof appDataSchema>();
|
||||
const trackingId = getAppData("trackingId");
|
||||
const [enabled, setEnabled] = useState(getAppData("enabled"));
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
description: Google Analytics is a web analytics service offered by Google that tracks and reports website traffic, currently as a platform inside the Google Marketing Platform brand.
|
||||
items:
|
||||
- /api/app-store/ga4/1.jpeg
|
||||
- /api/app-store/ga4/2.jpeg
|
||||
- /api/app-store/ga4/3.jpeg
|
||||
- /api/app-store/ga4/4.jpeg
|
||||
- /api/app-store/ga4/5.jpeg
|
||||
---
|
||||
|
||||
<Slider items={items} />
|
||||
|
||||
{description}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import type { AppMeta } from "@calcom/types/App";
|
||||
|
||||
import config from "./config.json";
|
||||
|
||||
export const metadata = {
|
||||
category: "other",
|
||||
...config,
|
||||
} as AppMeta;
|
||||
|
||||
export default metadata;
|
|
@ -0,0 +1,17 @@
|
|||
import { AppDeclarativeHandler } from "@calcom/types/AppHandler";
|
||||
|
||||
import { createDefaultInstallation } from "../../_utils/installation";
|
||||
import appConfig from "../config.json";
|
||||
|
||||
const handler: AppDeclarativeHandler = {
|
||||
// Instead of passing appType and slug from here, api/integrations/[..args] should be able to derive and pass these directly to createCredential
|
||||
appType: appConfig.type,
|
||||
variant: appConfig.variant,
|
||||
slug: appConfig.slug,
|
||||
supportsMultipleInstalls: false,
|
||||
handlerType: "add",
|
||||
createCredential: ({ appType, user, slug }) =>
|
||||
createDefaultInstallation({ appType, userId: user.id, slug, key: {} }),
|
||||
};
|
||||
|
||||
export default handler;
|
|
@ -0,0 +1 @@
|
|||
export { default as add } from "./add";
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"/*": "Don't modify slug - If required, do it using cli edit command",
|
||||
"name": "Google Analytics",
|
||||
"slug": "ga4",
|
||||
"type": "ga4_analytics",
|
||||
"imageSrc": "/api/app-store/ga4/icon.svg",
|
||||
"logo": "/api/app-store/ga4/icon.svg",
|
||||
"url": "https://marketingplatform.google.com",
|
||||
"variant": "analytics",
|
||||
"categories": ["analytics"],
|
||||
"publisher": "Cal.com, Inc.",
|
||||
"email": "support@cal.com",
|
||||
"description": "Google Analytics is a web analytics service offered by Google that tracks and reports website traffic, currently as a platform inside the Google Marketing Platform brand.",
|
||||
"extendsFeature": "EventType",
|
||||
"__createdUsingCli": true
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import { useState } from "react";
|
||||
|
||||
import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext";
|
||||
import AppCard from "@calcom/app-store/_components/AppCard";
|
||||
import type { EventTypeAppCardComponent } from "@calcom/app-store/types";
|
||||
import { TextField } from "@calcom/ui/v2";
|
||||
|
||||
import { appDataSchema } from "../zod";
|
||||
|
||||
const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ app }) {
|
||||
const [getAppData, setAppData] = useAppContextWithSchema<typeof appDataSchema>();
|
||||
const trackingId = getAppData("trackingId");
|
||||
const [enabled, setEnabled] = useState(getAppData("enabled"));
|
||||
|
||||
return (
|
||||
<AppCard
|
||||
setAppData={setAppData}
|
||||
app={app}
|
||||
switchOnClick={(e) => {
|
||||
if (!e) {
|
||||
setEnabled(false);
|
||||
} else {
|
||||
setEnabled(true);
|
||||
}
|
||||
}}
|
||||
switchChecked={enabled}>
|
||||
<TextField
|
||||
name="Tracking ID"
|
||||
value={trackingId}
|
||||
onChange={(e) => {
|
||||
setAppData("trackingId", e.target.value);
|
||||
}}
|
||||
/>
|
||||
</AppCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default EventTypeAppCard;
|
|
@ -0,0 +1,2 @@
|
|||
export * as api from "./api";
|
||||
export { metadata } from "./_metadata";
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"name": "@calcom/ga4",
|
||||
"version": "0.0.0",
|
||||
"main": "./index.ts",
|
||||
"description": "Google Analytics is a web analytics service offered by Google that tracks and reports website traffic, currently as a platform inside the Google Marketing Platform brand.",
|
||||
"dependencies": {
|
||||
"@calcom/lib": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@calcom/types": "*"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
|
@ -0,0 +1,35 @@
|
|||
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1_8)">
|
||||
<path d="M91.9072 0H73.6981C69.2937 0 65.6782 3.61842 65.6782 8.02632V31.5789H39.3177C35.0448 31.5789 31.5608 35.0658 31.5608 39.4079V65.7895H7.82976C3.49113 65.7895 0.00708008 69.2763 0.00708008 73.6184V92.0395C0.00708008 96.3816 3.49113 99.8684 7.82976 100H91.9729C96.3773 100 99.9928 96.3816 99.9928 91.9737V8.02632C99.9271 3.61842 96.3115 0 91.9072 0Z" fill="url(#paint0_linear_1_8)"/>
|
||||
<path d="M91.9072 0H73.6981C69.2937 0 65.6782 3.61842 65.6782 8.02632V31.5789H39.3177C35.0448 31.5789 31.5608 35.0658 31.5608 39.4079V65.7895H7.82976C3.49113 65.7895 0.00708008 69.2763 0.00708008 73.6184V92.0395C0.00708008 96.3816 3.49113 99.8684 7.82976 100H91.9729C96.3773 100 99.9928 96.3816 99.9928 91.9737V8.02632C99.9271 3.61842 96.3115 0 91.9072 0Z" fill="url(#paint1_linear_1_8)"/>
|
||||
<path d="M91.9072 0H73.8296C69.4252 0 65.8097 3.61842 65.8097 8.02632V100H91.9072C96.3116 100 99.9271 96.3816 99.9271 91.9737V8.02632C99.9271 3.61842 96.3116 0 91.9072 0Z" fill="#F57C00"/>
|
||||
<path d="M31.5608 39.4736V65.7894H7.8955C3.55687 65.7894 0.00708008 69.342 0.00708008 73.6841V92.1052C0.00708008 96.4473 3.55687 99.9999 7.8955 99.9999H65.7439V31.5789H39.4492C35.1106 31.5789 31.5608 35.1315 31.5608 39.4736Z" fill="#FFC107"/>
|
||||
<path d="M65.744 31.579V100H91.8415C96.2459 100 99.8614 96.3816 99.8614 91.9737V65.7895L65.744 31.579Z" fill="url(#paint2_linear_1_8)"/>
|
||||
<path opacity="0.2" d="M39.4492 32.2369H65.7439V31.579H39.4492C35.1106 31.579 31.5608 35.1316 31.5608 39.4737V40.1316C31.5608 35.7895 35.1106 32.2369 39.4492 32.2369Z" fill="white"/>
|
||||
<path opacity="0.2" d="M7.8955 66.4473H31.5608V65.7894H7.8955C3.55687 65.7894 0.00708008 69.3421 0.00708008 73.6842V74.3421C0.00708008 70 3.55687 66.4473 7.8955 66.4473Z" fill="white"/>
|
||||
<path opacity="0.2" d="M91.9072 0H73.8296C69.4252 0 65.8097 3.61842 65.8097 8.02631V8.68421C65.8097 4.27632 69.4252 0.657895 73.8296 0.657895H91.9072C96.3116 0.657895 99.9271 4.27632 99.9271 8.68421V8.02631C99.9271 3.61842 96.3116 0 91.9072 0Z" fill="white"/>
|
||||
<path opacity="0.2" d="M91.9072 99.3421H7.8955C3.55687 99.3421 0.00708008 95.7895 0.00708008 91.4474V92.1053C0.00708008 96.4474 3.55687 100 7.8955 100H91.8414C96.2458 100 99.8613 96.3816 99.8613 91.9737V91.3158C99.9271 95.7237 96.3115 99.3421 91.9072 99.3421V99.3421Z" fill="#BF360C"/>
|
||||
<path d="M91.9072 0H73.8296C69.4252 0 65.8097 3.61842 65.8097 8.02632V31.5789H39.5149C35.1763 31.5789 31.6265 35.1316 31.6265 39.4737V65.7895H7.8955C3.55687 65.7895 0.00708008 69.3421 0.00708008 73.6842V92.1053C0.00708008 96.4474 3.55687 100 7.8955 100H91.9072C96.3116 100 99.9271 96.3816 99.9271 91.9737V8.02632C99.9271 3.61842 96.3116 0 91.9072 0Z" fill="url(#paint3_linear_1_8)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1_8" x1="0.00708008" y1="50" x2="99.9928" y2="50" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white" stop-opacity="0.1"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1_8" x1="0.00708008" y1="50" x2="99.9928" y2="50" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white" stop-opacity="0.1"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_1_8" x1="48.8168" y1="48.8487" x2="97.5733" y2="97.5663" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#BF360C" stop-opacity="0.2"/>
|
||||
<stop offset="1" stop-color="#BF360C" stop-opacity="0.02"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_1_8" x1="33.5125" y1="33.573" x2="98.2006" y2="98.2094" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white" stop-opacity="0.1"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_1_8">
|
||||
<rect width="100" height="100" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1,9 @@
|
|||
import { z } from "zod";
|
||||
|
||||
import { eventTypeAppCardZod } from "../eventTypeAppCardZod";
|
||||
|
||||
export const appDataSchema = eventTypeAppCardZod.merge(
|
||||
z.object({
|
||||
trackingId: z.string(),
|
||||
})
|
||||
);
|
|
@ -84,6 +84,12 @@
|
|||
"slug": "fathom",
|
||||
"type": "fathom_analytics"
|
||||
},
|
||||
{
|
||||
"dirName": "ga4",
|
||||
"categories": ["analytics"],
|
||||
"slug": "ga4",
|
||||
"type": "ga4_analytics"
|
||||
},
|
||||
{
|
||||
"dirName": "pipedream",
|
||||
"categories": ["automation"],
|
||||
|
|
Loading…
Reference in New Issue
Block a user