mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
feat(tracking): integrate HubSpot tracking functionality and reintroduce cancell-deployments export
This commit is contained in:
@@ -68,7 +68,6 @@ export * from "./utils/backups/postgres";
|
||||
export * from "./utils/backups/utils";
|
||||
export * from "./utils/backups/web-server";
|
||||
export * from "./utils/builders/compose";
|
||||
export * from "./utils/startup/cancell-deployments";
|
||||
export * from "./utils/builders/docker-file";
|
||||
export * from "./utils/builders/drop";
|
||||
export * from "./utils/builders/heroku";
|
||||
@@ -77,7 +76,6 @@ export * from "./utils/builders/nixpacks";
|
||||
export * from "./utils/builders/paketo";
|
||||
export * from "./utils/builders/static";
|
||||
export * from "./utils/builders/utils";
|
||||
|
||||
export * from "./utils/cluster/upload";
|
||||
export * from "./utils/databases/rebuild";
|
||||
export * from "./utils/docker/collision";
|
||||
@@ -113,6 +111,8 @@ export * from "./utils/providers/raw";
|
||||
export * from "./utils/schedules/index";
|
||||
export * from "./utils/schedules/utils";
|
||||
export * from "./utils/servers/remote-docker";
|
||||
export * from "./utils/startup/cancell-deployments";
|
||||
export * from "./utils/tracking/hubspot";
|
||||
export * from "./utils/traefik/application";
|
||||
export * from "./utils/traefik/domain";
|
||||
export * from "./utils/traefik/file-types";
|
||||
|
||||
@@ -10,6 +10,7 @@ import { db } from "../db";
|
||||
import * as schema from "../db/schema";
|
||||
import { getUserByToken } from "../services/admin";
|
||||
import { updateUser } from "../services/user";
|
||||
import { getHubSpotUTK, submitToHubSpot } from "../utils/tracking/hubspot";
|
||||
import { sendEmail } from "../verification/send-verification-email";
|
||||
import { getPublicIpWithFallback } from "../wss/utils";
|
||||
|
||||
@@ -115,7 +116,7 @@ const { handler, api } = betterAuth({
|
||||
}
|
||||
}
|
||||
},
|
||||
after: async (user) => {
|
||||
after: async (user, context) => {
|
||||
const isAdminPresent = await db.query.member.findFirst({
|
||||
where: eq(schema.member.role, "owner"),
|
||||
});
|
||||
@@ -126,6 +127,27 @@ const { handler, api } = betterAuth({
|
||||
});
|
||||
}
|
||||
|
||||
if (IS_CLOUD) {
|
||||
try {
|
||||
const hutk = getHubSpotUTK(
|
||||
context?.request?.headers?.get("cookie") || undefined,
|
||||
);
|
||||
const hubspotSuccess = await submitToHubSpot(
|
||||
{
|
||||
email: user.email,
|
||||
firstName: user.name,
|
||||
lastName: user.name,
|
||||
},
|
||||
hutk,
|
||||
);
|
||||
if (!hubspotSuccess) {
|
||||
console.error("Failed to submit to HubSpot");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error submitting to HubSpot", error);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_CLOUD || !isAdminPresent) {
|
||||
await db.transaction(async (tx) => {
|
||||
const organization = await tx
|
||||
|
||||
125
packages/server/src/utils/tracking/hubspot.ts
Normal file
125
packages/server/src/utils/tracking/hubspot.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
interface HubSpotFormField {
|
||||
objectTypeId: string;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface HubSpotFormData {
|
||||
fields: HubSpotFormField[];
|
||||
context: {
|
||||
pageUri: string;
|
||||
pageName: string;
|
||||
hutk?: string; // HubSpot UTK from cookies
|
||||
};
|
||||
}
|
||||
|
||||
interface SignUpFormData {
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract HubSpot UTK (User Token) from cookies
|
||||
* This is used for tracking and attribution in HubSpot
|
||||
*/
|
||||
export function getHubSpotUTK(cookieHeader?: string): string | null {
|
||||
if (!cookieHeader) return null;
|
||||
|
||||
const name = "hubspotutk=";
|
||||
const decodedCookie = decodeURIComponent(cookieHeader);
|
||||
const cookieArray = decodedCookie.split(";");
|
||||
|
||||
for (let i = 0; i < cookieArray.length; i++) {
|
||||
const cookie = cookieArray[i]?.trim();
|
||||
if (!cookie) continue;
|
||||
if (cookie.indexOf(name) === 0) {
|
||||
return cookie.substring(name.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert contact form data to HubSpot form format
|
||||
*/
|
||||
export function formatContactDataForHubSpot(
|
||||
contactData: SignUpFormData,
|
||||
hutk?: string | null,
|
||||
): HubSpotFormData {
|
||||
const formData: HubSpotFormData = {
|
||||
fields: [
|
||||
{
|
||||
objectTypeId: "0-1", // Contact object type
|
||||
name: "firstname",
|
||||
value: contactData.firstName || "",
|
||||
},
|
||||
{
|
||||
objectTypeId: "0-1",
|
||||
name: "lastname",
|
||||
value: contactData.lastName || "",
|
||||
},
|
||||
{
|
||||
objectTypeId: "0-1",
|
||||
name: "email",
|
||||
value: contactData.email || "",
|
||||
},
|
||||
],
|
||||
context: {
|
||||
pageUri: "https://app.dokploy.com/register",
|
||||
pageName: "Sign Up",
|
||||
},
|
||||
};
|
||||
|
||||
// Add HubSpot UTK if available
|
||||
if (hutk) {
|
||||
formData.context.hutk = hutk;
|
||||
}
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form data to HubSpot Forms API
|
||||
*/
|
||||
export async function submitToHubSpot(
|
||||
contactData: SignUpFormData,
|
||||
hutk?: string | null,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const portalId = process.env.HUBSPOT_PORTAL_ID;
|
||||
const formGuid = process.env.HUBSPOT_FORM_GUID;
|
||||
|
||||
if (!portalId || !formGuid) {
|
||||
console.error(
|
||||
"HubSpot configuration missing: HUBSPOT_PORTAL_ID or HUBSPOT_FORM_GUID not set",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const formData = formatContactDataForHubSpot(contactData, hutk);
|
||||
const response = await fetch(
|
||||
`https://api.hsforms.com/submissions/v3/integration/submit/${portalId}/${formGuid}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error("HubSpot API error:", response.status, errorText);
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log("HubSpot submission successful:", result);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error submitting to HubSpot:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user