Skip to content

Commit

Permalink
Merge branch 'main' into referrals-tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
devkiran authored Nov 23, 2024
2 parents 5fd2b83 + e20dd78 commit 637ed3f
Show file tree
Hide file tree
Showing 35 changed files with 4,095 additions and 44 deletions.
5 changes: 4 additions & 1 deletion apps/web/lib/analytics/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const VALID_ANALYTICS_ENDPOINTS = [
"count",
"timeseries",
"continents",
"regions",
"countries",
"cities",
"devices",
Expand All @@ -116,6 +117,7 @@ export const VALID_ANALYTICS_ENDPOINTS = [

export const SINGULAR_ANALYTICS_ENDPOINTS = {
continents: "continent",
regions: "region",
countries: "country",
cities: "city",
devices: "device",
Expand All @@ -132,9 +134,10 @@ export const VALID_ANALYTICS_FILTERS = [
"interval",
"start",
"end",
"continent",
"country",
"city",
"region",
"continent",
"device",
"browser",
"os",
Expand Down
10 changes: 10 additions & 0 deletions apps/web/lib/analytics/get-analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const getAnalytics = async (params: AnalyticsFilters) => {
end,
qr,
trigger,
region,
country,
timezone = "UTC",
isDemo,
isDeprecatedClicksEndpoint = false,
Expand Down Expand Up @@ -68,6 +70,12 @@ export const getAnalytics = async (params: AnalyticsFilters) => {
}
}

if (region) {
const split = region.split("-");
country = split[0];
region = split[1];
}

// Create a Tinybird pipe
const pipe = (isDemo ? tbDemo : tb).buildPipe({
pipe: `v2_${groupBy}`,
Expand All @@ -85,6 +93,8 @@ export const getAnalytics = async (params: AnalyticsFilters) => {
end: endDate.toISOString().replace("T", " ").replace("Z", ""),
granularity,
timezone,
country,
region,
});

if (groupBy === "count") {
Expand Down
13 changes: 12 additions & 1 deletion apps/web/lib/analytics/get-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export const getEvents = async (params: EventsFilters) => {
end,
qr,
trigger,
region,
country,
isDemo,
} = params;

Expand All @@ -49,6 +51,12 @@ export const getEvents = async (params: EventsFilters) => {
}
}

if (region) {
const split = region.split("-");
country = split[0];
region = split[1];
}

const pipe = (isDemo ? tbDemo : tb).buildPipe({
pipe: "v2_events",
parameters: eventsFilterTB,
Expand All @@ -65,6 +73,8 @@ export const getEvents = async (params: EventsFilters) => {
eventType,
workspaceId,
qr,
country,
region,
offset: (params.page - 1) * params.limit,
start: startDate.toISOString().replace("T", " ").replace("Z", ""),
end: endDate.toISOString().replace("T", " ").replace("Z", ""),
Expand Down Expand Up @@ -101,7 +111,8 @@ export const getEvents = async (params: EventsFilters) => {
click: clickEventSchema.parse({
...evt,
id: evt.click_id,
// normalize referer_url_processed to camelCase
// normalize processed values
region: evt.region_processed ?? "",
refererUrl: evt.referer_url_processed ?? "",
}),
// transformLink -> add shortLink, qrCode, workspaceId, etc.
Expand Down
3 changes: 0 additions & 3 deletions apps/web/lib/analytics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ export type EventType = (typeof EVENT_TYPES)[number];

export type AnalyticsView = (typeof ANALYTICS_VIEWS)[number];

export type LocationTabs = "countries" | "cities";
export type TopLinksTabs = "link" | "url";
export type DeviceTabs = "devices" | "browsers" | "os" | "triggers";
export type RefererTabs = "referers" | "referer_urls";

export type AnalyticsFilters = z.infer<typeof analyticsQuerySchema> & {
workspaceId?: string;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/lib/tinybird/record-click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ export async function recordClick({
typeof ip === "string" && ip.trim().length > 0 && !isEuCountry ? ip : "",
continent: continent || "",
country: geo.country || "Unknown",
city: geo.city || "Unknown",
region: region || "Unknown",
city: geo.city || "Unknown",
latitude: geo.latitude || "Unknown",
longitude: geo.longitude || "Unknown",
vercel_region: req.headers.get("x-vercel-id") || "",
Expand Down
29 changes: 29 additions & 0 deletions apps/web/lib/zod/schemas/analytics-response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,35 @@ export const analyticsResponse = {
})
.openapi({ ref: "AnalyticsCountries" }),

regions: z
.object({
region: z
.string()
.describe(
"The 2-letter ISO 3166-2 region code representing the region associated with the location of the user.",
),
country: z
.enum(COUNTRY_CODES)
.describe("The 2-letter country code of the region: https://d.to/geo"),
clicks: z
.number()
.describe("The number of clicks from this region")
.default(0),
leads: z
.number()
.describe("The number of leads from this region")
.default(0),
sales: z
.number()
.describe("The number of sales from this region")
.default(0),
saleAmount: z
.number()
.describe("The total amount of sales from this region, in cents")
.default(0),
})
.openapi({ ref: "AnalyticsRegions" }),

cities: z
.object({
city: z.string().describe("The name of the city"),
Expand Down
16 changes: 11 additions & 5 deletions apps/web/lib/zod/schemas/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,6 @@ export const analyticsQuerySchema = z.object({
"The IANA time zone code for aligning timeseries granularity (e.g. America/New_York). Defaults to UTC.",
)
.openapi({ example: "America/New_York", default: "UTC" }),
continent: z
.enum(CONTINENT_CODES)
.optional()
.describe("The continent to retrieve analytics for.")
.openapi({ ref: "continentCode" }),
country: z
.enum(COUNTRY_CODES)
.optional()
Expand All @@ -122,6 +117,16 @@ export const analyticsQuerySchema = z.object({
.optional()
.describe("The city to retrieve analytics for.")
.openapi({ example: "New York" }),
region: z
.string()
.optional()
.describe("The ISO 3166-2 region code to retrieve analytics for.")
.openapi({ ref: "regionCode" }),
continent: z
.enum(CONTINENT_CODES)
.optional()
.describe("The continent to retrieve analytics for.")
.openapi({ ref: "continentCode" }),
device: z
.string()
.optional()
Expand Down Expand Up @@ -213,6 +218,7 @@ export const analyticsFilterTB = z
city: true,
country: true,
continent: true,
region: true,
device: true,
domain: true,
linkId: true,
Expand Down
9 changes: 6 additions & 3 deletions apps/web/lib/zod/schemas/clicks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const clickEventSchemaTB = z.object({
url: z.string(),
continent: z.string().nullable(),
country: z.string().nullable(),
city: z.string().nullable(),
region: z.string().nullable(),
city: z.string().nullable(),
latitude: z.string().nullable(),
longitude: z.string().nullable(),
device: z.string().nullable(),
Expand All @@ -37,9 +37,11 @@ export const clickEventSchemaTBEndpoint = z.object({
click_id: z.string(),
link_id: z.string(),
url: z.string(),
continent: z.string().nullable(),
country: z.string().nullable(),
city: z.string().nullable(),
region: z.string().nullable(),
region_processed: z.string().nullable(),
continent: z.string().nullable(),
device: z.string().nullable(),
browser: z.string().nullable(),
os: z.string().nullable(),
Expand All @@ -53,9 +55,10 @@ export const clickEventSchemaTBEndpoint = z.object({
export const clickEventSchema = z.object({
id: z.string(),
url: z.string(),
continent: z.string(),
country: z.string(),
city: z.string(),
region: z.string(),
continent: z.string(),
device: z.string(),
browser: z.string(),
os: z.string(),
Expand Down
2 changes: 2 additions & 0 deletions apps/web/lib/zod/schemas/leads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ export const leadEventSchemaTBEndpoint = z.object({
continent: z.string().nullable(),
country: z.string().nullable(),
city: z.string().nullable(),
region: z.string().nullable(),
region_processed: z.string().nullable(),
device: z.string().nullable(),
browser: z.string().nullable(),
os: z.string().nullable(),
Expand Down
2 changes: 2 additions & 0 deletions apps/web/lib/zod/schemas/sales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export const saleEventSchemaTBEndpoint = z.object({
continent: z.string().nullable(),
country: z.string().nullable(),
city: z.string().nullable(),
region: z.string().nullable(),
region_processed: z.string().nullable(),
device: z.string().nullable(),
browser: z.string().nullable(),
os: z.string().nullable(),
Expand Down
67 changes: 48 additions & 19 deletions apps/web/ui/analytics/events/events-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { CursorRays, Globe, Magnifier, QRCode } from "@dub/ui/src/icons";
import {
CONTINENTS,
COUNTRIES,
REGIONS,
capitalize,
currencyFormatter,
fetcher,
Expand Down Expand Up @@ -205,25 +206,6 @@ export default function EventsTable({
);
},
},
{
id: "continent",
header: "Continent",
accessorKey: "click.continent",
meta: {
filterParams: ({ getValue }) => ({ continent: getValue() }),
},
cell: ({ getValue }) => (
<div
className="flex items-center gap-3"
title={CONTINENTS[getValue()] ?? "Unknown"}
>
<ContinentIcon display={getValue()} className="size-4 shrink-0" />
<span className="truncate">
{CONTINENTS[getValue()] ?? "Unknown"}
</span>
</div>
),
},
{
id: "country",
header: "Country",
Expand Down Expand Up @@ -255,6 +237,9 @@ export default function EventsTable({
id: "city",
header: "City",
accessorKey: "click.city",
meta: {
filterParams: ({ getValue }) => ({ city: getValue() }),
},
minSize: 160,
cell: ({ getValue, row }) => (
<div className="flex items-center gap-3" title={getValue()}>
Expand All @@ -271,6 +256,50 @@ export default function EventsTable({
</div>
),
},
{
id: "region",
header: "Region",
accessorKey: "click.region",
meta: {
filterParams: ({ getValue }) => ({ region: getValue() }),
},
minSize: 160,
cell: ({ getValue, row }) => (
<div className="flex items-center gap-3" title={getValue()}>
{!row.original.country || row.original.country === "Unknown" ? (
<Globe className="size-4 shrink-0" />
) : (
<img
alt={row.original.country}
src={`https://hatscripts.github.io/circle-flags/flags/${row.original.country.toLowerCase()}.svg`}
className="size-4 shrink-0"
/>
)}
<span className="truncate">
{REGIONS[getValue()] || getValue().split("-")[1]}
</span>
</div>
),
},
{
id: "continent",
header: "Continent",
accessorKey: "click.continent",
meta: {
filterParams: ({ getValue }) => ({ continent: getValue() }),
},
cell: ({ getValue }) => (
<div
className="flex items-center gap-3"
title={CONTINENTS[getValue()] ?? "Unknown"}
>
<ContinentIcon display={getValue()} className="size-4 shrink-0" />
<span className="truncate">
{CONTINENTS[getValue()] ?? "Unknown"}
</span>
</div>
),
},
{
id: "device",
header: "Device",
Expand Down
9 changes: 6 additions & 3 deletions apps/web/ui/analytics/events/use-column-visibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ export const getEventColumns: (
all: [
"trigger",
...(!partners ? ["link"] : []),
"continent",
"country",
"city",
"region",
"continent",
"device",
"browser",
"os",
Expand All @@ -36,9 +37,10 @@ export const getEventColumns: (
"event",
...(!partners ? ["link"] : []),
"customer",
"continent",
"country",
"city",
"region",
"continent",
"device",
"browser",
"os",
Expand All @@ -61,9 +63,10 @@ export const getEventColumns: (
"event",
"customer",
...(!partners ? ["link", "invoiceId"] : []),
"continent",
"country",
"city",
"region",
"continent",
"device",
"browser",
"os",
Expand Down
Loading

0 comments on commit 637ed3f

Please sign in to comment.