mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
feat: Remove PostHog event calls (#6915)
This commit is contained in:
parent
41c3cc89ca
commit
270946a93b
|
@ -124,7 +124,6 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
return this.telemetry.track(
|
||||
'User responded to personalization questions',
|
||||
personalizationSurveyData,
|
||||
{ withPostHog: true },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -190,21 +189,17 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
workflowName: workflow.name,
|
||||
},
|
||||
}),
|
||||
this.telemetry.track(
|
||||
'User saved workflow',
|
||||
{
|
||||
user_id: user.id,
|
||||
workflow_id: workflow.id,
|
||||
node_graph_string: JSON.stringify(nodeGraph),
|
||||
notes_count_overlapping: overlappingCount,
|
||||
notes_count_non_overlapping: notesCount - overlappingCount,
|
||||
version_cli: N8N_VERSION,
|
||||
num_tags: workflow.tags?.length ?? 0,
|
||||
public_api: publicApi,
|
||||
sharing_role: userRole,
|
||||
},
|
||||
{ withPostHog: true },
|
||||
),
|
||||
this.telemetry.track('User saved workflow', {
|
||||
user_id: user.id,
|
||||
workflow_id: workflow.id,
|
||||
node_graph_string: JSON.stringify(nodeGraph),
|
||||
notes_count_overlapping: overlappingCount,
|
||||
notes_count_non_overlapping: notesCount - overlappingCount,
|
||||
version_cli: N8N_VERSION,
|
||||
num_tags: workflow.tags?.length ?? 0,
|
||||
public_api: publicApi,
|
||||
sharing_role: userRole,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -415,11 +410,7 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
node_id: nodeGraphResult.nameIndices[runData.data.startData?.destinationNode],
|
||||
};
|
||||
|
||||
promises.push(
|
||||
this.telemetry.track('Manual node exec finished', telemetryPayload, {
|
||||
withPostHog: true,
|
||||
}),
|
||||
);
|
||||
promises.push(this.telemetry.track('Manual node exec finished', telemetryPayload));
|
||||
} else {
|
||||
nodeGraphResult.webhookNodeNames.forEach((name: string) => {
|
||||
const execJson = runData.data.resultData.runData[name]?.[0]?.data?.main?.[0]?.[0]
|
||||
|
@ -432,9 +423,7 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
});
|
||||
|
||||
promises.push(
|
||||
this.telemetry.track('Manual workflow exec finished', manualExecEventProperties, {
|
||||
withPostHog: true,
|
||||
}),
|
||||
this.telemetry.track('Manual workflow exec finished', manualExecEventProperties),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -484,7 +473,7 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
user_id_list: userList,
|
||||
};
|
||||
|
||||
return this.telemetry.track('User updated workflow sharing', properties, { withPostHog: true });
|
||||
return this.telemetry.track('User updated workflow sharing', properties);
|
||||
}
|
||||
|
||||
async onN8nStop(): Promise<void> {
|
||||
|
@ -1017,7 +1006,7 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
user_id: string;
|
||||
workflow_id: string;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('Workflow first prod success', data, { withPostHog: true });
|
||||
return this.telemetry.track('Workflow first prod success', data);
|
||||
}
|
||||
|
||||
async onFirstWorkflowDataLoad(data: {
|
||||
|
@ -1028,7 +1017,7 @@ export class InternalHooks implements IInternalHooksClass {
|
|||
credential_type?: string;
|
||||
credential_id?: string;
|
||||
}): Promise<void> {
|
||||
return this.telemetry.track('Workflow first data fetched', data, { withPostHog: true });
|
||||
return this.telemetry.track('Workflow first data fetched', data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -490,7 +490,7 @@ export class Server extends AbstractServer {
|
|||
const controllers: object[] = [
|
||||
new EventBusController(),
|
||||
new AuthController({ config, internalHooks, repositories, logger, postHog }),
|
||||
new OwnerController({ config, internalHooks, repositories, logger }),
|
||||
new OwnerController({ config, internalHooks, repositories, logger, postHog }),
|
||||
new MeController({ externalHooks, internalHooks, repositories, logger }),
|
||||
new NodeTypesController({ config, nodeTypes }),
|
||||
new PasswordResetController({
|
||||
|
|
|
@ -762,7 +762,7 @@ export const schema = {
|
|||
externalFrontendHooksUrls: {
|
||||
doc: 'URLs to external frontend hooks files, ; separated',
|
||||
format: String,
|
||||
default: 'https://public.n8n.cloud/posthog-hooks.js',
|
||||
default: '',
|
||||
env: 'EXTERNAL_FRONTEND_HOOKS_URLS',
|
||||
},
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
hashPassword,
|
||||
sanitizeUser,
|
||||
validatePassword,
|
||||
withFeatureFlags,
|
||||
} from '@/UserManagement/UserManagementHelper';
|
||||
import { issueCookie } from '@/auth/jwt';
|
||||
import { Response } from 'express';
|
||||
|
@ -14,6 +15,7 @@ import type { Config } from '@/config';
|
|||
import { OwnerRequest } from '@/requests';
|
||||
import type { IDatabaseCollections, IInternalHooksClass } from '@/Interfaces';
|
||||
import type { SettingsRepository, UserRepository } from '@db/repositories';
|
||||
import type { PostHogClient } from '@/posthog';
|
||||
|
||||
@Authorized(['global', 'owner'])
|
||||
@RestController('/owner')
|
||||
|
@ -28,22 +30,27 @@ export class OwnerController {
|
|||
|
||||
private readonly settingsRepository: SettingsRepository;
|
||||
|
||||
private readonly postHog?: PostHogClient;
|
||||
|
||||
constructor({
|
||||
config,
|
||||
logger,
|
||||
internalHooks,
|
||||
repositories,
|
||||
postHog,
|
||||
}: {
|
||||
config: Config;
|
||||
logger: ILogger;
|
||||
internalHooks: IInternalHooksClass;
|
||||
repositories: Pick<IDatabaseCollections, 'User' | 'Settings'>;
|
||||
postHog?: PostHogClient;
|
||||
}) {
|
||||
this.config = config;
|
||||
this.logger = logger;
|
||||
this.internalHooks = internalHooks;
|
||||
this.userRepository = repositories.User;
|
||||
this.settingsRepository = repositories.Settings;
|
||||
this.postHog = postHog;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +129,7 @@ export class OwnerController {
|
|||
|
||||
void this.internalHooks.onInstanceOwnerSetup({ user_id: userId });
|
||||
|
||||
return sanitizeUser(owner);
|
||||
return withFeatureFlags(this.postHog, sanitizeUser(owner));
|
||||
}
|
||||
|
||||
@Post('/dismiss-banner')
|
||||
|
|
|
@ -95,15 +95,11 @@ export class Telemetry {
|
|||
return sum > 0;
|
||||
})
|
||||
.map(async (workflowId) => {
|
||||
const promise = this.track(
|
||||
'Workflow execution count',
|
||||
{
|
||||
event_version: '2',
|
||||
workflow_id: workflowId,
|
||||
...this.executionCountsBuffer[workflowId],
|
||||
},
|
||||
{ withPostHog: true },
|
||||
);
|
||||
const promise = this.track('Workflow execution count', {
|
||||
event_version: '2',
|
||||
workflow_id: workflowId,
|
||||
...this.executionCountsBuffer[workflowId],
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
|
|
@ -78,6 +78,12 @@ declare global {
|
|||
reset?(resetDeviceId?: boolean): void;
|
||||
onFeatureFlags?(callback: (keys: string[], map: FeatureFlags) => void): void;
|
||||
reloadFeatureFlags?(): void;
|
||||
capture?(event: string, properties: IDataObject): void;
|
||||
register?(metadata: IDataObject): void;
|
||||
people?: {
|
||||
set?(metadata: IDataObject): void;
|
||||
};
|
||||
debug?(): void;
|
||||
};
|
||||
analytics?: {
|
||||
track(event: string, proeprties?: ITelemetryTrackProperties): void;
|
||||
|
|
|
@ -28,7 +28,7 @@ export async function logout(context: IRestApiContext): Promise<void> {
|
|||
export async function setupOwner(
|
||||
context: IRestApiContext,
|
||||
params: { firstName: string; lastName: string; email: string; password: string },
|
||||
): Promise<IUserResponse> {
|
||||
): Promise<CurrentUserResponse> {
|
||||
return makeRestApiRequest(context, 'POST', '/owner/setup', params as unknown as IDataObject);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ import { useSettingsStore } from '@/stores/settings.store';
|
|||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createEventBus } from 'n8n-design-system/utils';
|
||||
import { usePostHog } from '@/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PersonalizationModal',
|
||||
|
@ -166,7 +167,7 @@ export default defineComponent({
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useSettingsStore, useUIStore, useUsersStore),
|
||||
...mapStores(useRootStore, useSettingsStore, useUIStore, useUsersStore, usePostHog),
|
||||
survey() {
|
||||
const survey: IFormInputs = [
|
||||
{
|
||||
|
@ -645,6 +646,8 @@ export default defineComponent({
|
|||
|
||||
await this.usersStore.submitPersonalizationSurvey(survey as IPersonalizationLatestVersion);
|
||||
|
||||
this.posthogStore.setMetadata(survey, 'user');
|
||||
|
||||
if (Object.keys(values).length === 0) {
|
||||
this.closeDialog();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import { useSettingsStore } from '@/stores/settings.store';
|
|||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { useTelemetryStore } from '@/stores/telemetry.store';
|
||||
import { SLACK_NODE_TYPE } from '@/constants';
|
||||
import { usePostHog } from '@/stores/posthog.store';
|
||||
|
||||
export class Telemetry {
|
||||
constructor(
|
||||
|
@ -72,7 +73,11 @@ export class Telemetry {
|
|||
}
|
||||
}
|
||||
|
||||
track(event: string, properties?: ITelemetryTrackProperties) {
|
||||
track(
|
||||
event: string,
|
||||
properties?: ITelemetryTrackProperties,
|
||||
{ withPostHog } = { withPostHog: false },
|
||||
) {
|
||||
if (!this.rudderStack) return;
|
||||
|
||||
const updatedProperties = {
|
||||
|
@ -81,6 +86,10 @@ export class Telemetry {
|
|||
};
|
||||
|
||||
this.rudderStack.track(event, updatedProperties);
|
||||
|
||||
if (withPostHog) {
|
||||
usePostHog().capture(event, updatedProperties);
|
||||
}
|
||||
}
|
||||
|
||||
page(route: Route) {
|
||||
|
@ -119,7 +128,7 @@ export class Telemetry {
|
|||
properties.session_id = useRootStore().sessionId;
|
||||
switch (event) {
|
||||
case 'askAi.generationFinished':
|
||||
this.track('Ai code generation finished', properties);
|
||||
this.track('Ai code generation finished', properties, { withPostHog: true });
|
||||
case 'ask.generationClicked':
|
||||
this.track('User clicked on generate code button', properties);
|
||||
default:
|
||||
|
@ -189,7 +198,7 @@ export class Telemetry {
|
|||
this.track('User viewed node category', properties);
|
||||
break;
|
||||
case 'nodeView.addNodeButton':
|
||||
this.track('User added node to workflow canvas', properties);
|
||||
this.track('User added node to workflow canvas', properties, { withPostHog: true });
|
||||
break;
|
||||
case 'nodeView.addSticky':
|
||||
this.track('User inserted workflow note', properties);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { defineStore } from 'pinia';
|
|||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import type { FeatureFlags } from 'n8n-workflow';
|
||||
import type { FeatureFlags, IDataObject } from 'n8n-workflow';
|
||||
import { EXPERIMENTS_TO_TRACK, LOCAL_STORAGE_EXPERIMENT_OVERRIDES } from '@/constants';
|
||||
import { useTelemetryStore } from './telemetry.store';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
@ -161,10 +161,29 @@ export const usePostHog = defineStore('posthog', () => {
|
|||
trackedDemoExp.value[name] = variant;
|
||||
};
|
||||
|
||||
const capture = (event: string, properties: IDataObject) => {
|
||||
if (typeof window.posthog?.capture === 'function') {
|
||||
window.posthog.capture(event, properties);
|
||||
}
|
||||
};
|
||||
|
||||
const setMetadata = (metadata: IDataObject, target: 'user' | 'events') => {
|
||||
if (typeof window.posthog?.people?.set !== 'function') return;
|
||||
if (typeof window.posthog?.register !== 'function') return;
|
||||
|
||||
if (target === 'user') {
|
||||
window.posthog?.people?.set(metadata);
|
||||
} else if (target === 'events') {
|
||||
window.posthog?.register(metadata);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
init,
|
||||
isVariantEnabled,
|
||||
getVariant,
|
||||
reset,
|
||||
capture,
|
||||
setMetadata,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -200,6 +200,7 @@ export const useUsersStore = defineStore(STORES.USERS, {
|
|||
this.addUsers([user]);
|
||||
this.currentUserId = user.id;
|
||||
settingsStore.stopShowingSetupPage();
|
||||
usePostHog().init(user.featureFlags);
|
||||
}
|
||||
},
|
||||
async validateSignupToken(params: {
|
||||
|
@ -221,9 +222,8 @@ export const useUsersStore = defineStore(STORES.USERS, {
|
|||
if (user) {
|
||||
this.addUsers([user]);
|
||||
this.currentUserId = user.id;
|
||||
usePostHog().init(user.featureFlags);
|
||||
}
|
||||
|
||||
usePostHog().init(user.featureFlags);
|
||||
},
|
||||
async sendForgotPasswordEmail(params: { email: string }): Promise<void> {
|
||||
const rootStore = useRootStore();
|
||||
|
|
|
@ -68,6 +68,7 @@ import type {
|
|||
import { setPageTitle } from '@/utils';
|
||||
import { VIEWS } from '@/constants';
|
||||
import { useTemplatesStore } from '@/stores/templates.store';
|
||||
import { usePostHog } from '@/stores/posthog.store';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TemplatesCollectionView',
|
||||
|
@ -78,7 +79,7 @@ export default defineComponent({
|
|||
TemplatesView,
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTemplatesStore),
|
||||
...mapStores(useTemplatesStore, usePostHog),
|
||||
collection(): null | ITemplatesCollectionFull {
|
||||
return this.templatesStore.getCollectionById(this.collectionId);
|
||||
},
|
||||
|
@ -122,8 +123,9 @@ export default defineComponent({
|
|||
source: 'collection',
|
||||
};
|
||||
void this.$externalHooks().run('templatesCollectionView.onUseWorkflow', telemetryPayload);
|
||||
this.$telemetry.track('User inserted workflow template', telemetryPayload);
|
||||
|
||||
this.$telemetry.track('User inserted workflow template', telemetryPayload, {
|
||||
withPostHog: true,
|
||||
});
|
||||
this.navigateTo(event, VIEWS.TEMPLATE_IMPORT, id);
|
||||
},
|
||||
navigateTo(e: MouseEvent, page: string, id: string) {
|
||||
|
|
|
@ -67,6 +67,7 @@ import { workflowHelpers } from '@/mixins/workflowHelpers';
|
|||
import { setPageTitle } from '@/utils';
|
||||
import { VIEWS } from '@/constants';
|
||||
import { useTemplatesStore } from '@/stores/templates.store';
|
||||
import { usePostHog } from '@/stores/posthog.store';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TemplatesWorkflowView',
|
||||
|
@ -77,7 +78,7 @@ export default defineComponent({
|
|||
WorkflowPreview,
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useTemplatesStore),
|
||||
...mapStores(useTemplatesStore, usePostHog),
|
||||
template(): ITemplatesWorkflow | ITemplatesWorkflowFull {
|
||||
return this.templatesStore.getTemplateById(this.templateId);
|
||||
},
|
||||
|
@ -101,8 +102,9 @@ export default defineComponent({
|
|||
};
|
||||
|
||||
void this.$externalHooks().run('templatesWorkflowView.openWorkflow', telemetryPayload);
|
||||
this.$telemetry.track('User inserted workflow template', telemetryPayload);
|
||||
|
||||
this.$telemetry.track('User inserted workflow template', telemetryPayload, {
|
||||
withPostHog: true,
|
||||
});
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
const route = this.$router.resolve({ name: VIEWS.TEMPLATE_IMPORT, params: { id } });
|
||||
window.open(route.href, '_blank');
|
||||
|
|
Loading…
Reference in a new issue