@canonry/canonry 5.22.0 → 5.29.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 (46) hide show
  1. package/README.md +2 -1
  2. package/assets/agent-workspace/skills/aero/SKILL.md +37 -3
  3. package/assets/agent-workspace/skills/aero/references/portfolio-analysis.md +26 -12
  4. package/assets/agent-workspace/skills/aero/references/reporting.md +1 -0
  5. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +100 -5
  6. package/assets/agent-workspace/skills/canonry/references/google-business-profile.md +30 -6
  7. package/assets/agent-workspace/skills/canonry/references/indexing.md +1 -0
  8. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +30 -0
  9. package/assets/assets/{AuditHistoryPanel-teTDC-4-.js → AuditHistoryPanel-ru-RI1SR.js} +1 -1
  10. package/assets/assets/{BacklinksPage-Bqm7bido.js → BacklinksPage-BbVWtfAh.js} +1 -1
  11. package/assets/assets/ChartPrimitives-B5okB5g-.js +1 -0
  12. package/assets/assets/{HistoryPage-IcqwPBmt.js → HistoryPage-CxIxsxIv.js} +1 -1
  13. package/assets/assets/MeasurementPropertyPage-Oju3oAP3.js +1 -0
  14. package/assets/assets/ProjectPage-ZsQo28yM.js +8 -0
  15. package/assets/assets/{RunRow-S_SCHr0o.js → RunRow-D73cbxey.js} +1 -1
  16. package/assets/assets/{RunsPage-DFiif626.js → RunsPage-D9hOl6k6.js} +1 -1
  17. package/assets/assets/{SettingsPage-CitZ6FAS.js → SettingsPage-By5cJJaC.js} +1 -1
  18. package/assets/assets/SiteHealthSection-Gfyispq_.js +4 -0
  19. package/assets/assets/{TrafficPage-lY8na5Pg.js → TrafficPage-8khxNXDL.js} +2 -2
  20. package/assets/assets/{TrafficSourceDetailPage-BTykoVGT.js → TrafficSourceDetailPage-FDe4jKLH.js} +1 -1
  21. package/assets/assets/{extract-error-message-r0Gpc7mv.js → extract-error-message-Co1hxrsc.js} +1 -1
  22. package/assets/assets/index-DKScDg92.js +86 -0
  23. package/assets/assets/index-DfhmHULl.css +1 -0
  24. package/assets/assets/{react-sigma_core.esm.min-DDrDxbO1.js → react-sigma_core.esm.min-DxAxqyeI.js} +1 -1
  25. package/assets/assets/{v2-overview-adapter-OsQiglXU.js → v2-overview-adapter-DNbOwIJq.js} +1 -1
  26. package/assets/index.html +2 -2
  27. package/dist/{chunk-XFHXKLNT.js → chunk-7BW7BAD5.js} +3727 -1282
  28. package/dist/{chunk-S5OSY3PI.js → chunk-DCGELKRW.js} +7126 -6001
  29. package/dist/{chunk-DDL2XSNM.js → chunk-J6BJIOIN.js} +130 -37
  30. package/dist/{chunk-P5VXVFQW.js → chunk-KGYHEYHX.js} +6992 -5409
  31. package/dist/{chunk-3LCR6WU6.js → chunk-THMIDWMS.js} +57 -3
  32. package/dist/{chunk-GLLY2GEV.js → chunk-VPIOF2PB.js} +172 -7
  33. package/dist/{chunk-YTSXQUJ3.js → chunk-WPQB4UYX.js} +3 -3
  34. package/dist/cli.js +561 -158
  35. package/dist/{demo-server-HULNEORN.js → demo-server-EU6B4KNK.js} +24 -32
  36. package/dist/index.d.ts +9 -1
  37. package/dist/index.js +6 -6
  38. package/dist/{intelligence-service-CXNBKRHV.js → intelligence-service-FVUNBN66.js} +2 -2
  39. package/dist/mcp.js +4 -4
  40. package/package.json +12 -11
  41. package/assets/assets/ChartPrimitives-BQC2VH0O.js +0 -1
  42. package/assets/assets/MeasurementPropertyPage-BLpptT3_.js +0 -1
  43. package/assets/assets/ProjectPage-nn2Y9H-m.js +0 -8
  44. package/assets/assets/SiteHealthSection-C2dsyNGY.js +0 -4
  45. package/assets/assets/index-DwlO8KfE.js +0 -86
  46. package/assets/assets/index-EJC8PSbh.css +0 -1
@@ -2,13 +2,14 @@ import {
2
2
  DEFAULT_DEMO_TRUSTED_PROXIES
3
3
  } from "./chunk-RB2F4D3Z.js";
4
4
  import {
5
+ computeFactorAverages,
5
6
  layoutSiteCrawlGraphInput,
6
7
  persistSiteCrawlGraphLayout
7
- } from "./chunk-3LCR6WU6.js";
8
+ } from "./chunk-THMIDWMS.js";
8
9
  import {
9
10
  PACKAGE_VERSION,
10
11
  canonryMcpTools
11
- } from "./chunk-DDL2XSNM.js";
12
+ } from "./chunk-J6BJIOIN.js";
12
13
  import {
13
14
  HISTORY_WINDOW_RUNS,
14
15
  IntelligenceService,
@@ -84,7 +85,7 @@ import {
84
85
  siteCrawlPages,
85
86
  siteCrawlSnapshots,
86
87
  trafficSources
87
- } from "./chunk-P5VXVFQW.js";
88
+ } from "./chunk-KGYHEYHX.js";
88
89
  import {
89
90
  RunKinds,
90
91
  SiteCrawlFetchStates,
@@ -102,13 +103,16 @@ import {
102
103
  effectiveBrandNames,
103
104
  effectiveDomains,
104
105
  factorStatusFromScore,
106
+ formatPercent,
105
107
  measurementPlanV2ChecksumJson,
106
108
  measurementPlanV2Schema,
107
109
  parseStoredMeasurementPlanAnyVersion,
110
+ percentOf,
108
111
  placementLinkDecision,
112
+ roundPreservingTotal,
109
113
  siteAuditPageFactorSchema,
110
114
  wilsonInterval
111
- } from "./chunk-S5OSY3PI.js";
115
+ } from "./chunk-DCGELKRW.js";
112
116
 
113
117
  // src/demo-server.ts
114
118
  import { dirname, join as join2 } from "path";
@@ -256,7 +260,7 @@ function formatPreviewDay(iso) {
256
260
  var engineName = (provider) => ENGINE_NAMES[provider] ?? provider;
257
261
  var quoted = (text) => `"${text}"`;
258
262
  var ratio = (numerator, denominator) => `${numerator}/${denominator}`;
259
- var percent = (numerator, denominator) => denominator === 0 ? 0 : Math.round(numerator / denominator * 100);
263
+ var percent = (numerator, denominator) => denominator === 0 ? formatPercent(0) : formatPercent(numerator / denominator);
260
264
  var unique = (values) => [...new Set(values)];
261
265
  function listJoin(items, conjunction = "and") {
262
266
  if (items.length <= 1) return items[0] ?? "";
@@ -457,7 +461,7 @@ function summitStatus(facts) {
457
461
  "| Queries | Mentioned | Cited |",
458
462
  "|---|---|---|",
459
463
  `| Branded (${queryIdsOf(branded).length}) | ${ratio(brandedCounts.mentioned, brandedCounts.total)} | ${ratio(brandedCounts.cited, brandedCounts.total)} |`,
460
- `| Non-brand (${nonBrandQueries}) | ${ratio(nonBrandCounts.mentioned, nonBrandCounts.total)} (${percent(nonBrandCounts.mentioned, nonBrandCounts.total)}%) | ${ratio(nonBrandCounts.cited, nonBrandCounts.total)} (${percent(nonBrandCounts.cited, nonBrandCounts.total)}%) |`
464
+ `| Non-brand (${nonBrandQueries}) | ${ratio(nonBrandCounts.mentioned, nonBrandCounts.total)} (${percent(nonBrandCounts.mentioned, nonBrandCounts.total)}) | ${ratio(nonBrandCounts.cited, nonBrandCounts.total)} (${percent(nonBrandCounts.cited, nonBrandCounts.total)}) |`
461
465
  ].join("\n"),
462
466
  `Non-brand by engine, mentioned then cited: ${perEngine.map((entry) => `${engineName(entry.provider)} ${ratio(entry.mentioned, entry.total)} and ${ratio(entry.cited, entry.total)}`).join(", ")}.`,
463
467
  ...attention.length > 0 ? [`**Needs attention**
@@ -1378,7 +1382,7 @@ async function createDemoHttpServer(options) {
1378
1382
  const notIndexed = [...latest.values()].filter((row) => row.inIndex === false).map(format);
1379
1383
  const unknown = [...latest.values()].filter((row) => row.inIndex === null).map(format);
1380
1384
  const total = latest.size;
1381
- return reply.send({ summary: { total, indexed: indexed.length, notIndexed: notIndexed.length, unknown: unknown.length, percentage: total ? Math.round(indexed.length / total * 1e3) / 10 : 0 }, lastInspectedAt: rows[0]?.inspectedAt ?? null, indexed, notIndexed, unknown });
1385
+ return reply.send({ summary: { total, indexed: indexed.length, notIndexed: notIndexed.length, unknown: unknown.length, percentage: percentOf(indexed.length, total) ?? 0 }, lastInspectedAt: rows[0]?.inspectedAt ?? null, indexed, notIndexed, unknown });
1382
1386
  }
1383
1387
  if (route === "/api/v1/projects/:name/bing/performance") {
1384
1388
  const name = request.params.name;
@@ -1676,32 +1680,17 @@ function seedPageAudits(db, projectId, runId, root, createdAt) {
1676
1680
  const crawlPages = db.select().from(siteCrawlPages).where(and2(eq3(siteCrawlPages.projectId, projectId), eq3(siteCrawlPages.runId, runId))).all();
1677
1681
  const audited = crawlPages.filter((page) => page.auditState === "success" && page.auditScore !== null);
1678
1682
  const pages = audited.map((page, index) => {
1679
- const factors2 = siteAuditPageFactorSchema.array().parse(page.auditFields.factors);
1680
- return { id: `${projectId}-audit-page-${index}`, projectId, runId, url: page.url, overallScore: page.auditScore, status: "success", factors: factors2, createdAt };
1681
- });
1682
- const factors = pages.flatMap((page) => page.factors);
1683
- const factorAverages = [...new Set(factors.map((factor) => factor.id))].map((id) => {
1684
- const matching = factors.filter((factor) => factor.id === id);
1685
- const first = matching[0];
1686
- const avgScore = Math.round(matching.reduce((sum, factor) => sum + factor.score, 0) / matching.length);
1687
- return {
1688
- id,
1689
- name: first.name,
1690
- weight: first.weight,
1691
- avgScore,
1692
- status: factorStatusFromScore(avgScore),
1693
- pagesPassing: matching.filter((factor) => factorStatusFromScore(factor.score) === "pass").length,
1694
- pagesPartial: matching.filter((factor) => factorStatusFromScore(factor.score) === "partial").length,
1695
- pagesFailing: matching.filter((factor) => factorStatusFromScore(factor.score) === "fail").length
1696
- };
1683
+ const factors = siteAuditPageFactorSchema.array().parse(page.auditFields.factors);
1684
+ return { id: `${projectId}-audit-page-${index}`, projectId, runId, url: page.url, overallScore: page.auditScore, status: "success", factors, createdAt };
1697
1685
  });
1686
+ const factorAverages = computeFactorAverages(pages.map((page) => ({ audit: { factors: page.factors } })));
1698
1687
  const crossCuttingIssues = factorAverages.filter((factor) => factor.pagesPartial + factor.pagesFailing > 0).map((factor) => ({
1699
1688
  factorId: factor.id,
1700
1689
  factorName: factor.name,
1701
1690
  avgScore: factor.avgScore,
1702
1691
  affectedPages: factor.pagesPartial + factor.pagesFailing,
1703
1692
  totalPages: pages.length,
1704
- affectedPct: Math.round((factor.pagesPartial + factor.pagesFailing) / pages.length * 100),
1693
+ affectedPct: percentOf(factor.pagesPartial + factor.pagesFailing, pages.length) ?? 0,
1705
1694
  topRecommendations: [`Complete ${factor.name.toLowerCase()} details on the affected pages.`]
1706
1695
  }));
1707
1696
  db.insert(siteAuditSnapshots).values({
@@ -2149,10 +2138,11 @@ function parentPath(path) {
2149
2138
  const slash = trimmed.lastIndexOf("/");
2150
2139
  return slash <= 0 ? ROOT_PATH : `${trimmed.slice(0, slash)}/`;
2151
2140
  }
2141
+ var DEMO_TOTAL_WEIGHT = DEMO_AUDIT_FACTORS.reduce((sum, factor) => sum + factor.weight, 0);
2142
+ var DEMO_FACTOR_SHARES = roundPreservingTotal(DEMO_AUDIT_FACTORS.map((factor) => factor.weight / DEMO_TOTAL_WEIGHT * 100), 1);
2152
2143
  function auditFactors(page) {
2153
- const totalWeight = DEMO_AUDIT_FACTORS.reduce((sum, factor) => sum + factor.weight, 0);
2154
2144
  const offsets = DEMO_AUDIT_FACTORS.map((factor) => factor.bias + (unitHash(`${page.path}#${factor.id}`) * 2 - 1) * 12);
2155
- const meanOffset = DEMO_AUDIT_FACTORS.reduce((sum, factor, index) => sum + offsets[index] * factor.weight, 0) / totalWeight;
2145
+ const meanOffset = DEMO_AUDIT_FACTORS.reduce((sum, factor, index) => sum + offsets[index] * factor.weight, 0) / DEMO_TOTAL_WEIGHT;
2156
2146
  const factors = DEMO_AUDIT_FACTORS.map((factor, index) => {
2157
2147
  const score2 = page.factorScores?.[factor.id] ?? Math.max(0, Math.min(100, Math.round(page.score + offsets[index] - meanOffset)));
2158
2148
  const status = factorStatusFromScore(score2);
@@ -2162,13 +2152,14 @@ function auditFactors(page) {
2162
2152
  name: factor.name,
2163
2153
  weight: factor.weight,
2164
2154
  score: score2,
2155
+ sharePct: DEMO_FACTOR_SHARES[index] ?? null,
2165
2156
  status,
2166
2157
  applicable: true,
2167
2158
  findings: [{ type: passing ? "found" : "missing", code: `${factor.id}.${passing ? "present" : "gap"}`, message: passing ? factor.found : factor.missing }],
2168
2159
  recommendations: passing ? [] : [factor.recommendation]
2169
2160
  };
2170
2161
  });
2171
- const score = Math.round(factors.reduce((sum, factor) => sum + factor.score * factor.weight, 0) / totalWeight);
2162
+ const score = Math.round(factors.reduce((sum, factor) => sum + factor.score * factor.weight, 0) / DEMO_TOTAL_WEIGHT);
2172
2163
  return { score, factors };
2173
2164
  }
2174
2165
  function buildDemoSiteCrawl(input) {
@@ -2320,10 +2311,11 @@ function buildDemoSiteCrawl(input) {
2320
2311
  outboundUniqueEdges: outboundEdges.length,
2321
2312
  inboundOccurrences: inboundEdges.reduce((sum, edge) => sum + edge.occurrences, 0),
2322
2313
  outboundOccurrences: outboundEdges.reduce((sum, edge) => sum + edge.occurrences, 0),
2323
- // Raw score is PageRank, as the crawler computes it. Node size reads the normalized value on a 0 to 1
2324
- // log scale of inbound links, so hub pages stay visibly larger than the pages they link to.
2314
+ // Raw score is PageRank, as the crawler computes it. The normalized score uses the crawler's scale, 0 to 100
2315
+ // against the top page with two decimals, but follows a log of inbound links so hub pages stay visibly larger
2316
+ // than the pages they link to.
2325
2317
  linkScoreRaw: Number(rank.toFixed(12)),
2326
- linkScoreNormalized: Math.log1p(inboundEdges.length) / Math.log1p(maxInbound),
2318
+ linkScoreNormalized: Number((Math.log1p(inboundEdges.length) / Math.log1p(maxInbound) * 100).toFixed(2)),
2327
2319
  createdAt: nowIso,
2328
2320
  updatedAt: nowIso
2329
2321
  };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FastifyInstance } from 'fastify';
2
2
  import { DatabaseClient } from '@ainyc/canonry-db';
3
- import { ProviderQuotaPolicy, SchedulableRunKind, AgentProviderId, EmbedConfigEntry, AgentPluginState, GoogleAdsCampaignMetricsQuery, GoogleAdsRawSnapshotDto, GoogleAdsEffectiveGoalGraphDto, GoogleMarketingProvider, GoogleAdsAccessibleCustomersResponse, GoogleAdsAccessibleCustomerDto, GtmAccountsResponse, GtmContainerListResponse, GtmWorkspaceListResponse, GtmRawSnapshotDto } from '@ainyc/canonry-contracts';
3
+ import { ProviderQuotaPolicy, ProviderBatchConfig, ProviderPricing, SchedulableRunKind, AgentProviderId, EmbedConfigEntry, AgentPluginState, GoogleAdsCampaignMetricsQuery, GoogleAdsRawSnapshotDto, GoogleAdsEffectiveGoalGraphDto, GoogleMarketingProvider, GoogleAdsAccessibleCustomersResponse, GoogleAdsAccessibleCustomerDto, GtmAccountsResponse, GtmContainerListResponse, GtmWorkspaceListResponse, GtmRawSnapshotDto } from '@ainyc/canonry-contracts';
4
4
  import { GoogleTokenResponse } from '@ainyc/canonry-integration-google';
5
5
 
6
6
  type GoogleConnectionType = 'gsc' | 'ga4' | 'gbp';
@@ -15,6 +15,14 @@ interface ProviderConfigEntry {
15
15
  vertexRegion?: string;
16
16
  /** Path to service account JSON for Vertex AI auth (falls back to ADC) */
17
17
  vertexCredentials?: string;
18
+ /**
19
+ * Batch dispatch for scheduled sweeps (`docs/batch-mode.md`). Off unless
20
+ * `enabled: true`, and only for a provider whose adapter has a batch API.
21
+ * Anthropic batches are not zero-data-retention eligible.
22
+ */
23
+ batch?: ProviderBatchConfig;
24
+ /** Price overrides (USD) per model id, winning over the built-in table. */
25
+ pricing?: ProviderPricing;
18
26
  }
19
27
  interface CdpConfigEntry {
20
28
  host?: string;
package/dist/index.js CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-XFHXKLNT.js";
6
+ } from "./chunk-7BW7BAD5.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-GLLY2GEV.js";
10
- import "./chunk-3LCR6WU6.js";
11
- import "./chunk-DDL2XSNM.js";
12
- import "./chunk-P5VXVFQW.js";
13
- import "./chunk-S5OSY3PI.js";
9
+ } from "./chunk-VPIOF2PB.js";
10
+ import "./chunk-THMIDWMS.js";
11
+ import "./chunk-J6BJIOIN.js";
12
+ import "./chunk-KGYHEYHX.js";
13
+ import "./chunk-DCGELKRW.js";
14
14
  export {
15
15
  GoogleMarketingRuntimeError,
16
16
  createGoogleMarketingCredentialStore,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  HISTORY_WINDOW_RUNS,
3
3
  IntelligenceService
4
- } from "./chunk-P5VXVFQW.js";
5
- import "./chunk-S5OSY3PI.js";
4
+ } from "./chunk-KGYHEYHX.js";
5
+ import "./chunk-DCGELKRW.js";
6
6
  export {
7
7
  HISTORY_WINDOW_RUNS,
8
8
  IntelligenceService
package/dist/mcp.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-YTSXQUJ3.js";
3
+ } from "./chunk-WPQB4UYX.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-GLLY2GEV.js";
8
- import "./chunk-DDL2XSNM.js";
7
+ } from "./chunk-VPIOF2PB.js";
8
+ import "./chunk-J6BJIOIN.js";
9
9
  import {
10
10
  isReadOnlyKey,
11
11
  updateCheckEnvOptOut
12
- } from "./chunk-S5OSY3PI.js";
12
+ } from "./chunk-DCGELKRW.js";
13
13
 
14
14
  // src/mcp/cli.ts
15
15
  import { randomUUID } from "crypto";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "5.22.0",
3
+ "version": "5.29.0",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "keywords": [
@@ -87,30 +87,31 @@
87
87
  "tsup": "^8.5.1",
88
88
  "tsx": "^4.19.0",
89
89
  "@ainyc/canonry-web": "0.0.0",
90
- "@ainyc/canonry-api-client": "0.0.0",
91
90
  "@ainyc/canonry-config": "0.0.0",
91
+ "@ainyc/canonry-api-client": "0.0.0",
92
92
  "@ainyc/canonry-api-routes": "0.0.0",
93
93
  "@ainyc/canonry-contracts": "0.0.0",
94
94
  "@ainyc/canonry-db": "0.0.0",
95
- "@ainyc/canonry-integration-bing": "0.0.0",
96
95
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
97
- "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
96
+ "@ainyc/canonry-integration-bing": "0.0.0",
98
97
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
99
- "@ainyc/canonry-integration-google": "0.0.0",
100
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
101
98
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
102
- "@ainyc/canonry-integration-google-places": "0.0.0",
99
+ "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
100
+ "@ainyc/canonry-integration-google": "0.0.0",
103
101
  "@ainyc/canonry-integration-google-ads": "0.0.0",
102
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
104
103
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
104
+ "@ainyc/canonry-integration-traffic": "0.0.0",
105
105
  "@ainyc/canonry-intelligence": "0.0.0",
106
106
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
107
- "@ainyc/canonry-integration-wordpress": "0.0.0",
108
107
  "@ainyc/canonry-provider-cdp": "0.0.0",
109
- "@ainyc/canonry-integration-traffic": "0.0.0",
110
- "@ainyc/canonry-provider-local": "0.0.0",
108
+ "@ainyc/canonry-integration-google-places": "0.0.0",
109
+ "@ainyc/canonry-provider-claude": "0.0.0",
111
110
  "@ainyc/canonry-provider-gemini": "0.0.0",
111
+ "@ainyc/canonry-provider-local": "0.0.0",
112
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
113
+ "@ainyc/canonry-provider-muse": "0.0.0",
112
114
  "@ainyc/canonry-provider-openai": "0.0.0",
113
- "@ainyc/canonry-provider-claude": "0.0.0",
114
115
  "@ainyc/canonry-provider-perplexity": "0.0.0"
115
116
  },
116
117
  "scripts": {
@@ -1 +0,0 @@
1
- import{j as i}from"./vendor-tanstack-ZXXkndVj.js";import{R as k,C as I,a as R,e as A,X as _,Y as L,T as w,d as v}from"./vendor-recharts-llkUFBGR.js";const O={contentStyle:{backgroundColor:"var(--chart-tooltip-bg, #18181b)",border:"1px solid var(--chart-tooltip-border, #3f3f46)",borderRadius:8,fontSize:12},labelStyle:{color:"var(--chart-tooltip-label, #e4e4e7)"},itemStyle:{color:"var(--chart-tooltip-item, #a1a1aa)"}},b={fill:"var(--chart-neutral-text-dim, #8b8b93)",fontSize:11},j="var(--chart-grid, #27272a)",p="var(--chart-axis, #27272a)",y=["var(--chart-series-1, #34d399)","var(--chart-series-2, #60a5fa)","var(--chart-series-3, #f472b6)","var(--chart-series-4, #facc15)","var(--chart-series-5, #a78bfa)","var(--chart-series-6, #fb923c)","var(--chart-series-7, #22d3ee)","var(--chart-series-8, #f87171)"],K={gemini:"#60a5fa",openai:"#34d399",claude:"#fb923c",perplexity:"#22d3ee",local:"#a78bfa"};function M(a,r=0){return K[a]??y[r%y.length]}const E={text:"var(--chart-neutral-text, #a1a1aa)",textDim:"var(--chart-neutral-text-dim, #8b8b93)",textFaint:"var(--chart-neutral-text-faint, #52525b)",surface:"var(--chart-neutral-surface, #27272a)",trackSubtle:"var(--chart-neutral-track-subtle, rgb(255 255 255 / 0.04))"},N={positive:"var(--chart-tone-positive, #34d399)",positiveDeep:"var(--chart-tone-positive-deep, #10b981)",caution:"var(--chart-tone-caution, #fbbf24)",negative:"var(--chart-tone-negative, #fb7185)",neutral:"var(--chart-tone-neutral, #a1a1aa)"};function U(a){return a}function f(a){const r=/^(\d{4})-(\d{2})-(\d{2})/.exec(a);return r?{year:Number(r[1]),month:Number(r[2]),day:Number(r[3])}:null}function Y(a){const r=String(a),e=f(r);return e?new Date(Date.UTC(e.year,e.month-1,e.day)).toLocaleDateString(void 0,{timeZone:"UTC",month:"short",day:"numeric",year:"numeric"}):r}function F(a){const r=f(String(a));return r?`${r.month}/${r.day}`:String(a)}function G(a){const r=f(String(a));return r?new Date(Date.UTC(r.year,r.month-1,r.day)).toLocaleDateString(void 0,{timeZone:"UTC",month:"short",day:"numeric"}):String(a)}function P(a){return new Date(a).toLocaleDateString(void 0,{month:"short",day:"numeric",year:"numeric"})}function V(a){return new Date(a).toLocaleDateString(void 0,{month:"short",day:"numeric"})}function W(a){return new Date(a).getFullYear()}function z(a){const r=new Date(a);return`${r.getMonth()+1}/${r.getDate()}`}function Z({data:a,xKey:r,series:e,height:x=260,xTickFormatter:g,labelFormatter:u,onSelectX:d,selectedX:h,accessibilityLayer:S=!0,ariaLabel:T}){const m=[...new Set(e.map(t=>t.axisId))],C=new Map(e.map(t=>[t.label,t.formatValue])),D=a.map((t,s)=>{const n={...t};for(const o of e){if(!o.trend)continue;const c=o.trend.startIndex??0,l=o.trend.endIndex??a.length-1;if(s<c||s>l){n[`${o.dataKey}__trend`]=null;continue}n[`${o.dataKey}__trend`]=l<=c?o.trend.start:o.trend.start+(o.trend.end-o.trend.start)*(s-c)/(l-c)}return n});return i.jsx(k,{width:"100%",height:x,children:i.jsxs(I,{data:D,accessibilityLayer:S,"aria-label":T,margin:{top:8,right:8,bottom:4,left:0},onClick:d?t=>{t?.activeLabel!==void 0&&d(String(t.activeLabel))}:void 0,style:d?{cursor:"pointer"}:void 0,children:[i.jsx(R,{stroke:j,strokeDasharray:"3 3",vertical:!1}),h!=null&&i.jsx(A,{x:h,yAxisId:m[0],stroke:E.text,strokeDasharray:"2 3",strokeWidth:1}),i.jsx(_,{dataKey:r,tick:b,stroke:p,tickFormatter:g,minTickGap:24}),m.map((t,s)=>{const n=e.find(o=>o.axisId===t);return i.jsx(L,{yAxisId:t,orientation:s===1?"right":"left",hide:s>1,reversed:n.inverted??!1,domain:n.inverted?[1,"auto"]:[0,"auto"],tick:b,stroke:p,width:48,tickFormatter:n.formatValue},t)}),i.jsx(w,{...O,labelFormatter:t=>u?u(String(t)):String(t),formatter:(t,s)=>{const n=String(s??"");return typeof t!="number"?[String(t??""),n]:[C.get(n)?.(t)??t.toLocaleString(),n]}}),e.filter(t=>t.trend).map(t=>i.jsx(v,{yAxisId:t.axisId,dataKey:`${t.dataKey}__trend`,name:`${t.label} trend`,stroke:t.color,strokeWidth:1.5,strokeDasharray:"5 4",strokeOpacity:.55,dot:!1,activeDot:!1,isAnimationActive:!1,legendType:"none",tooltipType:"none"},`${t.dataKey}-trend`)),e.map(t=>i.jsx(v,{yAxisId:t.axisId,dataKey:t.dataKey,name:t.label,stroke:t.color,strokeWidth:2,dot:!1,activeDot:{r:3},connectNulls:!1,isAnimationActive:!1},t.dataKey))]})})}export{j as C,Z as M,p as a,b,Y as c,O as d,y as e,F as f,E as g,N as h,z as i,P as j,G as k,W as l,V as m,U as o,M as p};
@@ -1 +0,0 @@
1
- import{D as Ne,k as we,l as Pe,r as b,u as L,C as Ce,j as e,L as I}from"./vendor-tanstack-ZXXkndVj.js";import{dS as Ee,ed as Le,dL as Me,dJ as Ae,x as Se,e2 as Re,dZ as z,fg as ke,fh as Te,j as M,fi as qe,B as g,I as P,T as w,az as ae,aA as ne,ef as D,fj as Ie,bX as Ue,fk as Be,fl as _e,A as $e,aL as ce}from"./index-DwlO8KfE.js";import{j as Oe,o as Ve}from"./ChartPrimitives-BQC2VH0O.js";import{m as Qe,a as he,M as Fe,A as Ke}from"./v2-overview-adapter-OsQiglXU.js";import{Z as ze}from"./vendor-lucide-N6vOpZmh.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-llkUFBGR.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";const re=50,u={branded:{headline:"When they know your name",technical:"Branded queries"},"non-brand":{headline:"When they don't",technical:"Non-brand queries"}},De={plan_v1:"Setup update required",no_completed_run:"No completed measurement yet",no_population:"No queries of this type are assigned",evidence_incomplete:"Source evidence is incomplete",identity_ambiguous:Ue,not_applicable:"Not applicable for this Property"},ie={complete:{label:"Measured",tone:"positive"},partial:{label:"Partly measured",tone:"caution"},running:{label:"Measuring now",tone:"neutral"},queued:{label:"Measurement queued",tone:"neutral"},failed:{label:"Measurement failed",tone:"negative"},not_measured:{label:"Not measured",tone:"neutral"}},oe={assigned:{label:"Matches this Property",tone:"positive"},sibling:{label:"Matches another Property",tone:"caution"},ownedUnmapped:{label:"Site URL not in a Property",tone:"caution"},external:{label:"External URL",tone:"neutral"},ambiguous:{label:"Matches multiple Properties",tone:"caution"},invalid:{label:"Invalid URL",tone:"negative"}};function He(s){return[...s].sort((t,a)=>+(a.classification==="assigned")-+(t.classification==="assigned"))}function We(s){return`${s.expectedSlotId}:${s.usageEdgeId}`}function Ge({row:s}){return s.mentioned===null?e.jsxs("span",{className:"inline-flex flex-col items-start gap-0.5",children:[e.jsx(w,{tone:"neutral",children:"Not measured"}),e.jsx("span",{className:"text-xs text-muted",children:"No mention signal for this Property"})]}):e.jsx(w,{tone:s.mentioned?"positive":"neutral",children:s.mentioned?"Mentioned":"Not mentioned"})}const Ze="—";function Ye({row:s}){return s.cited===null?e.jsxs("span",{className:"inline-flex flex-col items-start gap-0.5",children:[e.jsx(w,{tone:"neutral",children:"Not measured"}),e.jsx("span",{className:"text-xs text-muted",children:"Sources were not fully captured"})]}):e.jsx(w,{tone:s.cited?"positive":"neutral",children:s.cited?"Cited":"Not cited"})}function Je({row:s}){return s.cited===null&&s.sources.length===0?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"The sources for this answer were not fully captured, so none can be shown."}):s.sources.length===0?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"This answer returned no source URLs at all."}):e.jsxs("details",{className:"mt-2","data-answer-sources":!0,children:[e.jsxs("summary",{className:"min-h-11 cursor-pointer py-3 text-sm text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:[he," (",s.sources.length,")"]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsxs("caption",{className:"sr-only",children:["Source URLs for ",s.queryText]}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Match"}),e.jsx("th",{children:"URL"})]})}),e.jsx("tbody",{children:He(s.sources).map(t=>{const a=$e(t.sourceUrl);return e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx(w,{tone:oe[t.classification].tone,children:oe[t.classification].label})}),e.jsx("td",{className:"break-all text-secondary",children:a?e.jsx("a",{href:a,target:"_blank",rel:"noopener noreferrer",className:"text-link underline",children:t.sourceUrl}):t.sourceUrl})]},t.sourceUrl)})})]})})]})}function Xe({project:s,targetKey:t,row:a}){const r=L({..._e({client:M,path:{name:s},query:{targetKey:t,resultId:a.observationId}})});if(r.isPending)return e.jsx("p",{className:"py-2 text-sm text-secondary",role:"status","aria-live":"polite",children:"Loading the answer…"});if(r.isError)return e.jsx("p",{className:"py-2 text-sm text-secondary",role:"alert",children:"Could not load this answer."});const i=r.data?.answer;return i==null||i.trim()===""?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"This answer was measured, but its text was not stored."}):e.jsx("div",{className:"py-2",children:e.jsx(Ke,{headingLevel:4,copyable:!0,children:i})})}function B(s){return De[s.reason]??"Not measured"}function U({metric:s,emphasis:t=!1}){if(s.state==="unavailable")return e.jsxs("span",{className:"inline-flex flex-col gap-0.5",children:[e.jsx("span",{className:t?"text-lg font-semibold text-secondary":"text-sm font-medium text-secondary",children:"Not measured"}),e.jsx("span",{className:"text-sm text-secondary",children:B(s)})]});const a=`${Math.round(s.value*100)}%`,r=s.numerator===void 0||s.denominator===void 0?null:`${s.numerator} of ${s.denominator}`,i=ce(s);return e.jsxs("span",{className:"inline-flex flex-col gap-0.5 tabular-nums",children:[e.jsx("span",{className:t?"text-lg font-semibold text-heading":"text-sm font-medium text-primary",children:a}),r?e.jsx("span",{className:"text-xs text-muted",children:r}):null,i?e.jsx("span",{className:"text-xs text-muted",children:i}):null]})}function le(s,t,a){return Ie({client:M,path:{name:s},query:{scope:"property",targetKey:t,queryClass:a}})}function de(s){return s?.properties.items.at(0)}function es({measuredAt:s,unmeasuredReason:t,queryClass:a}){const r=s===void 0?null:s===null?"No completed sweep yet":`Measured ${Oe(Ve(s))}`;return r===null&&t===void 0?null:e.jsxs("p",{className:"supporting-copy",children:[[r,t].filter(Boolean).join(" · "),r!==null&&t===void 0?` · ${u[a].technical.toLocaleLowerCase()} only`:""]})}function ss({project:s,groups:t}){return t.length===0?null:e.jsxs("section",{"aria-labelledby":"property-market",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Competitive comparison"}),e.jsxs("h2",{id:"property-market",className:"text-base font-semibold text-heading",children:["Measured at the market level",e.jsx(P,{text:"Competitors are attached to a market rather than to a single Property, because one building has nobody to be compared against. Share of voice and competitor pressure are reported for the market this Property sits in."})]})]}),e.jsx(g,{asChild:!0,type:"button",size:"sm",variant:"outline",children:e.jsx(I,{to:"/projects/$projectName",params:{projectName:s},search:a=>z(D(a),{measurementScope:"project"}),children:"Open measurement overview"})})]}),e.jsx("ul",{className:"flex flex-wrap gap-2",children:t.map(a=>e.jsxs("li",{className:"rounded-md border border-default px-3 py-1.5 text-sm text-strong",children:[a.label,e.jsxs("span",{className:"ml-2 text-xs text-muted",children:[a.competitors.length," ",a.competitors.length===1?"competitor":"competitors"]})]},a.stableKey))})]})}function q({label:s,metric:t,failed:a=!1}){if(t===void 0)return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsx("p",{className:"aeo-hero-row-value text-base font-semibold text-secondary",children:a?"Unavailable":"…"}),a?e.jsx("div",{}):e.jsx("div",{className:"aeo-hero-row-bar","aria-hidden":"true"}),e.jsx("p",{className:"aeo-hero-row-detail",children:a?"Could not be loaded":"Loading"})]});if(t.state==="unavailable"){const o=B(t);return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsx("p",{className:"aeo-hero-row-value text-base font-semibold text-secondary",children:"Not measured"}),e.jsx("div",{}),e.jsx("p",{className:"aeo-hero-row-detail",children:o==="Not measured"?"":o})]})}const r=Math.round(t.value*100),i=t.numerator===void 0||t.denominator===void 0?null:`${t.numerator} of ${t.denominator}`,j=ce(t);return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsxs("p",{className:"aeo-hero-row-value text-heading",children:[r,e.jsx("span",{className:"text-faint",children:"%"})]}),e.jsx("div",{className:"aeo-hero-row-bar","aria-hidden":"true",children:e.jsx("div",{className:"metric-card-bar-fill progress-fill-neutral",style:{width:`${r}%`}})}),e.jsxs("p",{className:"aeo-hero-row-detail tabular-nums",children:[i??"",j?e.jsx("span",{className:"block",children:j}):null]})]})}function ts({branded:s,nonBrand:t,brandedFailed:a=!1,nonBrandFailed:r=!1}){return e.jsxs("section",{"aria-labelledby":"property-coverage-hero",children:[e.jsx("h2",{id:"property-coverage-hero",className:"sr-only",children:"Coverage for this Property"}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Non-brand · the demand to earn"}),e.jsx(q,{label:"Mentioned",metric:t?.mentionCoverage,failed:r}),e.jsx(q,{label:"Cited",metric:t?.citationCoverage,failed:r})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Branded · already named"}),e.jsx(q,{label:"Mentioned",metric:s?.mentionCoverage,failed:a}),e.jsx(q,{label:"Cited",metric:s?.citationCoverage,failed:a})]})]})]})}function as({branded:s,nonBrand:t,brandedError:a,nonBrandError:r,onRetry:i}){const j=[{queryClass:"branded",row:s,isError:a},{queryClass:"non-brand",row:t,isError:r}];return e.jsxs("section",{"aria-labelledby":"property-brand-contrast",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"The gap"}),e.jsxs("h2",{id:"property-brand-contrast",className:"text-base font-semibold text-heading",children:["Named versus not named",e.jsx(P,{text:"Branded queries already contain your name, so an answer engine has an easy path back to you. Non-brand queries describe the need instead, and that is the demand you have to earn. Each row is measured only over the queries assigned to this Property in that class; a class with no assigned query reads Not measured rather than 0%."})]})]})}),e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[560px]",children:[e.jsx("caption",{className:"sr-only",children:"Mention and citation coverage for this Property, split by query class"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query type"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"})]})}),e.jsx("tbody",{children:j.map(({queryClass:o,row:d,isError:c})=>e.jsxs("tr",{children:[e.jsxs("td",{children:[e.jsx("span",{className:"block font-medium text-heading",children:u[o].headline}),e.jsx("span",{className:"mt-0.5 block text-xs text-muted",children:u[o].technical}),d&&c?e.jsxs("span",{className:"mt-2 flex flex-wrap items-center gap-2 text-sm text-caution",children:[e.jsx("span",{role:"status",children:"Refresh failed."}),e.jsxs(g,{type:"button",size:"sm",variant:"ghost",className:"h-11 px-3 text-sm md:h-11",onClick:()=>i(o),children:["Retry ",u[o].technical.toLocaleLowerCase()]})]}):null]}),d?e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx(U,{metric:d.mentionCoverage,emphasis:!0})}),e.jsx("td",{children:e.jsx(U,{metric:d.citationCoverage,emphasis:!0})})]}):c?e.jsx("td",{colSpan:2,children:e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{role:"alert",children:["Could not load ",u[o].technical.toLocaleLowerCase(),"."]}),e.jsxs(g,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>i(o),children:["Retry ",u[o].technical.toLocaleLowerCase()]})]})}):e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx("span",{className:"text-sm text-secondary",children:"Loading…"})}),e.jsx("td",{children:e.jsx("span",{className:"text-sm text-secondary",children:"Loading…"})})]})]},o))})]})})]})}function ns({row:s,queryClass:t,isError:a}){return e.jsxs("section",{"aria-labelledby":"property-providers",className:"page-section-divider",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsx("div",{children:e.jsxs("h2",{id:"property-providers",className:"text-base font-semibold text-heading",children:["Which engines answer for this Property",e.jsx(P,{text:"Each row is measured over the queries that engine actually answered for this Property, so the rows are a split of the same population rather than parts that add up to the Property total. An engine that answered nothing for this Property is absent instead of shown at 0%."})]})})}),s===void 0&&a?e.jsxs("p",{className:"text-sm text-secondary",children:["Details for ",u[t].technical.toLocaleLowerCase()," are unavailable. Retry that query type above."]}):s===void 0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading…"}):s.providers.length===0?e.jsxs("p",{className:"text-sm text-secondary",children:["No answer engine has measured ",u[t].technical.toLocaleLowerCase()," for this Property.",s.mentionCoverage.state==="unavailable"?` ${B(s.mentionCoverage)}.`:""]}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[520px]",children:[e.jsx("caption",{className:"sr-only",children:"Per-engine mention and citation coverage"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Engine"}),e.jsx("th",{children:"Mentioned"}),e.jsx("th",{children:"Cited"})]})}),e.jsx("tbody",{children:s.providers.map(r=>e.jsxs("tr",{children:[e.jsx("td",{className:"font-medium text-heading",children:r.provider}),e.jsx("td",{children:e.jsx(U,{metric:r.mentionCoverage})}),e.jsx("td",{children:e.jsx(U,{metric:r.citationCoverage})})]},r.provider))})]})})]})}function rs(s){const t=s.questions.join(" · ");return s.questionsTruncated?`${t} +${s.questionTotal-s.questions.length} more`:t}function is({project:s,targetKey:t,queryClass:a}){const r=L({...Be({client:M,path:{name:s},query:{targetKey:t,queryClass:a}})});if(r.isPending||r.isError)return null;const i=r.data?.competitors??[],j=r.data?.basis;return e.jsxs("section",{"aria-labelledby":"property-named-instead",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-named-instead",className:"text-base font-semibold text-heading",children:["Named instead of this Property",e.jsx(P,{text:"Counted from the answers that did not name this Property, so a name here is one an engine recommended in its place. Occurrences count answers, not positions: an engine naming the same rival in two answers counts twice, and one naming it twice in a single answer counts once."})]})}),i.length>0?e.jsxs("p",{className:"supporting-copy",children:[r.data?.total??i.length," named"]}):null]}),i.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No rival was named in the answers this Property missed. Nothing to compete with here yet."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"Names the engines gave instead of this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Named"}),e.jsx("th",{children:"Answers"}),e.jsx("th",{children:"Engines"}),e.jsx("th",{children:"Queries"})]})}),e.jsx("tbody",{children:i.map(o=>e.jsxs("tr",{children:[e.jsx("td",{className:"text-strong",children:o.name}),e.jsx("td",{className:"tabular-nums text-secondary",children:o.occurrences}),e.jsxs("td",{className:"text-secondary",children:[o.providers.join(", "),o.providersTruncated?` +${o.providerTotal-o.providers.length}`:""]}),e.jsx("td",{className:"text-right",children:e.jsxs("span",{className:"inline-flex items-center justify-end gap-1",children:[e.jsx("span",{className:"tabular-nums text-secondary",children:o.questionTotal}),e.jsx(P,{text:rs(o)})]})})]},o.name))})]})}),j?.state==="available"?e.jsxs("p",{className:"supporting-copy mt-2",children:[j.targetMissResults," of ",j.answeredResults," answers to ",u[a].technical.toLocaleLowerCase()," did not name this Property."]}):null]})]})}function os({questions:s,queryClass:t}){return e.jsxs("section",{"aria-labelledby":"property-questions",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-questions",className:"text-base font-semibold text-heading",children:[u[t].technical," assigned to this Property"]})}),e.jsxs("p",{className:"supporting-copy",children:[s.length," assigned"]})]}),s.length===0?e.jsxs("p",{className:"text-sm text-secondary",children:["No ",u[t].technical.toLocaleLowerCase()," are assigned. Add one in advanced measurement setup to measure this class."]}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"Queries assigned to this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"Query"})})}),e.jsx("tbody",{children:s.map(a=>e.jsx("tr",{children:e.jsx("td",{className:"text-secondary",children:a})},a))})]})})]})}function ls({urls:s}){return e.jsxs("section",{"aria-labelledby":"property-urls",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-urls",className:"text-base font-semibold text-heading",children:["URLs that count as this Property",e.jsx(P,{text:"A cited source URL is credited to this Property when it matches one of these. The most specific matcher wins, so a URL covered by two Properties at the same specificity is flagged for review instead of being credited to either."})]})}),e.jsxs("p",{className:"supporting-copy",children:[s.length," configured"]})]}),s.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No URLs are configured for this Property."}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"URL matchers configured for this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"URL"})})}),e.jsx("tbody",{children:s.map(t=>e.jsx("tr",{children:e.jsx("td",{className:"break-all text-secondary",children:t})},t))})]})})]})}function ds(s,t){const a=[s.marketKey?t??"the selected market":null,s.provider?`the ${s.provider} answer engine`:null,s.model?`the ${s.model} model`:null,s.location?`location ${s.location}`:null,s.from||s.to?"a date range":null,s.measurementRunId?"a saved sweep":null].filter(r=>r!==null);return a.length===0?null:`AI Visibility is filtered to ${a.join(", ")}. This page shows the latest measurement for ${Fe.allMarkets.toLocaleLowerCase()} and answer engines.`}function vs(){const{projectName:s,targetKey:t}=Ne({strict:!1}),a=we(),r=Pe({strict:!1}),i=b.useMemo(()=>Ee(r),[r]),[j,o]=b.useState(new Set),d=s??"",c=t??"",H=!!d&&!!c,W=b.useMemo(()=>Le("portfolio",Me(Ae())),[]),A=H&&W,{canWrite:_}=Se(),C=L({...Re({client:M,path:{name:d}}),enabled:A}),G=C.data?.active?.plan,$=G?.schemaVersion===2?G:null,O=i.queryClass==="branded"||i.queryClass==="non-brand"?i.queryClass:null,Z=n=>$?.assignments.some(l=>l.targetKey===c&&l.queryClass===n)??!1,h=O??(!Z("non-brand")&&Z("branded")?"branded":"non-brand");b.useEffect(()=>{!$||O||a({to:".",replace:!0,search:n=>z(n,{queryClass:h})})},[$,O,h,a]);const v=L({...le(d,c,"branded"),enabled:A}),f=L({...le(d,c,"non-brand"),enabled:A}),V=de(v.data),Q=de(f.data),y=h==="branded"?v.data:f.data,E=h==="branded"?V:Q,Y=(h==="branded"?v.isError:f.isError)&&E===void 0,S=y?.measurement.displayedRunId;ke(d,{view:"property",selection:{mode:"advanced",scope:"property",scopeKey:c,queryClass:h,limit:10,...S?{runId:S}:{}}});const me=E?.mentionCoverage.state==="unavailable"?B(E.mentionCoverage):void 0,xe=y===void 0?void 0:y.measurement.completedAt??null,R={client:M,path:{name:d},query:{targetKey:c,queryClass:h,shape:Te.answers,limit:re,...S?{runId:S}:{}}},m=Ce({...qe(R),enabled:A&&y!==void 0,initialPageParam:R,getNextPageParam:n=>n.answers?.nextCursor?{path:R.path,query:{...R.query,cursor:n.answers.nextCursor}}:void 0}),F=C.data?.active??null,p=F?.plan.schemaVersion===2?F.plan:null,ue=F!==null&&p===null,k=p?.targets.find(n=>n.stableKey===c)??null,J=ds(i,p?.reportingScopes?.find(n=>n.stableKey===i.marketKey)?.label),pe=b.useMemo(()=>{if(!p)return[];const n=new Map(p.querySnapshots.map(l=>[l.queryId,l.queryText]));return[...new Set(p.assignments.filter(l=>l.targetKey===c&&l.queryClass===h).flatMap(l=>{const x=n.get(l.queryId);return x===void 0?[]:[x]}))].sort((l,x)=>l.localeCompare(x))},[p,c,h]),je=b.useMemo(()=>k?.urlMatchers.map(Qe)??[],[k]),ye=b.useMemo(()=>p?.groups.filter(n=>n.targetKeys.includes(c))??[],[p,c]),N=b.useMemo(()=>(m.data?.pages??[]).flatMap(x=>x.answers?.items??[]),[m.data]),X=m.data?.pages[0]?.answers?.totalEstimate??N.length,be=(m.data?.pages??[]).length>0&&(m.data?.pages??[]).every(n=>n.answers===void 0),ge=m.data?.pages[0]?.measurement.state,T=e.jsxs(I,{to:"/projects/$projectName",params:{projectName:d},search:D,className:"inline-flex items-center gap-1 text-xs text-muted hover:text-strong",children:[e.jsx(ze,{className:"size-3.5","aria-hidden":"true"}),"Back to AI Visibility"]});if(!H)return e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-muted",children:"Missing project name or Property key in URL."})});if(!W)return e.jsxs("div",{className:"page-container space-y-3",children:[T,e.jsx("p",{className:"text-sm text-muted",children:"This view is not available here."})]});if(C.isPending&&!C.isError)return e.jsx("div",{className:"page-container",children:e.jsxs("div",{role:"status","aria-live":"polite",children:[e.jsx("span",{className:"sr-only",children:"Loading Property"}),e.jsx("div",{className:"h-32 animate-pulse rounded-md bg-surface-subtle","aria-hidden":"true"})]})});const ve=C.isError&&C.data===void 0,ee=v.isError&&v.data===void 0,se=f.isError&&f.data===void 0;return ve||ee&&se?e.jsxs("div",{className:"page-container space-y-3",children:[T,e.jsx("p",{role:"alert",className:"text-sm text-negative",children:"Could not load this Property."}),e.jsx(g,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{C.refetch(),v.refetch(),f.refetch()},children:"Try again"})]}):!p||!k?e.jsxs("div",{className:"page-container space-y-3",children:[T,e.jsx("p",{role:"status",className:"text-sm text-secondary",children:p?"This Property is not in the published setup. It may have been renamed or removed.":"A Property page needs a published advanced measurement setup. Republish setup from the project Portfolio tab."}),e.jsx(g,{asChild:!0,type:"button",variant:"outline",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(I,{to:"/projects/$projectName/portfolio",params:{projectName:d},children:_?ue?"Republish setup":"Open measurement setup":"View measurement setup"})})]}):e.jsxs("div",{className:"page-container space-y-8",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[T,e.jsx("h1",{className:"page-title mt-2",children:k.label}),e.jsxs("p",{className:"page-subtitle",children:["Property in ",d,J?e.jsxs(e.Fragment,{children:[" · Filters not applied ",e.jsx(P,{text:J})]}):null]})]}),e.jsxs("div",{className:"page-header-right",children:[y?e.jsx(w,{tone:ie[y.measurement.state].tone,children:ie[y.measurement.state].label}):null,E&&E.flags>0?e.jsxs(w,{tone:"caution",children:[E.flags," flagged"]}):null]})]}),e.jsx(ts,{branded:V,nonBrand:Q,brandedFailed:ee,nonBrandFailed:se}),e.jsx(as,{branded:V,nonBrand:Q,brandedError:v.isError,nonBrandError:f.isError,onRetry:n=>{n==="branded"?v.refetch():f.refetch()}}),y&&(y.measurement.state==="not_measured"||y.nextAction.kind==="run_measurement")?e.jsxs("section",{className:"flex flex-wrap items-center justify-between gap-3 border-y border-default py-4","aria-label":"Measurement next step",children:[e.jsx("p",{className:"text-sm text-secondary",children:ne()?ae:_?"Run a measurement from the project overview to collect this Property’s coverage and source evidence.":"This Property needs a new measurement before coverage and source evidence are available."}),e.jsx(g,{asChild:!0,type:"button",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(I,{to:"/projects/$projectName",params:{projectName:d},search:D,children:_?"Go to AI Visibility":"View AI Visibility"})})]}):null,e.jsxs("div",{className:"flex flex-wrap items-end gap-4 border-y border-default py-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{htmlFor:"property-query-class",className:"block text-sm font-medium text-heading",children:"Query type"}),e.jsxs("select",{id:"property-query-class",value:h,onChange:n=>{const l=n.target.value==="branded"?"branded":"non-brand";a({to:".",search:x=>z(x,{queryClass:l})})},className:"h-11 rounded-md border border-default bg-surface px-3 text-sm text-primary focus:outline-none focus:ring-2 focus:ring-mono-400",children:[e.jsx("option",{value:"non-brand",children:u["non-brand"].technical}),e.jsx("option",{value:"branded",children:u.branded.technical})]})]}),e.jsx(es,{measuredAt:xe,unmeasuredReason:me,queryClass:h})]}),e.jsx(ns,{row:E,queryClass:h,isError:Y}),e.jsx(is,{project:d,targetKey:c,queryClass:h}),e.jsx(os,{questions:pe,queryClass:h}),e.jsx(ls,{urls:je}),e.jsx(ss,{project:d,groups:ye}),e.jsxs("section",{"aria-labelledby":"property-evidence",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-evidence",className:"text-base font-semibold text-heading",children:["Answers the engines gave",e.jsx(P,{text:"One row per answer an engine gave for the queries assigned to this Property in the displayed measurement. Mentioned and cited are independent: an answer can name this Property without linking it, or link it without naming it. Answers that did neither are listed first, because those are what a gap is made of. Where the answer text was not stored the mention reads Not measured, never a zero. Open a row to read what the engine actually said, followed by the source URLs it returned, this Property's own first. The answer is where a miss becomes actionable: a query this Property was not named in may still have named a sibling building."})]})}),N.length>0?e.jsxs("p",{className:"supporting-copy",children:[N.length," of ",X]}):null]}),Y?e.jsxs("p",{className:"text-sm text-secondary",children:["Evidence for ",u[h].technical.toLocaleLowerCase()," is unavailable. Retry that query type above."]}):m.isPending&&N.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading evidence…"}):m.isError&&N.length===0?e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsx("span",{role:"alert",children:"Evidence could not be loaded."}),e.jsx(g,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{m.refetch()},children:"Retry evidence"})]}):ge==="not_measured"?e.jsx("p",{className:"text-sm text-secondary",children:ne()?ae:"Not measured yet. Run a measurement to collect the answers for this Property."}):be?e.jsx("p",{role:"alert",className:"text-sm text-caution",children:"This measurement was returned in an older format, so the answers cannot be shown here. The numbers above are unaffected."}):N.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No answers matched this Property in the displayed measurement."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"property-answer-table-container overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table property-evidence-table",children:[e.jsx("caption",{className:"sr-only",children:"Answers measured for this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"}),e.jsx("th",{children:"Sources"}),e.jsx("th",{children:e.jsx("span",{className:"sr-only",children:"Sources detail"})})]})}),e.jsx("tbody",{children:N.map(n=>{const l=We(n),x=j.has(l),te=`property-answer-${encodeURIComponent(l)}`;return e.jsxs(b.Fragment,{children:[e.jsxs("tr",{className:"property-answer-summary",children:[e.jsxs("td",{className:"text-secondary",children:[e.jsx("h3",{className:"text-sm font-medium text-heading",children:n.queryText}),e.jsx("span",{className:"mt-1 block text-xs text-muted",children:[n.provider,n.location].filter(Boolean).join(" · ")}),n.historical||n.bridged?e.jsx("span",{className:"mt-1 flex",children:e.jsx(w,{tone:"caution",children:"Historical"})}):null]}),e.jsxs("td",{children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:"Mentioned"}),e.jsx(Ge,{row:n})]}),e.jsxs("td",{children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:"Cited"}),e.jsx(Ye,{row:n})]}),e.jsxs("td",{className:"tabular-nums text-secondary",children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:he}),n.cited===null?Ze:n.sources.length]}),e.jsx("td",{className:"text-right",children:e.jsx(g,{type:"button",size:"sm",variant:"ghost",className:"h-auto min-h-11 max-w-full whitespace-normal py-2 text-left md:h-auto","aria-expanded":x,"aria-label":x?`Hide the answer for ${n.queryText}`:`Read the answer for ${n.queryText}`,"aria-controls":x?te:void 0,onClick:()=>o(fe=>{const K=new Set(fe);return K.delete(l)||K.add(l),K}),children:x?"Hide answer":"Read answer"})})]}),x?e.jsx("tr",{className:"property-answer-detail",children:e.jsxs("td",{id:te,colSpan:5,className:"bg-surface-subtle px-4",children:[e.jsx(Xe,{project:d,targetKey:c,row:n}),e.jsx(Je,{row:n})]})}):null]},l)})})]})}),m.hasNextPage?e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{children:["Showing ",N.length," of ",X]}),m.isFetchNextPageError?e.jsx("span",{role:"alert",children:"Could not load more evidence."}):null,e.jsx(g,{size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",disabled:m.isFetchingNextPage,onClick:()=>{m.fetchNextPage()},children:m.isFetchingNextPage?"Loading…":m.isFetchNextPageError?"Retry more evidence":`Show ${re} more`})]}):null]})]})]})}export{oe as EVIDENCE_LABELS,vs as MeasurementPropertyPage};