diff --git a/app/api/rpc/[command]/get_publication_analytics.ts b/app/api/rpc/[command]/get_publication_analytics.ts index 540c4564..62c5ec60 100644 --- a/app/api/rpc/[command]/get_publication_analytics.ts +++ b/app/api/rpc/[command]/get_publication_analytics.ts @@ -21,7 +21,11 @@ export const get_publication_analytics = makeRoute({ { supabase }: Pick, ) => { const identity = await getIdentityData(); - if (!identity?.atp_did || !identity.entitlements?.publication_analytics || !identity.entitlements?.pro_plan_visible) { + if ( + !identity?.atp_did || + !identity.entitlements?.publication_analytics || + !identity.entitlements?.pro_plan_visible + ) { return { error: "unauthorized" as const }; } @@ -32,12 +36,15 @@ export const get_publication_analytics = makeRoute({ .eq("uri", publication_uri) .single(); - if (!publication || publication.identity_did !== identity.atp_did) { + if (!publication) { return { error: "not_found" as const }; } - const domain = publication.publication_domains?.[0]?.domain; - if (!domain) { + const domains = (publication.publication_domains ?? []) + .map((d) => d.domain) + .filter(Boolean) + .join(","); + if (!domains) { return { result: { traffic: [], topReferrers: [], topPages: [] }, }; @@ -45,20 +52,20 @@ export const get_publication_analytics = makeRoute({ const [trafficResult, referrersResult, pagesResult] = await Promise.all([ tinybird.publicationTraffic.query({ - domain, + domains, ...(from ? { date_from: from } : {}), ...(to ? { date_to: to } : {}), ...(path ? { path } : {}), }), tinybird.publicationTopReferrers.query({ - domain, + domains, ...(from ? { date_from: from } : {}), ...(to ? { date_to: to } : {}), ...(path ? { path } : {}), limit: 10, }), tinybird.publicationTopPages.query({ - domain, + domains, ...(from ? { date_from: from } : {}), ...(to ? { date_to: to } : {}), limit: 20, diff --git a/lib/tinybird.ts b/lib/tinybird.ts index 8262b5a7..d7211a9a 100644 --- a/lib/tinybird.ts +++ b/lib/tinybird.ts @@ -19,8 +19,11 @@ import { type InferRow, type InferParams, type InferOutputRow, + TokenDefinition, } from "@tinybirdco/sdk"; +const PROD_READ_TOKEN = { name: "prod_read_token_v1", scopes: ["READ"] }; + // ============================================================================ // Datasources // ============================================================================ @@ -87,11 +90,12 @@ export type AnalyticsEventsRow = InferRow; export const publicationTraffic = defineEndpoint("publication_traffic", { description: "Daily pageview time series for a publication domain", params: { - domain: p.string(), + domains: p.string(), date_from: p.string().optional(), date_to: p.string().optional(), path: p.string().optional(), }, + tokens: [PROD_READ_TOKEN], nodes: [ node({ name: "endpoint", @@ -102,7 +106,7 @@ export const publicationTraffic = defineEndpoint("publication_traffic", { uniq(deviceId) AS visitors FROM analytics_events WHERE eventType = 'pageview' - AND domain(origin) = {{String(domain)}} + AND domain(origin) IN splitByChar(',', {{String(domains)}}) {% if defined(date_from) %} AND fromUnixTimestamp64Milli(timestamp) >= parseDateTimeBestEffort({{String(date_from)}}) {% end %} @@ -125,7 +129,9 @@ export const publicationTraffic = defineEndpoint("publication_traffic", { }); export type PublicationTrafficParams = InferParams; -export type PublicationTrafficOutput = InferOutputRow; +export type PublicationTrafficOutput = InferOutputRow< + typeof publicationTraffic +>; /** * publication_top_referrers – top referring domains for a publication. @@ -133,9 +139,10 @@ export type PublicationTrafficOutput = InferOutputRow export const publicationTopReferrers = defineEndpoint( "publication_top_referrers", { + tokens: [PROD_READ_TOKEN], description: "Top referrers for a publication domain", params: { - domain: p.string(), + domains: p.string(), date_from: p.string().optional(), date_to: p.string().optional(), path: p.string().optional(), @@ -150,9 +157,9 @@ export const publicationTopReferrers = defineEndpoint( count() AS pageviews FROM analytics_events WHERE eventType = 'pageview' - AND domain(origin) = {{String(domain)}} + AND domain(origin) IN splitByChar(',', {{String(domains)}}) AND referrer != '' - AND domain(referrer) != {{String(domain)}} + AND domain(referrer) NOT IN splitByChar(',', {{String(domains)}}) {% if defined(date_from) %} AND fromUnixTimestamp64Milli(timestamp) >= parseDateTimeBestEffort({{String(date_from)}}) {% end %} @@ -187,8 +194,9 @@ export type PublicationTopReferrersOutput = InferOutputRow< */ export const publicationTopPages = defineEndpoint("publication_top_pages", { description: "Top pages for a publication domain", + tokens: [PROD_READ_TOKEN], params: { - domain: p.string(), + domains: p.string(), date_from: p.string().optional(), date_to: p.string().optional(), limit: p.int32().optional(10), @@ -202,7 +210,7 @@ export const publicationTopPages = defineEndpoint("publication_top_pages", { count() AS pageviews FROM analytics_events WHERE eventType = 'pageview' - AND domain(origin) = {{String(domain)}} + AND domain(origin) IN splitByChar(',', {{String(domains)}}) {% if defined(date_from) %} AND fromUnixTimestamp64Milli(timestamp) >= parseDateTimeBestEffort({{String(date_from)}}) {% end %}