@appeeky/spec 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +158 -5
- package/agents/appeeky-ads.md +50 -0
- package/agents/appeeky-aso.md +58 -0
- package/agents/appeeky-releases.md +47 -0
- package/agents/appeeky-reviews.md +53 -0
- package/agents/appeeky-social.md +54 -0
- package/agents/appeeky-ugc.md +56 -0
- package/agents/cofounder.md +36 -0
- package/dist/ads.d.ts +5 -2
- package/dist/ads.js +8 -4
- package/dist/agents.d.ts +47 -0
- package/dist/agents.js +88 -0
- package/dist/cli.js +582 -9
- package/dist/dataforseo.d.ts +139 -0
- package/dist/dataforseo.js +354 -0
- package/dist/experiments.d.ts +4 -4
- package/dist/metrics.d.ts +20 -0
- package/dist/metrics.js +4 -0
- package/dist/report.d.ts +5 -0
- package/dist/report.js +42 -0
- package/dist/reviews.d.ts +2 -2
- package/dist/schema.d.ts +95 -2
- package/dist/schema.js +35 -0
- package/dist/search-ads.d.ts +137 -0
- package/dist/search-ads.js +354 -0
- package/dist/seo.d.ts +87 -0
- package/dist/seo.js +391 -0
- package/dist/setup.js +39 -6
- package/dist/social.d.ts +129 -0
- package/dist/social.js +189 -0
- package/dist/transport.d.ts +1 -0
- package/dist/transport.js +1 -1
- package/dist/ugc-core.js +1 -0
- package/dist/ugc-local.d.ts +116 -0
- package/dist/ugc-local.js +174 -0
- package/dist/ugc.d.ts +149 -0
- package/dist/ugc.js +111 -0
- package/dist/visibility-core.js +96 -0
- package/dist/visibility-local.d.ts +159 -0
- package/dist/visibility-local.js +246 -0
- package/dist/visibility.d.ts +3 -0
- package/dist/visibility.js +1 -1
- package/package.json +7 -3
- package/skills/appeeky-spec/SKILL.md +14 -18
- package/skills/appeeky-spec-experiments/SKILL.md +12 -2
- package/skills/appeeky-spec-visibility/SKILL.md +33 -6
package/dist/schema.d.ts
CHANGED
|
@@ -30,16 +30,40 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
30
30
|
via: z.ZodDefault<z.ZodEnum<["auto", "local", "hosted"]>>;
|
|
31
31
|
/** Named account of the local `appstore` CLI. */
|
|
32
32
|
account: z.ZodOptional<z.ZodString>;
|
|
33
|
+
/**
|
|
34
|
+
* Apple Search Ads on your own API key (ASA_CLIENT_ID, ASA_TEAM_ID, ASA_KEY_ID, ASA_PRIVATE_KEY):
|
|
35
|
+
* `search-ads pull` reads this app's campaigns. Without it, Search Ads comes from Appeeky.
|
|
36
|
+
*/
|
|
37
|
+
searchAds: z.ZodOptional<z.ZodObject<{
|
|
38
|
+
/** The organization, when the key reaches more than one. */
|
|
39
|
+
orgId: z.ZodOptional<z.ZodString>;
|
|
40
|
+
/** Only these campaign ids; default: every campaign for this app. */
|
|
41
|
+
campaigns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
42
|
+
}, "strict", z.ZodTypeAny, {
|
|
43
|
+
orgId?: string | undefined;
|
|
44
|
+
campaigns?: string[] | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
orgId?: string | undefined;
|
|
47
|
+
campaigns?: string[] | undefined;
|
|
48
|
+
}>>;
|
|
33
49
|
}, "strict", z.ZodTypeAny, {
|
|
34
50
|
appId: string;
|
|
35
51
|
platform: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS";
|
|
36
52
|
via: "auto" | "local" | "hosted";
|
|
37
53
|
account?: string | undefined;
|
|
54
|
+
searchAds?: {
|
|
55
|
+
orgId?: string | undefined;
|
|
56
|
+
campaigns?: string[] | undefined;
|
|
57
|
+
} | undefined;
|
|
38
58
|
}, {
|
|
39
59
|
appId: string;
|
|
40
60
|
platform?: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS" | undefined;
|
|
41
61
|
via?: "auto" | "local" | "hosted" | undefined;
|
|
42
62
|
account?: string | undefined;
|
|
63
|
+
searchAds?: {
|
|
64
|
+
orgId?: string | undefined;
|
|
65
|
+
campaigns?: string[] | undefined;
|
|
66
|
+
} | undefined;
|
|
43
67
|
}>>;
|
|
44
68
|
googlePlay: z.ZodOptional<z.ZodObject<{
|
|
45
69
|
packageName: z.ZodString;
|
|
@@ -65,6 +89,10 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
65
89
|
platform: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS";
|
|
66
90
|
via: "auto" | "local" | "hosted";
|
|
67
91
|
account?: string | undefined;
|
|
92
|
+
searchAds?: {
|
|
93
|
+
orgId?: string | undefined;
|
|
94
|
+
campaigns?: string[] | undefined;
|
|
95
|
+
} | undefined;
|
|
68
96
|
} | undefined;
|
|
69
97
|
googlePlay?: {
|
|
70
98
|
via: "auto" | "local" | "hosted";
|
|
@@ -78,6 +106,10 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
78
106
|
platform?: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS" | undefined;
|
|
79
107
|
via?: "auto" | "local" | "hosted" | undefined;
|
|
80
108
|
account?: string | undefined;
|
|
109
|
+
searchAds?: {
|
|
110
|
+
orgId?: string | undefined;
|
|
111
|
+
campaigns?: string[] | undefined;
|
|
112
|
+
} | undefined;
|
|
81
113
|
} | undefined;
|
|
82
114
|
googlePlay?: {
|
|
83
115
|
packageName: string;
|
|
@@ -251,6 +283,10 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
251
283
|
description?: string | undefined;
|
|
252
284
|
prompts?: string[] | undefined;
|
|
253
285
|
}>, "many">>>;
|
|
286
|
+
/** Assistants `visibility scan --local` asks, among those with a key set; defaults to all of them. */
|
|
287
|
+
models: z.ZodOptional<z.ZodArray<z.ZodEnum<["chatgpt", "claude", "gemini", "perplexity"]>, "many">>;
|
|
288
|
+
/** Other names the assistants may use for the app, e.g. the brand without the subtitle. */
|
|
289
|
+
aliases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
254
290
|
}, "strict", z.ZodTypeAny, {
|
|
255
291
|
intents: Record<string, {
|
|
256
292
|
label: string;
|
|
@@ -259,6 +295,8 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
259
295
|
}[]>;
|
|
260
296
|
store?: "app-store" | "google-play" | undefined;
|
|
261
297
|
countries?: string[] | undefined;
|
|
298
|
+
models?: ("chatgpt" | "claude" | "gemini" | "perplexity")[] | undefined;
|
|
299
|
+
aliases?: string[] | undefined;
|
|
262
300
|
}, {
|
|
263
301
|
store?: "app-store" | "google-play" | undefined;
|
|
264
302
|
countries?: string[] | undefined;
|
|
@@ -267,6 +305,35 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
267
305
|
description?: string | undefined;
|
|
268
306
|
prompts?: string[] | undefined;
|
|
269
307
|
}[]> | undefined;
|
|
308
|
+
models?: ("chatgpt" | "claude" | "gemini" | "perplexity")[] | undefined;
|
|
309
|
+
aliases?: string[] | undefined;
|
|
310
|
+
}>>;
|
|
311
|
+
/**
|
|
312
|
+
* The app's website. `seo check` reads it for search and AI readiness; `seo pull` records
|
|
313
|
+
* its Google Search Console clicks with your own service account.
|
|
314
|
+
*/
|
|
315
|
+
web: z.ZodOptional<z.ZodObject<{
|
|
316
|
+
url: z.ZodString;
|
|
317
|
+
/** Search Console property: "sc-domain:example.com" or "https://example.com/"; defaults to the url's domain. */
|
|
318
|
+
searchConsole: z.ZodOptional<z.ZodString>;
|
|
319
|
+
/** Google searches to watch with `seo ranks` and `seo keywords`, per storefront; default: the store targets. */
|
|
320
|
+
keywords: z.ZodOptional<z.ZodRecord<z.ZodEffects<z.ZodString, string, string>, z.ZodArray<z.ZodString, "many">>>;
|
|
321
|
+
/** Storefronts to watch; default: the first one under keywords or targets. */
|
|
322
|
+
countries: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
|
|
323
|
+
/** The results page to read; default mobile, where people look for apps. */
|
|
324
|
+
device: z.ZodOptional<z.ZodEnum<["mobile", "desktop"]>>;
|
|
325
|
+
}, "strict", z.ZodTypeAny, {
|
|
326
|
+
url: string;
|
|
327
|
+
countries?: string[] | undefined;
|
|
328
|
+
searchConsole?: string | undefined;
|
|
329
|
+
keywords?: Record<string, string[]> | undefined;
|
|
330
|
+
device?: "mobile" | "desktop" | undefined;
|
|
331
|
+
}, {
|
|
332
|
+
url: string;
|
|
333
|
+
countries?: string[] | undefined;
|
|
334
|
+
searchConsole?: string | undefined;
|
|
335
|
+
keywords?: Record<string, string[]> | undefined;
|
|
336
|
+
device?: "mobile" | "desktop" | undefined;
|
|
270
337
|
}>>;
|
|
271
338
|
/** Rank in the app's category chart (top 100), recorded daily by `category pull`. */
|
|
272
339
|
category: z.ZodOptional<z.ZodObject<{
|
|
@@ -319,6 +386,10 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
319
386
|
platform: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS";
|
|
320
387
|
via: "auto" | "local" | "hosted";
|
|
321
388
|
account?: string | undefined;
|
|
389
|
+
searchAds?: {
|
|
390
|
+
orgId?: string | undefined;
|
|
391
|
+
campaigns?: string[] | undefined;
|
|
392
|
+
} | undefined;
|
|
322
393
|
} | undefined;
|
|
323
394
|
googlePlay?: {
|
|
324
395
|
via: "auto" | "local" | "hosted";
|
|
@@ -369,6 +440,15 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
369
440
|
}[]>;
|
|
370
441
|
store?: "app-store" | "google-play" | undefined;
|
|
371
442
|
countries?: string[] | undefined;
|
|
443
|
+
models?: ("chatgpt" | "claude" | "gemini" | "perplexity")[] | undefined;
|
|
444
|
+
aliases?: string[] | undefined;
|
|
445
|
+
} | undefined;
|
|
446
|
+
web?: {
|
|
447
|
+
url: string;
|
|
448
|
+
countries?: string[] | undefined;
|
|
449
|
+
searchConsole?: string | undefined;
|
|
450
|
+
keywords?: Record<string, string[]> | undefined;
|
|
451
|
+
device?: "mobile" | "desktop" | undefined;
|
|
372
452
|
} | undefined;
|
|
373
453
|
category?: {
|
|
374
454
|
appStore?: string | undefined;
|
|
@@ -388,6 +468,10 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
388
468
|
platform?: "IOS" | "MAC_OS" | "TV_OS" | "VISION_OS" | undefined;
|
|
389
469
|
via?: "auto" | "local" | "hosted" | undefined;
|
|
390
470
|
account?: string | undefined;
|
|
471
|
+
searchAds?: {
|
|
472
|
+
orgId?: string | undefined;
|
|
473
|
+
campaigns?: string[] | undefined;
|
|
474
|
+
} | undefined;
|
|
391
475
|
} | undefined;
|
|
392
476
|
googlePlay?: {
|
|
393
477
|
packageName: string;
|
|
@@ -432,6 +516,15 @@ export declare const specFileSchema: z.ZodObject<{
|
|
|
432
516
|
description?: string | undefined;
|
|
433
517
|
prompts?: string[] | undefined;
|
|
434
518
|
}[]> | undefined;
|
|
519
|
+
models?: ("chatgpt" | "claude" | "gemini" | "perplexity")[] | undefined;
|
|
520
|
+
aliases?: string[] | undefined;
|
|
521
|
+
} | undefined;
|
|
522
|
+
web?: {
|
|
523
|
+
url: string;
|
|
524
|
+
countries?: string[] | undefined;
|
|
525
|
+
searchConsole?: string | undefined;
|
|
526
|
+
keywords?: Record<string, string[]> | undefined;
|
|
527
|
+
device?: "mobile" | "desktop" | undefined;
|
|
435
528
|
} | undefined;
|
|
436
529
|
category?: {
|
|
437
530
|
appStore?: string | undefined;
|
|
@@ -464,8 +557,8 @@ export declare const appStoreListingSchema: z.ZodObject<{
|
|
|
464
557
|
}, "strict", z.ZodTypeAny, {
|
|
465
558
|
description?: string | undefined;
|
|
466
559
|
name?: string | undefined;
|
|
467
|
-
subtitle?: string | undefined;
|
|
468
560
|
keywords?: string | undefined;
|
|
561
|
+
subtitle?: string | undefined;
|
|
469
562
|
promotionalText?: string | undefined;
|
|
470
563
|
whatsNew?: string | undefined;
|
|
471
564
|
marketingUrl?: string | undefined;
|
|
@@ -473,8 +566,8 @@ export declare const appStoreListingSchema: z.ZodObject<{
|
|
|
473
566
|
}, {
|
|
474
567
|
description?: string | undefined;
|
|
475
568
|
name?: string | undefined;
|
|
476
|
-
subtitle?: string | undefined;
|
|
477
569
|
keywords?: string | undefined;
|
|
570
|
+
subtitle?: string | undefined;
|
|
478
571
|
promotionalText?: string | undefined;
|
|
479
572
|
whatsNew?: string | undefined;
|
|
480
573
|
marketingUrl?: string | undefined;
|
package/dist/schema.js
CHANGED
|
@@ -15,6 +15,19 @@ const appStoreConfig = z
|
|
|
15
15
|
via: transportMode.default("auto"),
|
|
16
16
|
/** Named account of the local `appstore` CLI. */
|
|
17
17
|
account: z.string().optional(),
|
|
18
|
+
/**
|
|
19
|
+
* Apple Search Ads on your own API key (ASA_CLIENT_ID, ASA_TEAM_ID, ASA_KEY_ID, ASA_PRIVATE_KEY):
|
|
20
|
+
* `search-ads pull` reads this app's campaigns. Without it, Search Ads comes from Appeeky.
|
|
21
|
+
*/
|
|
22
|
+
searchAds: z
|
|
23
|
+
.object({
|
|
24
|
+
/** The organization, when the key reaches more than one. */
|
|
25
|
+
orgId: z.string().regex(/^\d+$/, "Use the numeric org id from Apple Search Ads → Account Settings").optional(),
|
|
26
|
+
/** Only these campaign ids; default: every campaign for this app. */
|
|
27
|
+
campaigns: z.array(z.string().regex(/^\d+$/)).optional(),
|
|
28
|
+
})
|
|
29
|
+
.strict()
|
|
30
|
+
.optional(),
|
|
18
31
|
})
|
|
19
32
|
.strict();
|
|
20
33
|
const googlePlayConfig = z
|
|
@@ -140,6 +153,28 @@ export const specFileSchema = z
|
|
|
140
153
|
countries: z.array(countryCode).min(1).optional(),
|
|
141
154
|
/** What people ask AI assistants, per storefront. `visibility sync` sends them to Appeeky. */
|
|
142
155
|
intents: z.record(countryCode, z.array(aiIntent)).default({}),
|
|
156
|
+
/** Assistants `visibility scan --local` asks, among those with a key set; defaults to all of them. */
|
|
157
|
+
models: z.array(z.enum(["chatgpt", "claude", "gemini", "perplexity"])).min(1).optional(),
|
|
158
|
+
/** Other names the assistants may use for the app, e.g. the brand without the subtitle. */
|
|
159
|
+
aliases: z.array(z.string().min(2)).optional(),
|
|
160
|
+
})
|
|
161
|
+
.strict()
|
|
162
|
+
.optional(),
|
|
163
|
+
/**
|
|
164
|
+
* The app's website. `seo check` reads it for search and AI readiness; `seo pull` records
|
|
165
|
+
* its Google Search Console clicks with your own service account.
|
|
166
|
+
*/
|
|
167
|
+
web: z
|
|
168
|
+
.object({
|
|
169
|
+
url: z.string().url(),
|
|
170
|
+
/** Search Console property: "sc-domain:example.com" or "https://example.com/"; defaults to the url's domain. */
|
|
171
|
+
searchConsole: z.string().min(3).optional(),
|
|
172
|
+
/** Google searches to watch with `seo ranks` and `seo keywords`, per storefront; default: the store targets. */
|
|
173
|
+
keywords: z.record(countryCode, z.array(z.string().min(1))).optional(),
|
|
174
|
+
/** Storefronts to watch; default: the first one under keywords or targets. */
|
|
175
|
+
countries: z.array(countryCode).min(1).optional(),
|
|
176
|
+
/** The results page to read; default mobile, where people look for apps. */
|
|
177
|
+
device: z.enum(["mobile", "desktop"]).optional(),
|
|
143
178
|
})
|
|
144
179
|
.strict()
|
|
145
180
|
.optional(),
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { type Runner } from "./transport.js";
|
|
2
|
+
import type { MetricSource } from "./metrics.js";
|
|
3
|
+
import type { Project } from "./schema.js";
|
|
4
|
+
export declare const searchAdsDir: (root: string) => string;
|
|
5
|
+
export interface SearchAdsCredentials {
|
|
6
|
+
clientId: string;
|
|
7
|
+
teamId: string;
|
|
8
|
+
keyId: string;
|
|
9
|
+
privateKey: string;
|
|
10
|
+
orgId?: string;
|
|
11
|
+
}
|
|
12
|
+
/** ASA_* (or the APPLE_SEARCH_ADS_* spelling); null when no key is set. */
|
|
13
|
+
export declare function readSearchAdsCredentials(env: Record<string, string | undefined>, orgId?: string): Promise<SearchAdsCredentials | null>;
|
|
14
|
+
/** The client secret Apple wants: a JWT signed with the API key (ES256). */
|
|
15
|
+
export declare function clientSecret(creds: SearchAdsCredentials, now?: Date): string;
|
|
16
|
+
/** One Search Ads API call: returns Apple's JSON body, or throws with Apple's message. */
|
|
17
|
+
export type SearchAdsRequest = (method: string, path: string, body?: unknown) => Promise<{
|
|
18
|
+
data?: unknown;
|
|
19
|
+
}>;
|
|
20
|
+
/** Calls Apple directly with a key from the environment (ASA_*). */
|
|
21
|
+
export declare function directRequest(creds: SearchAdsCredentials, fetcher?: typeof fetch): {
|
|
22
|
+
request: SearchAdsRequest;
|
|
23
|
+
org: () => Promise<string>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Calls Apple through the App Store Connect CLI (`appstore search-ads call`), with the Search Ads key
|
|
27
|
+
* saved on an account next to its App Store Connect key, so the private key never leaves the CLI:
|
|
28
|
+
* appstore accounts search-ads <account> --client-id … --team-id … --key-id … --private-key-path …
|
|
29
|
+
*/
|
|
30
|
+
export declare function cliRequest(options?: {
|
|
31
|
+
account?: string;
|
|
32
|
+
orgId?: string;
|
|
33
|
+
runner?: Runner;
|
|
34
|
+
useNpx?: boolean;
|
|
35
|
+
}): {
|
|
36
|
+
request: SearchAdsRequest;
|
|
37
|
+
org: () => Promise<string>;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Where the Search Ads key comes from: ASA_* in the environment (called directly), else the
|
|
41
|
+
* App Store Connect CLI account in stores.appStore.account (or its default account).
|
|
42
|
+
*/
|
|
43
|
+
export declare function searchAdsSource(project: Project, env?: Record<string, string | undefined>, runner?: Runner): Promise<{
|
|
44
|
+
label: string;
|
|
45
|
+
source: SearchAdsCredentials;
|
|
46
|
+
} | {
|
|
47
|
+
label: string;
|
|
48
|
+
source: {
|
|
49
|
+
request: SearchAdsRequest;
|
|
50
|
+
org: () => Promise<string>;
|
|
51
|
+
};
|
|
52
|
+
}>;
|
|
53
|
+
export declare class SearchAdsClient {
|
|
54
|
+
private readonly request;
|
|
55
|
+
private readonly resolveOrg;
|
|
56
|
+
/** A key from the environment (calls Apple directly), or another way to call it, such as the appstore CLI. */
|
|
57
|
+
constructor(source: SearchAdsCredentials | {
|
|
58
|
+
request: SearchAdsRequest;
|
|
59
|
+
org: () => Promise<string>;
|
|
60
|
+
}, fetcher?: typeof fetch);
|
|
61
|
+
private call;
|
|
62
|
+
/** The organization the calls go to. */
|
|
63
|
+
org(): Promise<string>;
|
|
64
|
+
campaigns(): Promise<Campaign[]>;
|
|
65
|
+
/** Per campaign and day. */
|
|
66
|
+
daily(from: string, to: string): Promise<CampaignReportRow[]>;
|
|
67
|
+
/** Totals per keyword (or per search term) for one campaign. */
|
|
68
|
+
totals(campaignId: number | string, kind: "keywords" | "searchterms", from: string, to: string): Promise<TotalsRow[]>;
|
|
69
|
+
}
|
|
70
|
+
export interface Campaign {
|
|
71
|
+
id: number;
|
|
72
|
+
name: string;
|
|
73
|
+
adamId: number;
|
|
74
|
+
status?: string;
|
|
75
|
+
displayStatus?: string;
|
|
76
|
+
countriesOrRegions?: string[];
|
|
77
|
+
/** Where the ads show: only APPSTORE_SEARCH_RESULTS campaigns have keywords and search terms. */
|
|
78
|
+
supplySources?: string[];
|
|
79
|
+
adChannelType?: string;
|
|
80
|
+
}
|
|
81
|
+
interface Metrics {
|
|
82
|
+
impressions?: number;
|
|
83
|
+
taps?: number;
|
|
84
|
+
totalInstalls?: number;
|
|
85
|
+
installs?: number;
|
|
86
|
+
tapInstalls?: number;
|
|
87
|
+
localSpend?: {
|
|
88
|
+
amount: string;
|
|
89
|
+
currency: string;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export interface CampaignReportRow {
|
|
93
|
+
metadata: {
|
|
94
|
+
campaignId: number;
|
|
95
|
+
campaignName?: string;
|
|
96
|
+
adamId?: number;
|
|
97
|
+
};
|
|
98
|
+
granularity?: Array<Metrics & {
|
|
99
|
+
date: string;
|
|
100
|
+
}>;
|
|
101
|
+
}
|
|
102
|
+
export interface TotalsRow {
|
|
103
|
+
metadata: {
|
|
104
|
+
keyword?: string;
|
|
105
|
+
searchTermText?: string | null;
|
|
106
|
+
matchType?: string;
|
|
107
|
+
countryOrRegion?: string;
|
|
108
|
+
countriesOrRegions?: string[];
|
|
109
|
+
keywordStatus?: string;
|
|
110
|
+
};
|
|
111
|
+
total?: Metrics;
|
|
112
|
+
}
|
|
113
|
+
export interface SearchAdsPullResult {
|
|
114
|
+
orgId: string;
|
|
115
|
+
campaigns: Array<{
|
|
116
|
+
id: number;
|
|
117
|
+
name: string;
|
|
118
|
+
status?: string;
|
|
119
|
+
}>;
|
|
120
|
+
currency?: string;
|
|
121
|
+
last30: {
|
|
122
|
+
spend: number;
|
|
123
|
+
installs: number;
|
|
124
|
+
taps: number;
|
|
125
|
+
impressions: number;
|
|
126
|
+
};
|
|
127
|
+
keywords: number;
|
|
128
|
+
searchTerms: number;
|
|
129
|
+
/** Reports that could not be read; the rest were written. */
|
|
130
|
+
errors: string[];
|
|
131
|
+
files: string[];
|
|
132
|
+
}
|
|
133
|
+
/** The App Store app's campaigns only: ads for other apps in the same organization stay out. */
|
|
134
|
+
export declare function pullSearchAds(project: Project, client: SearchAdsClient, now?: Date, days?: number): Promise<SearchAdsPullResult>;
|
|
135
|
+
/** `ad_installs` and `cpa` per day from appeeky/search-ads/daily.csv, for the App Store app. */
|
|
136
|
+
export declare function searchAdsMetricSource(root: string): MetricSource | null;
|
|
137
|
+
export {};
|