import {z} from 'zod' export type Date = {day?: number | undefined, month?: number | undefined, year?: number | undefined}; export type DateRange = {endDate?: Date | undefined, startDate?: Date | undefined}; export type CampaignDuration = {dateRange?: DateRange | undefined, durationDays?: number | undefined}; export type FrequencyCap = {maxImpressions?: number | undefined, maxViews?: number | undefined, timeUnit?: ('TIME_UNIT_UNSPECIFIED' | 'TIME_UNIT_LIFETIME' | 'TIME_UNIT_MONTHS' | 'TIME_UNIT_WEEKS' | 'TIME_UNIT_DAYS' | 'TIME_UNIT_HOURS' | 'TIME_UNIT_MINUTES') | undefined, timeUnitCount?: number | undefined, unlimited?: boolean | undefined}; export type SurfaceTargetingSettings = {surfaces?: (Array<'PLANNABLE_SURFACE_UNSPECIFIED' | 'PLANNABLE_SURFACE_IN_FEED' | 'PLANNABLE_SURFACE_IN_STREAM_BUMPER' | 'PLANNABLE_SURFACE_IN_STREAM_NON_SKIPPABLE' | 'PLANNABLE_SURFACE_IN_STREAM_SKIPPABLE' | 'PLANNABLE_SURFACE_SHORTS' | 'PLANNABLE_SURFACE_DISCOVER_FEED' | 'PLANNABLE_SURFACE_GMAIL' | 'PLANNABLE_SURFACE_GOOGLE_DISPLAY_NETWORK' | 'PLANNABLE_SURFACE_IN_STREAM_NON_SKIPPABLE_THIRTY_SECONDS'>) | undefined}; export type TargetFrequency = {targetCount?: unknown | undefined, timeUnit?: ('TIME_UNIT_UNSPECIFIED' | 'TIME_UNIT_LIFETIME' | 'TIME_UNIT_MONTHS' | 'TIME_UNIT_WEEKS' | 'TIME_UNIT_DAYS' | 'TIME_UNIT_HOURS' | 'TIME_UNIT_MINUTES') | undefined, timeUnitCount?: number | undefined}; export type YouTubeSelectSettings = {lineupId?: unknown | undefined}; export type AdvancedProductTargeting = {ageRange?: ('PLANNABLE_AGE_RANGE_UNSPECIFIED' | 'PLANNABLE_AGE_RANGE_18_24' | 'PLANNABLE_AGE_RANGE_18_34' | 'PLANNABLE_AGE_RANGE_18_44' | 'PLANNABLE_AGE_RANGE_18_49' | 'PLANNABLE_AGE_RANGE_18_54' | 'PLANNABLE_AGE_RANGE_18_64' | 'PLANNABLE_AGE_RANGE_18_65_UP' | 'PLANNABLE_AGE_RANGE_21_34' | 'PLANNABLE_AGE_RANGE_21_44' | 'PLANNABLE_AGE_RANGE_21_49' | 'PLANNABLE_AGE_RANGE_21_54' | 'PLANNABLE_AGE_RANGE_21_64' | 'PLANNABLE_AGE_RANGE_21_65_UP' | 'PLANNABLE_AGE_RANGE_25_34' | 'PLANNABLE_AGE_RANGE_25_44' | 'PLANNABLE_AGE_RANGE_25_49' | 'PLANNABLE_AGE_RANGE_25_54' | 'PLANNABLE_AGE_RANGE_25_64' | 'PLANNABLE_AGE_RANGE_25_65_UP' | 'PLANNABLE_AGE_RANGE_35_44' | 'PLANNABLE_AGE_RANGE_35_49' | 'PLANNABLE_AGE_RANGE_35_54' | 'PLANNABLE_AGE_RANGE_35_64' | 'PLANNABLE_AGE_RANGE_35_65_UP' | 'PLANNABLE_AGE_RANGE_45_54' | 'PLANNABLE_AGE_RANGE_45_64' | 'PLANNABLE_AGE_RANGE_45_65_UP' | 'PLANNABLE_AGE_RANGE_50_65_UP' | 'PLANNABLE_AGE_RANGE_55_64' | 'PLANNABLE_AGE_RANGE_55_65_UP' | 'PLANNABLE_AGE_RANGE_65_UP') | undefined, dateRange?: DateRange | undefined, devices?: (Array<'DEVICE_TYPE_UNSPECIFIED' | 'DEVICE_TYPE_COMPUTER' | 'DEVICE_TYPE_CONNECTED_TV' | 'DEVICE_TYPE_SMART_PHONE' | 'DEVICE_TYPE_TABLET' | 'DEVICE_TYPE_CONNECTED_DEVICE'>) | undefined, frequencyCap?: FrequencyCap | undefined, genders?: (Array<'GENDER_UNSPECIFIED' | 'GENDER_MALE' | 'GENDER_FEMALE' | 'GENDER_UNKNOWN'>) | undefined, network?: ('PLANNABLE_NETWORK_UNSPECIFIED' | 'PLANNABLE_NETWORK_YOUTUBE' | 'PLANNABLE_NETWORK_GOOGLE_VIDEO_PARTNERS' | 'PLANNABLE_NETWORK_YOUTUBE_AND_GOOGLE_VIDEO_PARTNERS') | undefined, plannableLocationIds?: Array | undefined, surfaceTargetingSettings?: SurfaceTargetingSettings | undefined, targetFrequency?: TargetFrequency | undefined, userInterestIds?: Array | undefined, userListIds?: Array | undefined, youtubeSelectSettings?: YouTubeSelectSettings | undefined}; export type PlannedProduct = {advancedProductTargeting?: AdvancedProductTargeting | undefined, budgetMicros?: unknown | undefined, plannableProductCode?: string | undefined}; export type Targeting = {ageRange?: ('PLANNABLE_AGE_RANGE_UNSPECIFIED' | 'PLANNABLE_AGE_RANGE_18_24' | 'PLANNABLE_AGE_RANGE_18_34' | 'PLANNABLE_AGE_RANGE_18_44' | 'PLANNABLE_AGE_RANGE_18_49' | 'PLANNABLE_AGE_RANGE_18_54' | 'PLANNABLE_AGE_RANGE_18_64' | 'PLANNABLE_AGE_RANGE_18_65_UP' | 'PLANNABLE_AGE_RANGE_21_34' | 'PLANNABLE_AGE_RANGE_21_44' | 'PLANNABLE_AGE_RANGE_21_49' | 'PLANNABLE_AGE_RANGE_21_54' | 'PLANNABLE_AGE_RANGE_21_64' | 'PLANNABLE_AGE_RANGE_21_65_UP' | 'PLANNABLE_AGE_RANGE_25_34' | 'PLANNABLE_AGE_RANGE_25_44' | 'PLANNABLE_AGE_RANGE_25_49' | 'PLANNABLE_AGE_RANGE_25_54' | 'PLANNABLE_AGE_RANGE_25_64' | 'PLANNABLE_AGE_RANGE_25_65_UP' | 'PLANNABLE_AGE_RANGE_35_44' | 'PLANNABLE_AGE_RANGE_35_49' | 'PLANNABLE_AGE_RANGE_35_54' | 'PLANNABLE_AGE_RANGE_35_64' | 'PLANNABLE_AGE_RANGE_35_65_UP' | 'PLANNABLE_AGE_RANGE_45_54' | 'PLANNABLE_AGE_RANGE_45_64' | 'PLANNABLE_AGE_RANGE_45_65_UP' | 'PLANNABLE_AGE_RANGE_50_65_UP' | 'PLANNABLE_AGE_RANGE_55_64' | 'PLANNABLE_AGE_RANGE_55_65_UP' | 'PLANNABLE_AGE_RANGE_65_UP') | undefined, devices?: (Array<'DEVICE_TYPE_UNSPECIFIED' | 'DEVICE_TYPE_COMPUTER' | 'DEVICE_TYPE_CONNECTED_TV' | 'DEVICE_TYPE_SMART_PHONE' | 'DEVICE_TYPE_TABLET' | 'DEVICE_TYPE_CONNECTED_DEVICE'>) | undefined, genders?: (Array<'GENDER_UNSPECIFIED' | 'GENDER_MALE' | 'GENDER_FEMALE' | 'GENDER_UNKNOWN'>) | undefined, plannableLocationIds?: Array | undefined}; export type GenerateReachForecastRequest = {campaignDuration?: CampaignDuration | undefined, currencyCode?: string | undefined, minEffectiveFrequency?: number | undefined, plannedProducts?: Array | undefined, targeting?: Targeting | undefined}; export type CreateApiV4AdvertisersAdvertisersIdReachForecastGenerateReachForecastArgs = {advertisersId: string, body: GenerateReachForecastRequest}; export type CreateApiV4AdvertisersAdvertisersIdReachForecastGenerateReachForecastOptions = {baseUrl?: string | undefined, Oauth2?: string | undefined, Oauth2c?: string | undefined, fetch?: typeof fetch | undefined}; export const onTargetAudienceMetrics = z.object({censusAudienceSize: z.string().optional(), youtubeAudienceSize: z.string().optional()}); export const plannedProductForecast = z.object({onTargetCoviewImpressions: z.string().optional(), onTargetCoviewReach: z.string().optional(), onTargetImpressions: z.string().optional(), onTargetReach: z.string().optional(), totalCoviewImpressions: z.string().optional(), totalCoviewReach: z.string().optional(), totalImpressions: z.string().optional(), totalReach: z.string().optional(), trueviewViews: z.string().optional(), viewableImpressions: z.string().optional()}); export const plannedProductReachForecast = z.object({costMicros: z.string().optional(), plannableProductCode: z.string().optional(), plannedProductForecast: plannedProductForecast.optional()}); export const reachForecast = z.object({costMicros: z.string().optional(), forecast: plannedProductForecast.optional(), plannedProductReachForecasts: z.array(plannedProductReachForecast).optional()}); export const reachCurve = z.object({reachForecasts: z.array(reachForecast).optional()}); export const generateReachForecastResponse = z.object({onTargetAudienceMetrics: onTargetAudienceMetrics.optional(), reachCurve: reachCurve.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Generates a reach forecast for a given advertiser and targeting configuration. API support for generating reach forecasts and retrieving related metadata is in beta. This method is only available to allowlisted users. * * POST /v4/advertisers/{advertisersId}/reachForecast:generateReachForecast */ export const createApiV4AdvertisersAdvertisersIdReachForecastGenerateReachForecast = async (args: CreateApiV4AdvertisersAdvertisersIdReachForecastGenerateReachForecastArgs, options?: CreateApiV4AdvertisersAdvertisersIdReachForecastGenerateReachForecastOptions) => { const {baseUrl = "https://displayvideo.googleapis.com", fetch: fetchFn = fetch, Oauth2, Oauth2c} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (Oauth2 !== undefined) headers.set('authorization', `Bearer ${Oauth2}`) if (Oauth2c !== undefined) headers.set('authorization', `Bearer ${Oauth2c}`) const url = `${baseUrl.replace(/\/+$/, '')}/v4/advertisers/${encodeURIComponent(String(args.advertisersId))}/reachForecast:generateReachForecast${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(generateReachForecastResponse, await res.json()) };