@miranda0808/maya-codex 0.1.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.
Files changed (270) hide show
  1. package/README.md +30 -0
  2. package/bin/maya-codex.js +36 -0
  3. package/package.json +19 -0
  4. package/payload/.agents/skills/ab-test-setup/SKILL.md +266 -0
  5. package/payload/.agents/skills/ab-test-setup/evals/evals.json +105 -0
  6. package/payload/.agents/skills/ab-test-setup/references/sample-size-guide.md +263 -0
  7. package/payload/.agents/skills/ab-test-setup/references/test-templates.md +277 -0
  8. package/payload/.agents/skills/ad-creative/SKILL.md +362 -0
  9. package/payload/.agents/skills/ad-creative/evals/evals.json +90 -0
  10. package/payload/.agents/skills/ad-creative/references/generative-tools.md +637 -0
  11. package/payload/.agents/skills/ad-creative/references/platform-specs.md +213 -0
  12. package/payload/.agents/skills/ai-seo/SKILL.md +398 -0
  13. package/payload/.agents/skills/ai-seo/evals/evals.json +90 -0
  14. package/payload/.agents/skills/ai-seo/references/content-patterns.md +285 -0
  15. package/payload/.agents/skills/ai-seo/references/platform-ranking-factors.md +152 -0
  16. package/payload/.agents/skills/analytics-tracking/SKILL.md +309 -0
  17. package/payload/.agents/skills/analytics-tracking/evals/evals.json +90 -0
  18. package/payload/.agents/skills/analytics-tracking/references/event-library.md +260 -0
  19. package/payload/.agents/skills/analytics-tracking/references/ga4-implementation.md +300 -0
  20. package/payload/.agents/skills/analytics-tracking/references/gtm-implementation.md +390 -0
  21. package/payload/.agents/skills/churn-prevention/SKILL.md +424 -0
  22. package/payload/.agents/skills/churn-prevention/evals/evals.json +93 -0
  23. package/payload/.agents/skills/churn-prevention/references/cancel-flow-patterns.md +316 -0
  24. package/payload/.agents/skills/churn-prevention/references/dunning-playbook.md +408 -0
  25. package/payload/.agents/skills/cold-email/SKILL.md +158 -0
  26. package/payload/.agents/skills/cold-email/evals/evals.json +94 -0
  27. package/payload/.agents/skills/cold-email/references/benchmarks.md +83 -0
  28. package/payload/.agents/skills/cold-email/references/follow-up-sequences.md +81 -0
  29. package/payload/.agents/skills/cold-email/references/frameworks.md +90 -0
  30. package/payload/.agents/skills/cold-email/references/personalization.md +79 -0
  31. package/payload/.agents/skills/cold-email/references/subject-lines.md +53 -0
  32. package/payload/.agents/skills/competitor-alternatives/SKILL.md +256 -0
  33. package/payload/.agents/skills/competitor-alternatives/evals/evals.json +93 -0
  34. package/payload/.agents/skills/competitor-alternatives/references/content-architecture.md +271 -0
  35. package/payload/.agents/skills/competitor-alternatives/references/templates.md +223 -0
  36. package/payload/.agents/skills/content-strategy/SKILL.md +359 -0
  37. package/payload/.agents/skills/content-strategy/evals/evals.json +90 -0
  38. package/payload/.agents/skills/copy-editing/SKILL.md +447 -0
  39. package/payload/.agents/skills/copy-editing/evals/evals.json +89 -0
  40. package/payload/.agents/skills/copy-editing/references/plain-english-alternatives.md +394 -0
  41. package/payload/.agents/skills/copywriting/SKILL.md +252 -0
  42. package/payload/.agents/skills/copywriting/evals/evals.json +111 -0
  43. package/payload/.agents/skills/copywriting/references/copy-frameworks.md +344 -0
  44. package/payload/.agents/skills/copywriting/references/natural-transitions.md +272 -0
  45. package/payload/.agents/skills/email-sequence/SKILL.md +309 -0
  46. package/payload/.agents/skills/email-sequence/evals/evals.json +93 -0
  47. package/payload/.agents/skills/email-sequence/references/copy-guidelines.md +113 -0
  48. package/payload/.agents/skills/email-sequence/references/email-types.md +515 -0
  49. package/payload/.agents/skills/email-sequence/references/sequence-templates.md +168 -0
  50. package/payload/.agents/skills/form-cro/SKILL.md +429 -0
  51. package/payload/.agents/skills/form-cro/evals/evals.json +90 -0
  52. package/payload/.agents/skills/free-tool-strategy/SKILL.md +178 -0
  53. package/payload/.agents/skills/free-tool-strategy/evals/evals.json +90 -0
  54. package/payload/.agents/skills/free-tool-strategy/references/tool-types.md +217 -0
  55. package/payload/.agents/skills/launch-strategy/SKILL.md +353 -0
  56. package/payload/.agents/skills/launch-strategy/evals/evals.json +91 -0
  57. package/payload/.agents/skills/marketing-ideas/SKILL.md +167 -0
  58. package/payload/.agents/skills/marketing-ideas/evals/evals.json +90 -0
  59. package/payload/.agents/skills/marketing-ideas/references/ideas-by-category.md +366 -0
  60. package/payload/.agents/skills/marketing-psychology/SKILL.md +455 -0
  61. package/payload/.agents/skills/marketing-psychology/evals/evals.json +88 -0
  62. package/payload/.agents/skills/onboarding-cro/SKILL.md +220 -0
  63. package/payload/.agents/skills/onboarding-cro/evals/evals.json +92 -0
  64. package/payload/.agents/skills/onboarding-cro/references/experiments.md +258 -0
  65. package/payload/.agents/skills/page-cro/SKILL.md +182 -0
  66. package/payload/.agents/skills/page-cro/evals/evals.json +111 -0
  67. package/payload/.agents/skills/page-cro/references/experiments.md +248 -0
  68. package/payload/.agents/skills/paid-ads/SKILL.md +315 -0
  69. package/payload/.agents/skills/paid-ads/evals/evals.json +90 -0
  70. package/payload/.agents/skills/paid-ads/references/ad-copy-templates.md +207 -0
  71. package/payload/.agents/skills/paid-ads/references/audience-targeting.md +243 -0
  72. package/payload/.agents/skills/paid-ads/references/platform-setup-checklists.md +277 -0
  73. package/payload/.agents/skills/paywall-upgrade-cro/SKILL.md +227 -0
  74. package/payload/.agents/skills/paywall-upgrade-cro/evals/evals.json +93 -0
  75. package/payload/.agents/skills/paywall-upgrade-cro/references/experiments.md +164 -0
  76. package/payload/.agents/skills/popup-cro/SKILL.md +453 -0
  77. package/payload/.agents/skills/popup-cro/evals/evals.json +94 -0
  78. package/payload/.agents/skills/pricing-strategy/SKILL.md +231 -0
  79. package/payload/.agents/skills/pricing-strategy/evals/evals.json +90 -0
  80. package/payload/.agents/skills/pricing-strategy/references/research-methods.md +152 -0
  81. package/payload/.agents/skills/pricing-strategy/references/tier-structure.md +232 -0
  82. package/payload/.agents/skills/product-marketing-context/SKILL.md +27 -0
  83. package/payload/.agents/skills/product-marketing-context/evals/evals.json +40 -0
  84. package/payload/.agents/skills/programmatic-seo/SKILL.md +238 -0
  85. package/payload/.agents/skills/programmatic-seo/evals/evals.json +94 -0
  86. package/payload/.agents/skills/programmatic-seo/references/playbooks.md +308 -0
  87. package/payload/.agents/skills/referral-program/SKILL.md +255 -0
  88. package/payload/.agents/skills/referral-program/evals/evals.json +89 -0
  89. package/payload/.agents/skills/referral-program/references/affiliate-programs.md +164 -0
  90. package/payload/.agents/skills/referral-program/references/program-examples.md +143 -0
  91. package/payload/.agents/skills/revops/SKILL.md +343 -0
  92. package/payload/.agents/skills/revops/evals/evals.json +91 -0
  93. package/payload/.agents/skills/revops/references/automation-playbooks.md +290 -0
  94. package/payload/.agents/skills/revops/references/lifecycle-definitions.md +278 -0
  95. package/payload/.agents/skills/revops/references/routing-rules.md +203 -0
  96. package/payload/.agents/skills/revops/references/scoring-models.md +247 -0
  97. package/payload/.agents/skills/sales-enablement/SKILL.md +349 -0
  98. package/payload/.agents/skills/sales-enablement/evals/evals.json +91 -0
  99. package/payload/.agents/skills/sales-enablement/references/deck-frameworks.md +263 -0
  100. package/payload/.agents/skills/sales-enablement/references/demo-scripts.md +355 -0
  101. package/payload/.agents/skills/sales-enablement/references/objection-library.md +270 -0
  102. package/payload/.agents/skills/sales-enablement/references/one-pager-templates.md +208 -0
  103. package/payload/.agents/skills/schema-markup/SKILL.md +179 -0
  104. package/payload/.agents/skills/schema-markup/evals/evals.json +87 -0
  105. package/payload/.agents/skills/schema-markup/references/schema-examples.md +398 -0
  106. package/payload/.agents/skills/seo-audit/SKILL.md +412 -0
  107. package/payload/.agents/skills/seo-audit/evals/evals.json +136 -0
  108. package/payload/.agents/skills/seo-audit/references/ai-writing-detection.md +200 -0
  109. package/payload/.agents/skills/signup-flow-cro/SKILL.md +359 -0
  110. package/payload/.agents/skills/signup-flow-cro/evals/evals.json +88 -0
  111. package/payload/.agents/skills/site-architecture/SKILL.md +357 -0
  112. package/payload/.agents/skills/site-architecture/evals/evals.json +88 -0
  113. package/payload/.agents/skills/site-architecture/references/mermaid-templates.md +216 -0
  114. package/payload/.agents/skills/site-architecture/references/navigation-patterns.md +305 -0
  115. package/payload/.agents/skills/site-architecture/references/site-type-templates.md +293 -0
  116. package/payload/.agents/skills/social-content/SKILL.md +278 -0
  117. package/payload/.agents/skills/social-content/evals/evals.json +92 -0
  118. package/payload/.agents/skills/social-content/references/platforms.md +170 -0
  119. package/payload/.agents/skills/social-content/references/post-templates.md +177 -0
  120. package/payload/.agents/skills/social-content/references/reverse-engineering.md +195 -0
  121. package/payload/.maya/executor.md +79 -0
  122. package/payload/.maya/meta-api-agent.md +48 -0
  123. package/payload/.maya/modes/consult.md +63 -0
  124. package/payload/.maya/modes/task.md +97 -0
  125. package/payload/.maya/planner.md +69 -0
  126. package/payload/.maya/researcher.md +51 -0
  127. package/payload/.maya/templates/plan.md +77 -0
  128. package/payload/.maya/templates/state.md +87 -0
  129. package/payload/.maya/templates/task-packet.md +75 -0
  130. package/payload/MAYA-CATALOG.md +115 -0
  131. package/payload/MAYA-DEPENDENCIES.md +58 -0
  132. package/payload/MAYA.md +151 -0
  133. package/payload/campaigns/README.md +14 -0
  134. package/payload/commands/maya-consult.md +28 -0
  135. package/payload/commands/maya-task.md +38 -0
  136. package/payload/commands/product.md +55 -0
  137. package/payload/research/README.md +14 -0
  138. package/payload/templates/README.md +15 -0
  139. package/payload/templates/plan.md +77 -0
  140. package/payload/templates/state.md +87 -0
  141. package/payload/templates/task-packet.md +75 -0
  142. package/payload/tools/REGISTRY.md +368 -0
  143. package/payload/tools/clis/README.md +187 -0
  144. package/payload/tools/clis/activecampaign.js +435 -0
  145. package/payload/tools/clis/adobe-analytics.js +161 -0
  146. package/payload/tools/clis/ahrefs.js +192 -0
  147. package/payload/tools/clis/amplitude.js +182 -0
  148. package/payload/tools/clis/apollo.js +142 -0
  149. package/payload/tools/clis/beehiiv.js +245 -0
  150. package/payload/tools/clis/brevo.js +368 -0
  151. package/payload/tools/clis/buffer.js +260 -0
  152. package/payload/tools/clis/calendly.js +253 -0
  153. package/payload/tools/clis/clearbit.js +163 -0
  154. package/payload/tools/clis/customer-io.js +205 -0
  155. package/payload/tools/clis/dataforseo.js +257 -0
  156. package/payload/tools/clis/demio.js +149 -0
  157. package/payload/tools/clis/dub.js +158 -0
  158. package/payload/tools/clis/g2.js +186 -0
  159. package/payload/tools/clis/ga4.js +194 -0
  160. package/payload/tools/clis/google-ads.js +189 -0
  161. package/payload/tools/clis/google-search-console.js +166 -0
  162. package/payload/tools/clis/hotjar.js +167 -0
  163. package/payload/tools/clis/hunter.js +249 -0
  164. package/payload/tools/clis/instantly.js +270 -0
  165. package/payload/tools/clis/intercom.js +399 -0
  166. package/payload/tools/clis/keywords-everywhere.js +185 -0
  167. package/payload/tools/clis/kit.js +232 -0
  168. package/payload/tools/clis/klaviyo.js +348 -0
  169. package/payload/tools/clis/lemlist.js +221 -0
  170. package/payload/tools/clis/linkedin-ads.js +185 -0
  171. package/payload/tools/clis/livestorm.js +292 -0
  172. package/payload/tools/clis/mailchimp.js +220 -0
  173. package/payload/tools/clis/mention-me.js +161 -0
  174. package/payload/tools/clis/meta-ads.js +181 -0
  175. package/payload/tools/clis/mixpanel.js +248 -0
  176. package/payload/tools/clis/onesignal.js +241 -0
  177. package/payload/tools/clis/optimizely.js +233 -0
  178. package/payload/tools/clis/paddle.js +385 -0
  179. package/payload/tools/clis/partnerstack.js +382 -0
  180. package/payload/tools/clis/plausible.js +249 -0
  181. package/payload/tools/clis/postmark.js +375 -0
  182. package/payload/tools/clis/resend.js +370 -0
  183. package/payload/tools/clis/rewardful.js +160 -0
  184. package/payload/tools/clis/savvycal.js +223 -0
  185. package/payload/tools/clis/segment.js +192 -0
  186. package/payload/tools/clis/semrush.js +207 -0
  187. package/payload/tools/clis/sendgrid.js +211 -0
  188. package/payload/tools/clis/snov.js +237 -0
  189. package/payload/tools/clis/tiktok-ads.js +190 -0
  190. package/payload/tools/clis/tolt.js +153 -0
  191. package/payload/tools/clis/trustpilot.js +276 -0
  192. package/payload/tools/clis/typeform.js +269 -0
  193. package/payload/tools/clis/wistia.js +256 -0
  194. package/payload/tools/clis/zapier.js +160 -0
  195. package/payload/tools/integrations/activecampaign.md +337 -0
  196. package/payload/tools/integrations/adobe-analytics.md +156 -0
  197. package/payload/tools/integrations/ahrefs.md +142 -0
  198. package/payload/tools/integrations/amplitude.md +135 -0
  199. package/payload/tools/integrations/apollo.md +148 -0
  200. package/payload/tools/integrations/beehiiv.md +157 -0
  201. package/payload/tools/integrations/brevo.md +268 -0
  202. package/payload/tools/integrations/buffer.md +138 -0
  203. package/payload/tools/integrations/calendly.md +161 -0
  204. package/payload/tools/integrations/clearbit.md +142 -0
  205. package/payload/tools/integrations/customer-io.md +187 -0
  206. package/payload/tools/integrations/dataforseo.md +165 -0
  207. package/payload/tools/integrations/demio.md +182 -0
  208. package/payload/tools/integrations/dub-co.md +160 -0
  209. package/payload/tools/integrations/g2.md +179 -0
  210. package/payload/tools/integrations/ga4.md +126 -0
  211. package/payload/tools/integrations/google-ads.md +159 -0
  212. package/payload/tools/integrations/google-search-console.md +147 -0
  213. package/payload/tools/integrations/hotjar.md +147 -0
  214. package/payload/tools/integrations/hubspot.md +178 -0
  215. package/payload/tools/integrations/hunter.md +90 -0
  216. package/payload/tools/integrations/instantly.md +104 -0
  217. package/payload/tools/integrations/intercom.md +292 -0
  218. package/payload/tools/integrations/keywords-everywhere.md +207 -0
  219. package/payload/tools/integrations/kit.md +167 -0
  220. package/payload/tools/integrations/klaviyo.md +228 -0
  221. package/payload/tools/integrations/lemlist.md +110 -0
  222. package/payload/tools/integrations/linkedin-ads.md +164 -0
  223. package/payload/tools/integrations/livestorm.md +313 -0
  224. package/payload/tools/integrations/mailchimp.md +150 -0
  225. package/payload/tools/integrations/mention-me.md +160 -0
  226. package/payload/tools/integrations/meta-ads.md +147 -0
  227. package/payload/tools/integrations/mixpanel.md +137 -0
  228. package/payload/tools/integrations/onesignal.md +229 -0
  229. package/payload/tools/integrations/optimizely.md +171 -0
  230. package/payload/tools/integrations/paddle.md +212 -0
  231. package/payload/tools/integrations/partnerstack.md +222 -0
  232. package/payload/tools/integrations/plausible.md +177 -0
  233. package/payload/tools/integrations/posthog.md +151 -0
  234. package/payload/tools/integrations/postmark.md +234 -0
  235. package/payload/tools/integrations/resend.md +168 -0
  236. package/payload/tools/integrations/rewardful.md +147 -0
  237. package/payload/tools/integrations/salesforce.md +150 -0
  238. package/payload/tools/integrations/savvycal.md +181 -0
  239. package/payload/tools/integrations/segment.md +159 -0
  240. package/payload/tools/integrations/semrush.md +121 -0
  241. package/payload/tools/integrations/sendgrid.md +161 -0
  242. package/payload/tools/integrations/shopify.md +176 -0
  243. package/payload/tools/integrations/snov.md +94 -0
  244. package/payload/tools/integrations/stripe.md +148 -0
  245. package/payload/tools/integrations/tiktok-ads.md +161 -0
  246. package/payload/tools/integrations/tolt.md +144 -0
  247. package/payload/tools/integrations/trustpilot.md +191 -0
  248. package/payload/tools/integrations/typeform.md +190 -0
  249. package/payload/tools/integrations/webflow.md +198 -0
  250. package/payload/tools/integrations/wistia.md +164 -0
  251. package/payload/tools/integrations/wordpress.md +175 -0
  252. package/payload/tools/integrations/zapier.md +150 -0
  253. package/payload/tools/meta/README.md +55 -0
  254. package/payload/tools/meta/meta-cache-schema.md +65 -0
  255. package/payload/tools/meta/meta-fetch.ps1 +324 -0
  256. package/payload/tools/meta/meta-fetch.test.ps1 +38 -0
  257. package/vendor/shared-installer/manifests/claude-files.json +13 -0
  258. package/vendor/shared-installer/manifests/codex-files.json +13 -0
  259. package/vendor/shared-installer/manifests/common-files.json +13 -0
  260. package/vendor/shared-installer/package.json +15 -0
  261. package/vendor/shared-installer/src/bootstrap.js +12 -0
  262. package/vendor/shared-installer/src/cli-options.js +53 -0
  263. package/vendor/shared-installer/src/fs.js +105 -0
  264. package/vendor/shared-installer/src/index.js +44 -0
  265. package/vendor/shared-installer/src/install.js +157 -0
  266. package/vendor/shared-installer/src/manifest.js +52 -0
  267. package/vendor/shared-installer/templates/claude/.claude/skills/.gitkeep +1 -0
  268. package/vendor/shared-installer/templates/claude/CLAUDE.md +27 -0
  269. package/vendor/shared-installer/templates/codex/.agent/skills/.gitkeep +1 -0
  270. package/vendor/shared-installer/templates/codex/AGENTS.md +27 -0
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+
3
+ const TOKEN = process.env.GOOGLE_ADS_TOKEN
4
+ const DEV_TOKEN = process.env.GOOGLE_ADS_DEVELOPER_TOKEN
5
+ const CUSTOMER_ID = process.env.GOOGLE_ADS_CUSTOMER_ID
6
+ const BASE_URL = 'https://googleads.googleapis.com/v14'
7
+
8
+ if (!TOKEN || !DEV_TOKEN || !CUSTOMER_ID) {
9
+ console.error(JSON.stringify({ error: 'GOOGLE_ADS_TOKEN, GOOGLE_ADS_DEVELOPER_TOKEN, and GOOGLE_ADS_CUSTOMER_ID environment variables required' }))
10
+ process.exit(1)
11
+ }
12
+
13
+ async function api(method, path, body) {
14
+ if (args['dry-run']) {
15
+ return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { Authorization: '***', 'developer-token': '***', 'Content-Type': 'application/json' }, body: body || undefined }
16
+ }
17
+ const res = await fetch(`${BASE_URL}${path}`, {
18
+ method,
19
+ headers: {
20
+ 'Authorization': `Bearer ${TOKEN}`,
21
+ 'developer-token': DEV_TOKEN,
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ body: body ? JSON.stringify(body) : undefined,
25
+ })
26
+ const text = await res.text()
27
+ try {
28
+ return JSON.parse(text)
29
+ } catch {
30
+ return { status: res.status, body: text }
31
+ }
32
+ }
33
+
34
+ async function gaql(query) {
35
+ return api('POST', `/customers/${CUSTOMER_ID}/googleAds:searchStream`, { query })
36
+ }
37
+
38
+ function parseArgs(args) {
39
+ const result = { _: [] }
40
+ for (let i = 0; i < args.length; i++) {
41
+ const arg = args[i]
42
+ if (arg.startsWith('--')) {
43
+ const key = arg.slice(2)
44
+ const next = args[i + 1]
45
+ if (next && !next.startsWith('--')) {
46
+ result[key] = next
47
+ i++
48
+ } else {
49
+ result[key] = true
50
+ }
51
+ } else {
52
+ result._.push(arg)
53
+ }
54
+ }
55
+ return result
56
+ }
57
+
58
+ const args = parseArgs(process.argv.slice(2))
59
+ const [cmd, sub, ...rest] = args._
60
+
61
+ function daysToDateRange(days) {
62
+ const d = parseInt(days) || 30
63
+ if (d === 7) return 'LAST_7_DAYS'
64
+ if (d === 14) return 'LAST_14_DAYS'
65
+ if (d === 30) return 'LAST_30_DAYS'
66
+ if (d === 90) return 'LAST_90_DAYS'
67
+ return `LAST_${d}_DAYS`
68
+ }
69
+
70
+ async function main() {
71
+ let result
72
+
73
+ switch (cmd) {
74
+ case 'account':
75
+ switch (sub) {
76
+ case 'info':
77
+ default:
78
+ result = await gaql('SELECT customer.id, customer.descriptive_name FROM customer')
79
+ }
80
+ break
81
+
82
+ case 'campaigns':
83
+ switch (sub) {
84
+ case 'list':
85
+ result = await gaql('SELECT campaign.id, campaign.name, campaign.status, campaign_budget.amount_micros FROM campaign ORDER BY campaign.id')
86
+ break
87
+ case 'performance': {
88
+ const dateRange = daysToDateRange(args.days)
89
+ result = await gaql(`SELECT campaign.name, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions FROM campaign WHERE segments.date DURING ${dateRange}`)
90
+ break
91
+ }
92
+ case 'pause': {
93
+ if (!args.id) { result = { error: '--id required' }; break }
94
+ result = await api('POST', `/customers/${CUSTOMER_ID}/campaigns:mutate`, {
95
+ operations: [{
96
+ update: {
97
+ resourceName: `customers/${CUSTOMER_ID}/campaigns/${args.id}`,
98
+ status: 'PAUSED',
99
+ },
100
+ updateMask: 'status',
101
+ }],
102
+ })
103
+ break
104
+ }
105
+ case 'enable': {
106
+ if (!args.id) { result = { error: '--id required' }; break }
107
+ result = await api('POST', `/customers/${CUSTOMER_ID}/campaigns:mutate`, {
108
+ operations: [{
109
+ update: {
110
+ resourceName: `customers/${CUSTOMER_ID}/campaigns/${args.id}`,
111
+ status: 'ENABLED',
112
+ },
113
+ updateMask: 'status',
114
+ }],
115
+ })
116
+ break
117
+ }
118
+ default:
119
+ result = { error: 'Unknown campaigns subcommand. Use: list, performance, pause, enable' }
120
+ }
121
+ break
122
+
123
+ case 'adgroups':
124
+ switch (sub) {
125
+ case 'performance': {
126
+ const dateRange = daysToDateRange(args.days)
127
+ const limit = args.limit ? ` LIMIT ${args.limit}` : ''
128
+ result = await gaql(`SELECT ad_group.name, metrics.impressions, metrics.clicks, metrics.conversions FROM ad_group WHERE segments.date DURING ${dateRange}${limit}`)
129
+ break
130
+ }
131
+ default:
132
+ result = { error: 'Unknown adgroups subcommand. Use: performance' }
133
+ }
134
+ break
135
+
136
+ case 'keywords':
137
+ switch (sub) {
138
+ case 'performance': {
139
+ const dateRange = daysToDateRange(args.days)
140
+ const limit = args.limit || '50'
141
+ result = await gaql(`SELECT ad_group_criterion.keyword.text, metrics.impressions, metrics.clicks, metrics.average_cpc FROM keyword_view WHERE segments.date DURING ${dateRange} ORDER BY metrics.clicks DESC LIMIT ${limit}`)
142
+ break
143
+ }
144
+ default:
145
+ result = { error: 'Unknown keywords subcommand. Use: performance' }
146
+ }
147
+ break
148
+
149
+ case 'budgets':
150
+ switch (sub) {
151
+ case 'update': {
152
+ if (!args.id || !args.amount) { result = { error: '--id and --amount required' }; break }
153
+ const amountMicros = String(Math.round(parseFloat(args.amount) * 1000000))
154
+ result = await api('POST', `/customers/${CUSTOMER_ID}/campaignBudgets:mutate`, {
155
+ operations: [{
156
+ update: {
157
+ resourceName: `customers/${CUSTOMER_ID}/campaignBudgets/${args.id}`,
158
+ amount_micros: amountMicros,
159
+ },
160
+ updateMask: 'amount_micros',
161
+ }],
162
+ })
163
+ break
164
+ }
165
+ default:
166
+ result = { error: 'Unknown budgets subcommand. Use: update' }
167
+ }
168
+ break
169
+
170
+ default:
171
+ result = {
172
+ error: 'Unknown command',
173
+ usage: {
174
+ account: 'account [info]',
175
+ campaigns: 'campaigns [list|performance|pause|enable] [--days 30] [--id <id>]',
176
+ adgroups: 'adgroups [performance] [--days 30] [--limit <n>]',
177
+ keywords: 'keywords [performance] [--days 30] [--limit 50]',
178
+ budgets: 'budgets [update] --id <budget_id> --amount <dollars>',
179
+ },
180
+ }
181
+ }
182
+
183
+ console.log(JSON.stringify(result, null, 2))
184
+ }
185
+
186
+ main().catch(err => {
187
+ console.error(JSON.stringify({ error: err.message }))
188
+ process.exit(1)
189
+ })
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+
3
+ const ACCESS_TOKEN = process.env.GSC_ACCESS_TOKEN
4
+ const BASE_URL = 'https://searchconsole.googleapis.com'
5
+
6
+ if (!ACCESS_TOKEN) {
7
+ console.error(JSON.stringify({ error: 'GSC_ACCESS_TOKEN environment variable required' }))
8
+ process.exit(1)
9
+ }
10
+
11
+ async function api(method, path, body) {
12
+ if (args['dry-run']) {
13
+ return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { Authorization: '***', 'Content-Type': 'application/json' }, body: body || undefined }
14
+ }
15
+ const res = await fetch(`${BASE_URL}${path}`, {
16
+ method,
17
+ headers: {
18
+ 'Authorization': `Bearer ${ACCESS_TOKEN}`,
19
+ 'Content-Type': 'application/json',
20
+ },
21
+ body: body ? JSON.stringify(body) : undefined,
22
+ })
23
+ const text = await res.text()
24
+ try {
25
+ return JSON.parse(text)
26
+ } catch {
27
+ return { status: res.status, body: text }
28
+ }
29
+ }
30
+
31
+ function parseArgs(args) {
32
+ const result = { _: [] }
33
+ for (let i = 0; i < args.length; i++) {
34
+ const arg = args[i]
35
+ if (arg.startsWith('--')) {
36
+ const key = arg.slice(2)
37
+ const next = args[i + 1]
38
+ if (next && !next.startsWith('--')) {
39
+ result[key] = next
40
+ i++
41
+ } else {
42
+ result[key] = true
43
+ }
44
+ } else {
45
+ result._.push(arg)
46
+ }
47
+ }
48
+ return result
49
+ }
50
+
51
+ const args = parseArgs(process.argv.slice(2))
52
+ const [cmd, sub, ...rest] = args._
53
+
54
+ function getDefaultDates() {
55
+ const end = new Date()
56
+ end.setDate(end.getDate() - 3)
57
+ const start = new Date(end)
58
+ start.setDate(start.getDate() - 28)
59
+ return {
60
+ startDate: start.toISOString().split('T')[0],
61
+ endDate: end.toISOString().split('T')[0],
62
+ }
63
+ }
64
+
65
+ async function main() {
66
+ let result
67
+ const siteUrl = args['site-url']
68
+
69
+ switch (cmd) {
70
+ case 'search': {
71
+ if (!siteUrl) {
72
+ result = { error: '--site-url is required for search commands' }
73
+ break
74
+ }
75
+ const encodedSiteUrl = encodeURIComponent(siteUrl)
76
+ const defaults = getDefaultDates()
77
+ const body = {
78
+ startDate: args['start-date'] || defaults.startDate,
79
+ endDate: args['end-date'] || defaults.endDate,
80
+ rowLimit: parseInt(args.limit || '100', 10),
81
+ }
82
+
83
+ switch (sub) {
84
+ case 'query':
85
+ body.dimensions = ['query']
86
+ result = await api('POST', `/webmasters/v3/sites/${encodedSiteUrl}/searchAnalytics/query`, body)
87
+ break
88
+ case 'pages':
89
+ body.dimensions = ['page']
90
+ result = await api('POST', `/webmasters/v3/sites/${encodedSiteUrl}/searchAnalytics/query`, body)
91
+ break
92
+ case 'countries':
93
+ body.dimensions = ['country']
94
+ result = await api('POST', `/webmasters/v3/sites/${encodedSiteUrl}/searchAnalytics/query`, body)
95
+ break
96
+ default:
97
+ result = { error: 'Unknown search subcommand. Use: query, pages, countries' }
98
+ }
99
+ break
100
+ }
101
+
102
+ case 'inspect': {
103
+ if (!siteUrl) {
104
+ result = { error: '--site-url is required for inspect commands' }
105
+ break
106
+ }
107
+ switch (sub) {
108
+ case 'url':
109
+ if (!args.url) { result = { error: '--url required (URL to inspect)' }; break }
110
+ result = await api('POST', '/v1/urlInspection/index:inspect', {
111
+ inspectionUrl: args.url,
112
+ siteUrl: siteUrl,
113
+ })
114
+ break
115
+ default:
116
+ result = { error: 'Unknown inspect subcommand. Use: url' }
117
+ }
118
+ break
119
+ }
120
+
121
+ case 'sitemaps': {
122
+ if (!siteUrl) {
123
+ result = { error: '--site-url is required for sitemaps commands' }
124
+ break
125
+ }
126
+ const encodedSiteUrl = encodeURIComponent(siteUrl)
127
+ switch (sub) {
128
+ case 'list':
129
+ result = await api('GET', `/webmasters/v3/sites/${encodedSiteUrl}/sitemaps`)
130
+ break
131
+ case 'submit': {
132
+ if (!args['sitemap-url']) { result = { error: '--sitemap-url required' }; break }
133
+ const sitemapUrl = encodeURIComponent(args['sitemap-url'])
134
+ result = await api('PUT', `/webmasters/v3/sites/${encodedSiteUrl}/sitemaps/${sitemapUrl}`)
135
+ if (!result.body && !result.error) {
136
+ result = { success: true, message: 'Sitemap submitted successfully' }
137
+ }
138
+ break
139
+ }
140
+ default:
141
+ result = { error: 'Unknown sitemaps subcommand. Use: list, submit' }
142
+ }
143
+ break
144
+ }
145
+
146
+ default:
147
+ result = {
148
+ error: 'Unknown command',
149
+ usage: {
150
+ 'search query': 'search query --site-url <url> [--start-date <date>] [--end-date <date>] [--limit <n>]',
151
+ 'search pages': 'search pages --site-url <url> [--start-date <date>] [--end-date <date>] [--limit <n>]',
152
+ 'search countries': 'search countries --site-url <url> [--start-date <date>] [--end-date <date>] [--limit <n>]',
153
+ 'inspect url': 'inspect url --site-url <url> --url <page-url>',
154
+ 'sitemaps list': 'sitemaps list --site-url <url>',
155
+ 'sitemaps submit': 'sitemaps submit --site-url <url> --sitemap-url <sitemap-url>',
156
+ }
157
+ }
158
+ }
159
+
160
+ console.log(JSON.stringify(result, null, 2))
161
+ }
162
+
163
+ main().catch(err => {
164
+ console.error(JSON.stringify({ error: err.message }))
165
+ process.exit(1)
166
+ })
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+
3
+ const CLIENT_ID = process.env.HOTJAR_CLIENT_ID
4
+ const CLIENT_SECRET = process.env.HOTJAR_CLIENT_SECRET
5
+ const OAUTH_URL = 'https://api.hotjar.io'
6
+ const BASE_URL = 'https://api.hotjar.io/v2'
7
+
8
+ if (!CLIENT_ID || !CLIENT_SECRET) {
9
+ console.error(JSON.stringify({ error: 'HOTJAR_CLIENT_ID and HOTJAR_CLIENT_SECRET environment variables required' }))
10
+ process.exit(1)
11
+ }
12
+
13
+ let cachedToken = null
14
+
15
+ async function getToken() {
16
+ if (cachedToken) return cachedToken
17
+ const res = await fetch(`${OAUTH_URL}/oauth/token`, {
18
+ method: 'POST',
19
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
20
+ body: `grant_type=client_credentials&client_id=${encodeURIComponent(CLIENT_ID)}&client_secret=${encodeURIComponent(CLIENT_SECRET)}`,
21
+ })
22
+ const data = await res.json()
23
+ if (!data.access_token) {
24
+ throw new Error(data.error_description || data.error || 'Failed to obtain access token')
25
+ }
26
+ cachedToken = data.access_token
27
+ return cachedToken
28
+ }
29
+
30
+ async function api(method, path) {
31
+ if (args['dry-run']) {
32
+ return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { Authorization: '***', 'Content-Type': 'application/json', Accept: 'application/json' } }
33
+ }
34
+ const token = await getToken()
35
+ const res = await fetch(`${BASE_URL}${path}`, {
36
+ method,
37
+ headers: {
38
+ 'Authorization': `Bearer ${token}`,
39
+ 'Content-Type': 'application/json',
40
+ 'Accept': 'application/json',
41
+ },
42
+ })
43
+ const text = await res.text()
44
+ try {
45
+ return JSON.parse(text)
46
+ } catch {
47
+ return { status: res.status, body: text }
48
+ }
49
+ }
50
+
51
+ function parseArgs(args) {
52
+ const result = { _: [] }
53
+ for (let i = 0; i < args.length; i++) {
54
+ const arg = args[i]
55
+ if (arg.startsWith('--')) {
56
+ const key = arg.slice(2)
57
+ const next = args[i + 1]
58
+ if (next && !next.startsWith('--')) {
59
+ result[key] = next
60
+ i++
61
+ } else {
62
+ result[key] = true
63
+ }
64
+ } else {
65
+ result._.push(arg)
66
+ }
67
+ }
68
+ return result
69
+ }
70
+
71
+ const args = parseArgs(process.argv.slice(2))
72
+ const [cmd, sub, ...rest] = args._
73
+
74
+ async function main() {
75
+ let result
76
+ const siteId = args['site-id']
77
+ const limit = args.limit || '100'
78
+ const cursor = args.cursor
79
+
80
+ switch (cmd) {
81
+ case 'sites':
82
+ switch (sub) {
83
+ case 'list':
84
+ result = await api('GET', '/sites')
85
+ break
86
+ default:
87
+ result = { error: 'Unknown sites subcommand. Use: list' }
88
+ }
89
+ break
90
+
91
+ case 'surveys':
92
+ if (!siteId) { result = { error: '--site-id required' }; break }
93
+ switch (sub) {
94
+ case 'list':
95
+ result = await api('GET', `/sites/${siteId}/surveys`)
96
+ break
97
+ case 'responses': {
98
+ const surveyId = args['survey-id']
99
+ if (!surveyId) { result = { error: '--survey-id required' }; break }
100
+ const params = new URLSearchParams({ limit })
101
+ if (cursor) params.set('cursor', cursor)
102
+ result = await api('GET', `/sites/${siteId}/surveys/${surveyId}/responses?${params.toString()}`)
103
+ break
104
+ }
105
+ default:
106
+ result = { error: 'Unknown surveys subcommand. Use: list, responses' }
107
+ }
108
+ break
109
+
110
+ case 'heatmaps':
111
+ if (!siteId) { result = { error: '--site-id required' }; break }
112
+ switch (sub) {
113
+ case 'list':
114
+ result = await api('GET', `/sites/${siteId}/heatmaps`)
115
+ break
116
+ default:
117
+ result = { error: 'Unknown heatmaps subcommand. Use: list' }
118
+ }
119
+ break
120
+
121
+ case 'recordings':
122
+ if (!siteId) { result = { error: '--site-id required' }; break }
123
+ switch (sub) {
124
+ case 'list': {
125
+ const params = new URLSearchParams({ limit })
126
+ if (cursor) params.set('cursor', cursor)
127
+ if (args['date-from']) params.set('date_from', args['date-from'])
128
+ if (args['date-to']) params.set('date_to', args['date-to'])
129
+ result = await api('GET', `/sites/${siteId}/recordings?${params.toString()}`)
130
+ break
131
+ }
132
+ default:
133
+ result = { error: 'Unknown recordings subcommand. Use: list' }
134
+ }
135
+ break
136
+
137
+ case 'forms':
138
+ if (!siteId) { result = { error: '--site-id required' }; break }
139
+ switch (sub) {
140
+ case 'list':
141
+ result = await api('GET', `/sites/${siteId}/forms`)
142
+ break
143
+ default:
144
+ result = { error: 'Unknown forms subcommand. Use: list' }
145
+ }
146
+ break
147
+
148
+ default:
149
+ result = {
150
+ error: 'Unknown command',
151
+ usage: {
152
+ sites: 'sites list',
153
+ surveys: 'surveys list --site-id <id> | surveys responses --site-id <id> --survey-id <id> [--limit <n>] [--cursor <cursor>]',
154
+ heatmaps: 'heatmaps list --site-id <id>',
155
+ recordings: 'recordings list --site-id <id> [--limit <n>] [--cursor <cursor>] [--date-from <date>] [--date-to <date>]',
156
+ forms: 'forms list --site-id <id>',
157
+ }
158
+ }
159
+ }
160
+
161
+ console.log(JSON.stringify(result, null, 2))
162
+ }
163
+
164
+ main().catch(err => {
165
+ console.error(JSON.stringify({ error: err.message }))
166
+ process.exit(1)
167
+ })