Frontend UTM Tracking Guidelines
This guide explains how to track frontend interactions with UTM parameters in both Vue components and vanilla JavaScript.
When to use UTM tracking
- Track clicks on important UI actions (buttons, menu actions, external links).
- Track GraphQL operations where campaign attribution is needed.
- Track elapsed time between form load and submit when this context matters.
Shared types and endpoint contract
- Frontend campaign/type definitions are in
app/frontend/src/shared/types/utm.ts. - REST tracking client is in
app/frontend/src/shared/api/utmApi.ts. - GraphQL URL helper is in
app/frontend/src/shared/utils/utm.ts. - Backend endpoint is
GET /utm_trackingineasy_engines/easy_extensions/config/routes.rb. - Endpoint action responds with
204 No Contentineasy_engines/easy_extensions/app/controllers/analytics_controller.rb.
1) Click tracking with REST endpoint
Use utmApi.sendUTMTrackingData(...) for regular click/event tracking.
Vue example
import { utmApi } from "@/src/shared/api/utmApi";
const openWebinar = async () => {
await utmApi.sendUTMTrackingData({
utmCampaign: "news",
utmContent: "news_onboarding",
utmTerm: "webinar",
});
window.open("https://example.com/webinar", "_blank");
};
Vanilla JavaScript example (no imports)
Use this when your script is built separately and you only want to call the REST endpoint.
async function trackUTM({ utmCampaign, utmContent, utmTerm }) {
const params = new URLSearchParams({
utm_campaign: utmCampaign,
utm_content: utmContent,
utm_term: utmTerm,
format: "json",
});
await fetch(`/utm_tracking?${params.toString()}`, {
method: "GET",
credentials: "same-origin",
});
}
document.getElementById("my-button")?.addEventListener("click", () => {
trackUTM({
utmCampaign: "menu",
utmContent: "react_widget",
utmTerm: "open_details",
}).catch(() => {});
});
React one-liner (no imports)
onClick={() => fetch(`/utm_tracking?${new URLSearchParams({ utm_campaign: "menu", utm_content: "react_widget", utm_term: "open_details", format: "json" })}`, { method: "GET", credentials: "same-origin" }).catch(() => {})}
2) GraphQL request tracking
Use getGraphqlUriWithUtmParams(...) when a GraphQL request should include UTM parameters.
import { getGraphqlUriWithUtmParams } from "@/src/shared/utils/utm";
const uri = getGraphqlUriWithUtmParams(
{
utm_campaign: "spent_time",
utm_content: "log_time_form_v2",
},
"create"
);
// Apollo context:
// context: { uri }
3) Elapsed time tracking (utm_time)
Vue composable approach
Use useUTMTimeTracker(...) to measure elapsed time and attach it to UTM params.
import { useUTMTimeTracker } from "@/src/shared/composables/useUTMTimeTracker";
const { getUTMParams, restartTimer } = useUTMTimeTracker({
utm_campaign: "spent_time",
utm_content: "log_time_form_v2",
});
const submit = () => {
const params = getUTMParams("create");
// params contains utm_time and utm_term
};
restartTimer();
Form helper approach (works outside Vue)
Use useUTMTimeOnForm(...) to update form action URL on submit with utm_campaign, utm_content, utm_term, and utm_time.
import { useUTMTimeOnForm } from "@/src/shared/utils/utm";
useUTMTimeOnForm("my-form-id", {
utmCampaign: "menu",
utmContent: "my_form",
utmTerm: "submit",
});
Naming conventions
utm_campaign: feature/domain name (must matchUTMCampaignunion).utm_content: UI area or action group.utm_term: specific action, state, or entity identifier.utm_time: elapsed milliseconds (string), when applicable.
Prefer constants for repeated values (for example constants/utm.ts in feature modules).
Real examples in this repository
Click tracking
- Vue:
app/frontend/src/modals/newsOnboarding/components/NewsOnboardingActions.vue - Vue:
app/frontend/src/easy_help_feedback/EasyHelpFeedback.vue - Vanilla JS:
app/frontend/src/easy_legacy_js/automations_webhook.ts
GraphQL URI tracking
app/frontend/src/log_time/api/timeEntryApi.tsapp/frontend/src/easy_automations/rules_execution/api/rulesExecutionApi.ts
Shared utilities
app/frontend/src/shared/api/utmApi.tsapp/frontend/src/shared/utils/utm.tsapp/frontend/src/shared/composables/useUTMTimeTracker.ts
Tests
app/frontend/src/tests/tests/shared/tests/utils/utm.spec.tsapp/frontend/src/tests/tests/easy_legacy_js/automations_webhook.spec.tsapp/frontend/src/tests/tests/modals/tests/news_onboarding/tests/newsOnboardingActions.spec.ts