@gscdump/contracts 1.1.0 → 1.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/dist/v1/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { accountNextActions, accountStatuses, analyticsNextActions, analyticsStatuses, builderStateSchema, gscComparisonFilterSchema, gscdumpAnalysisBundleResponseSchema, gscdumpAnalysisPresetSchema, gscdumpAnalysisResponseSchema, gscdumpAvailableSiteSchema, gscdumpCanonicalMismatchesResponseSchema, gscdumpDataDetailResponseSchema, gscdumpDataResponseSchema, gscdumpIndexingDiagnosticsResponseSchema, gscdumpIndexingResponseSchema, gscdumpKeywordSparklinesResponseSchema, gscdumpPageTrendResponseSchema, gscdumpQueryTrendResponseSchema, gscdumpSiteRegistrationSchema, gscdumpSitemapChangesResponseSchema, gscdumpSitemapsResponseSchema, gscdumpUserRegistrationSchema, indexingNextActions, indexingStatuses, indexingUrlsResponseSchema, lifecycleErrorCodes, propertyNextActions, propertyStatuses, querySourceModes, registerPartnerSiteSchema, registerPartnerUserSchema, searchTypeSchema, sitemapNextActions, sitemapStatuses, updatePartnerUserTokensSchema } from "../_chunks/schemas.mjs";
1
+ import { accountNextActions, accountStatuses, analyticsNextActions, analyticsStatuses, builderStateSchema, gscComparisonFilterSchema, gscdumpAnalysisBundleResponseSchema, gscdumpAnalysisPresetSchema, gscdumpAnalysisResponseSchema, gscdumpAvailableSiteSchema, gscdumpCanonicalMismatchesResponseSchema, gscdumpDataDetailResponseSchema, gscdumpDataResponseSchema, gscdumpIndexPercentResponseSchema, gscdumpIndexingDiagnosticsResponseSchema, gscdumpIndexingResponseSchema, gscdumpKeywordSparklinesResponseSchema, gscdumpPageTrendResponseSchema, gscdumpQueryTrendResponseSchema, gscdumpSiteRegistrationSchema, gscdumpSitemapChangesResponseSchema, gscdumpSitemapsResponseSchema, gscdumpTopAssociationResponseSchema, gscdumpUserRegistrationSchema, indexingNextActions, indexingStatuses, indexingUrlsResponseSchema, lifecycleErrorCodes, propertyNextActions, propertyStatuses, querySourceModes, registerPartnerSiteSchema, registerPartnerUserSchema, searchTypeSchema, sitemapNextActions, sitemapStatuses, updatePartnerUserTokensSchema } from "../_chunks/schemas.mjs";
2
2
  import { z } from "zod";
3
3
  const HTTP_V1_SURFACES = [
4
4
  "partner",
@@ -1050,6 +1050,150 @@ function createGscdumpV1Protocol() {
1050
1050
  reason: z.enum(["domain_mismatch", "rate_limited"])
1051
1051
  }))
1052
1052
  }), partnerResponseMeta);
1053
+ const dateRangeQuery = z.strictObject({
1054
+ startDate: calendarDate,
1055
+ endDate: calendarDate
1056
+ });
1057
+ const siteDataMeta = z.object({
1058
+ siteUrl: z.string().nullable(),
1059
+ syncStatus: z.string().nullable()
1060
+ });
1061
+ const contentVelocityResponse = defineSuccessResponse(defineResponseObject({
1062
+ weekly: z.array(z.strictObject({
1063
+ week: z.string(),
1064
+ newKeywords: z.number().int().nonnegative(),
1065
+ totalKeywords: z.number().int().nonnegative()
1066
+ })),
1067
+ summary: z.strictObject({
1068
+ totalNewKeywords: z.number().int().nonnegative(),
1069
+ avgPerWeek: z.number().nonnegative(),
1070
+ trend: z.enum([
1071
+ "stable",
1072
+ "accelerating",
1073
+ "decelerating"
1074
+ ])
1075
+ }),
1076
+ meta: siteDataMeta
1077
+ }), partnerResponseMeta);
1078
+ const ctrOutlier = z.strictObject({
1079
+ query: z.string(),
1080
+ clicks: z.number(),
1081
+ impressions: z.number(),
1082
+ ctr: z.number(),
1083
+ position: z.number(),
1084
+ expectedCtr: z.number(),
1085
+ ctrDiff: z.number()
1086
+ });
1087
+ const ctrCurveResponse = defineSuccessResponse(defineResponseObject({
1088
+ curve: z.array(z.strictObject({
1089
+ bucket: z.string(),
1090
+ avgCtr: z.number(),
1091
+ medianPosition: z.number(),
1092
+ keywordCount: z.number(),
1093
+ totalClicks: z.number(),
1094
+ totalImpressions: z.number()
1095
+ })),
1096
+ overperforming: z.array(ctrOutlier),
1097
+ underperforming: z.array(ctrOutlier),
1098
+ meta: siteDataMeta
1099
+ }), partnerResponseMeta);
1100
+ const darkTrafficResponse = defineSuccessResponse(defineResponseObject({
1101
+ summary: z.strictObject({
1102
+ totalClicks: z.number(),
1103
+ attributedClicks: z.number(),
1104
+ darkClicks: z.number(),
1105
+ darkPercent: z.number(),
1106
+ totalImpressions: z.number(),
1107
+ attributedImpressions: z.number()
1108
+ }),
1109
+ pages: z.array(z.strictObject({
1110
+ url: z.string(),
1111
+ totalClicks: z.number(),
1112
+ attributedClicks: z.number(),
1113
+ darkClicks: z.number(),
1114
+ darkPercent: z.number(),
1115
+ keywordCount: z.number()
1116
+ })),
1117
+ meta: siteDataMeta
1118
+ }), partnerResponseMeta);
1119
+ const deviceGapMetrics = z.strictObject({
1120
+ clicks: z.number(),
1121
+ impressions: z.number(),
1122
+ ctr: z.number(),
1123
+ position: z.number()
1124
+ });
1125
+ const deviceGapResponse = defineSuccessResponse(defineResponseObject({
1126
+ daily: z.array(z.strictObject({
1127
+ date: z.string(),
1128
+ desktop: deviceGapMetrics,
1129
+ mobile: deviceGapMetrics,
1130
+ gaps: z.strictObject({
1131
+ ctrGap: z.number(),
1132
+ positionGap: z.number()
1133
+ })
1134
+ })),
1135
+ summary: z.strictObject({
1136
+ avgCtrGap: z.number(),
1137
+ avgPositionGap: z.number(),
1138
+ ctrGapTrend: z.enum([
1139
+ "stable",
1140
+ "improving",
1141
+ "worsening"
1142
+ ]),
1143
+ positionGapTrend: z.enum([
1144
+ "stable",
1145
+ "improving",
1146
+ "worsening"
1147
+ ])
1148
+ }).nullable(),
1149
+ meta: siteDataMeta
1150
+ }), partnerResponseMeta);
1151
+ const keywordBreadthPage = z.strictObject({
1152
+ url: z.string(),
1153
+ keywordCount: z.number(),
1154
+ clicks: z.number(),
1155
+ impressions: z.number()
1156
+ });
1157
+ const keywordBreadthResponse = defineSuccessResponse(defineResponseObject({
1158
+ distribution: z.array(z.strictObject({
1159
+ bucket: z.string(),
1160
+ pageCount: z.number()
1161
+ })),
1162
+ fragilePages: z.array(keywordBreadthPage),
1163
+ authorityPages: z.array(keywordBreadthPage),
1164
+ summary: z.strictObject({
1165
+ totalPages: z.number(),
1166
+ avgKeywordsPerPage: z.number(),
1167
+ fragileCount: z.number(),
1168
+ authorityCount: z.number()
1169
+ }),
1170
+ meta: siteDataMeta
1171
+ }), partnerResponseMeta);
1172
+ const positionDistributionResponse = defineSuccessResponse(defineResponseObject({
1173
+ distribution: z.array(z.strictObject({
1174
+ date: z.string(),
1175
+ pos_1_3: z.number(),
1176
+ pos_4_10: z.number(),
1177
+ pos_11_20: z.number(),
1178
+ pos_20_plus: z.number(),
1179
+ total: z.number()
1180
+ })),
1181
+ meta: siteDataMeta
1182
+ }), partnerResponseMeta);
1183
+ const topAssociationQuery = z.strictObject({
1184
+ type: z.enum(["topPage", "topKeyword"]),
1185
+ identifier: z.string().min(1),
1186
+ startDate: calendarDate,
1187
+ endDate: calendarDate
1188
+ });
1189
+ const topAssociationResponse = defineSuccessResponse(defineResponseObject(gscdumpTopAssociationResponseSchema.shape), partnerResponseMeta);
1190
+ const indexPercentQuery = z.strictObject({
1191
+ invisibleLimit: z.coerce.number().int().min(1).max(500).optional(),
1192
+ invisibleOffset: z.coerce.number().int().min(0).max(1e6).optional(),
1193
+ orphanLimit: z.coerce.number().int().min(1).max(500).optional()
1194
+ });
1195
+ const indexPercentResponse = defineSuccessResponse(defineResponseObject(gscdumpIndexPercentResponseSchema.shape), partnerResponseMeta);
1196
+ const contentVelocityQuery = z.strictObject({ days: z.coerce.number().int().min(1).max(365).optional() });
1053
1197
  const responseStreamHead = defineResponseObject({
1054
1198
  streamId: realtimeSchemas.streamId,
1055
1199
  sequence: realtimeSchemas.sequence
@@ -2447,6 +2591,589 @@ function createGscdumpV1Protocol() {
2447
2591
  }
2448
2592
  }
2449
2593
  }
2594
+ }),
2595
+ getContentVelocity: defineHttpOperation({
2596
+ id: "partner.sites.content.velocity.get",
2597
+ method: "GET",
2598
+ path: "/sites/{siteId}/content-velocity",
2599
+ visibility: "public",
2600
+ semantics: {
2601
+ kind: "query",
2602
+ sideEffects: "none",
2603
+ idempotent: true,
2604
+ retry: "idempotent",
2605
+ readConsistency: "primary"
2606
+ },
2607
+ auth: {
2608
+ credentials: ["user_key", "partner_key"],
2609
+ scopes: ["analytics:read"],
2610
+ ownership: [{
2611
+ credential: "user_key",
2612
+ rule: "authorized_site"
2613
+ }, {
2614
+ credential: "partner_key",
2615
+ rule: "authorized_site"
2616
+ }]
2617
+ },
2618
+ request: {
2619
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2620
+ query: contentVelocityQuery,
2621
+ headers: requestHeaders,
2622
+ body: null
2623
+ },
2624
+ responses: { 200: contentVelocityResponse },
2625
+ errors: partnerSiteErrors,
2626
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2627
+ resources: {
2628
+ reads: [{
2629
+ type: "site.analytics",
2630
+ idFrom: "params.siteId"
2631
+ }],
2632
+ changes: []
2633
+ },
2634
+ lifecycle: { introduced: "1.2.0" },
2635
+ docs: {
2636
+ summary: "Get content velocity",
2637
+ description: "Returns the weekly new-keyword series over the requested window with a summary trend.",
2638
+ tags: ["Analytics"],
2639
+ examples: {
2640
+ request: {
2641
+ params: { siteId: "s_01" },
2642
+ query: { days: 90 }
2643
+ },
2644
+ response: {
2645
+ data: {
2646
+ weekly: [],
2647
+ summary: {
2648
+ totalNewKeywords: 0,
2649
+ avgPerWeek: 0,
2650
+ trend: "stable"
2651
+ },
2652
+ meta: {
2653
+ siteUrl: "sc-domain:example.com",
2654
+ syncStatus: "synced"
2655
+ }
2656
+ },
2657
+ meta: {
2658
+ requestId: "req_01",
2659
+ surface: "partner",
2660
+ version: "1.0"
2661
+ }
2662
+ }
2663
+ }
2664
+ }
2665
+ }),
2666
+ getCtrCurve: defineHttpOperation({
2667
+ id: "partner.sites.ctr.curve.get",
2668
+ method: "GET",
2669
+ path: "/sites/{siteId}/ctr-curve",
2670
+ visibility: "public",
2671
+ semantics: {
2672
+ kind: "query",
2673
+ sideEffects: "none",
2674
+ idempotent: true,
2675
+ retry: "idempotent",
2676
+ readConsistency: "primary"
2677
+ },
2678
+ auth: {
2679
+ credentials: ["user_key", "partner_key"],
2680
+ scopes: ["analytics:read"],
2681
+ ownership: [{
2682
+ credential: "user_key",
2683
+ rule: "authorized_site"
2684
+ }, {
2685
+ credential: "partner_key",
2686
+ rule: "authorized_site"
2687
+ }]
2688
+ },
2689
+ request: {
2690
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2691
+ query: dateRangeQuery,
2692
+ headers: requestHeaders,
2693
+ body: null
2694
+ },
2695
+ responses: { 200: ctrCurveResponse },
2696
+ errors: partnerSiteErrors,
2697
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2698
+ resources: {
2699
+ reads: [{
2700
+ type: "site.analytics",
2701
+ idFrom: "params.siteId"
2702
+ }],
2703
+ changes: []
2704
+ },
2705
+ lifecycle: { introduced: "1.2.0" },
2706
+ docs: {
2707
+ summary: "Get CTR curve and outliers",
2708
+ description: "Returns the position-bucketed CTR curve plus over/under-performing query outliers for the window.",
2709
+ tags: ["Analytics"],
2710
+ examples: {
2711
+ request: {
2712
+ params: { siteId: "s_01" },
2713
+ query: {
2714
+ startDate: "2026-06-01",
2715
+ endDate: "2026-06-28"
2716
+ }
2717
+ },
2718
+ response: {
2719
+ data: {
2720
+ curve: [],
2721
+ overperforming: [],
2722
+ underperforming: [],
2723
+ meta: {
2724
+ siteUrl: "sc-domain:example.com",
2725
+ syncStatus: "synced"
2726
+ }
2727
+ },
2728
+ meta: {
2729
+ requestId: "req_01",
2730
+ surface: "partner",
2731
+ version: "1.0"
2732
+ }
2733
+ }
2734
+ }
2735
+ }
2736
+ }),
2737
+ getDarkTraffic: defineHttpOperation({
2738
+ id: "partner.sites.dark.traffic.get",
2739
+ method: "GET",
2740
+ path: "/sites/{siteId}/dark-traffic",
2741
+ visibility: "public",
2742
+ semantics: {
2743
+ kind: "query",
2744
+ sideEffects: "none",
2745
+ idempotent: true,
2746
+ retry: "idempotent",
2747
+ readConsistency: "primary"
2748
+ },
2749
+ auth: {
2750
+ credentials: ["user_key", "partner_key"],
2751
+ scopes: ["analytics:read"],
2752
+ ownership: [{
2753
+ credential: "user_key",
2754
+ rule: "authorized_site"
2755
+ }, {
2756
+ credential: "partner_key",
2757
+ rule: "authorized_site"
2758
+ }]
2759
+ },
2760
+ request: {
2761
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2762
+ query: dateRangeQuery,
2763
+ headers: requestHeaders,
2764
+ body: null
2765
+ },
2766
+ responses: { 200: darkTrafficResponse },
2767
+ errors: partnerSiteErrors,
2768
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2769
+ resources: {
2770
+ reads: [{
2771
+ type: "site.analytics",
2772
+ idFrom: "params.siteId"
2773
+ }],
2774
+ changes: []
2775
+ },
2776
+ lifecycle: { introduced: "1.2.0" },
2777
+ docs: {
2778
+ summary: "Get dark traffic breakdown",
2779
+ description: "Returns clicks not attributable to any tracked keyword, in total and per page, for the window.",
2780
+ tags: ["Analytics"],
2781
+ examples: {
2782
+ request: {
2783
+ params: { siteId: "s_01" },
2784
+ query: {
2785
+ startDate: "2026-06-01",
2786
+ endDate: "2026-06-28"
2787
+ }
2788
+ },
2789
+ response: {
2790
+ data: {
2791
+ summary: {
2792
+ totalClicks: 0,
2793
+ attributedClicks: 0,
2794
+ darkClicks: 0,
2795
+ darkPercent: 0,
2796
+ totalImpressions: 0,
2797
+ attributedImpressions: 0
2798
+ },
2799
+ pages: [],
2800
+ meta: {
2801
+ siteUrl: "sc-domain:example.com",
2802
+ syncStatus: "synced"
2803
+ }
2804
+ },
2805
+ meta: {
2806
+ requestId: "req_01",
2807
+ surface: "partner",
2808
+ version: "1.0"
2809
+ }
2810
+ }
2811
+ }
2812
+ }
2813
+ }),
2814
+ getDeviceGap: defineHttpOperation({
2815
+ id: "partner.sites.device.gap.get",
2816
+ method: "GET",
2817
+ path: "/sites/{siteId}/device-gap",
2818
+ visibility: "public",
2819
+ semantics: {
2820
+ kind: "query",
2821
+ sideEffects: "none",
2822
+ idempotent: true,
2823
+ retry: "idempotent",
2824
+ readConsistency: "primary"
2825
+ },
2826
+ auth: {
2827
+ credentials: ["user_key", "partner_key"],
2828
+ scopes: ["analytics:read"],
2829
+ ownership: [{
2830
+ credential: "user_key",
2831
+ rule: "authorized_site"
2832
+ }, {
2833
+ credential: "partner_key",
2834
+ rule: "authorized_site"
2835
+ }]
2836
+ },
2837
+ request: {
2838
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2839
+ query: dateRangeQuery,
2840
+ headers: requestHeaders,
2841
+ body: null
2842
+ },
2843
+ responses: { 200: deviceGapResponse },
2844
+ errors: partnerSiteErrors,
2845
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2846
+ resources: {
2847
+ reads: [{
2848
+ type: "site.analytics",
2849
+ idFrom: "params.siteId"
2850
+ }],
2851
+ changes: []
2852
+ },
2853
+ lifecycle: { introduced: "1.2.0" },
2854
+ docs: {
2855
+ summary: "Get desktop/mobile gap",
2856
+ description: "Returns per-day desktop vs mobile CTR/position metrics with gap trends for the window.",
2857
+ tags: ["Analytics"],
2858
+ examples: {
2859
+ request: {
2860
+ params: { siteId: "s_01" },
2861
+ query: {
2862
+ startDate: "2026-06-01",
2863
+ endDate: "2026-06-28"
2864
+ }
2865
+ },
2866
+ response: {
2867
+ data: {
2868
+ daily: [],
2869
+ summary: null,
2870
+ meta: {
2871
+ siteUrl: "sc-domain:example.com",
2872
+ syncStatus: "synced"
2873
+ }
2874
+ },
2875
+ meta: {
2876
+ requestId: "req_01",
2877
+ surface: "partner",
2878
+ version: "1.0"
2879
+ }
2880
+ }
2881
+ }
2882
+ }
2883
+ }),
2884
+ getKeywordBreadth: defineHttpOperation({
2885
+ id: "partner.sites.keyword.breadth.get",
2886
+ method: "GET",
2887
+ path: "/sites/{siteId}/keyword-breadth",
2888
+ visibility: "public",
2889
+ semantics: {
2890
+ kind: "query",
2891
+ sideEffects: "none",
2892
+ idempotent: true,
2893
+ retry: "idempotent",
2894
+ readConsistency: "primary"
2895
+ },
2896
+ auth: {
2897
+ credentials: ["user_key", "partner_key"],
2898
+ scopes: ["analytics:read"],
2899
+ ownership: [{
2900
+ credential: "user_key",
2901
+ rule: "authorized_site"
2902
+ }, {
2903
+ credential: "partner_key",
2904
+ rule: "authorized_site"
2905
+ }]
2906
+ },
2907
+ request: {
2908
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2909
+ query: dateRangeQuery,
2910
+ headers: requestHeaders,
2911
+ body: null
2912
+ },
2913
+ responses: { 200: keywordBreadthResponse },
2914
+ errors: partnerSiteErrors,
2915
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2916
+ resources: {
2917
+ reads: [{
2918
+ type: "site.analytics",
2919
+ idFrom: "params.siteId"
2920
+ }],
2921
+ changes: []
2922
+ },
2923
+ lifecycle: { introduced: "1.2.0" },
2924
+ docs: {
2925
+ summary: "Get keyword breadth",
2926
+ description: "Returns the pages-per-keyword-count distribution with fragile and authority page lists for the window.",
2927
+ tags: ["Analytics"],
2928
+ examples: {
2929
+ request: {
2930
+ params: { siteId: "s_01" },
2931
+ query: {
2932
+ startDate: "2026-06-01",
2933
+ endDate: "2026-06-28"
2934
+ }
2935
+ },
2936
+ response: {
2937
+ data: {
2938
+ distribution: [],
2939
+ fragilePages: [],
2940
+ authorityPages: [],
2941
+ summary: {
2942
+ totalPages: 0,
2943
+ avgKeywordsPerPage: 0,
2944
+ fragileCount: 0,
2945
+ authorityCount: 0
2946
+ },
2947
+ meta: {
2948
+ siteUrl: "sc-domain:example.com",
2949
+ syncStatus: "synced"
2950
+ }
2951
+ },
2952
+ meta: {
2953
+ requestId: "req_01",
2954
+ surface: "partner",
2955
+ version: "1.0"
2956
+ }
2957
+ }
2958
+ }
2959
+ }
2960
+ }),
2961
+ getPositionDistribution: defineHttpOperation({
2962
+ id: "partner.sites.position.distribution.get",
2963
+ method: "GET",
2964
+ path: "/sites/{siteId}/position-distribution",
2965
+ visibility: "public",
2966
+ semantics: {
2967
+ kind: "query",
2968
+ sideEffects: "none",
2969
+ idempotent: true,
2970
+ retry: "idempotent",
2971
+ readConsistency: "primary"
2972
+ },
2973
+ auth: {
2974
+ credentials: ["user_key", "partner_key"],
2975
+ scopes: ["analytics:read"],
2976
+ ownership: [{
2977
+ credential: "user_key",
2978
+ rule: "authorized_site"
2979
+ }, {
2980
+ credential: "partner_key",
2981
+ rule: "authorized_site"
2982
+ }]
2983
+ },
2984
+ request: {
2985
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2986
+ query: dateRangeQuery,
2987
+ headers: requestHeaders,
2988
+ body: null
2989
+ },
2990
+ responses: { 200: positionDistributionResponse },
2991
+ errors: partnerSiteErrors,
2992
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2993
+ resources: {
2994
+ reads: [{
2995
+ type: "site.analytics",
2996
+ idFrom: "params.siteId"
2997
+ }],
2998
+ changes: []
2999
+ },
3000
+ lifecycle: { introduced: "1.2.0" },
3001
+ docs: {
3002
+ summary: "Get position distribution",
3003
+ description: "Returns the per-day keyword counts bucketed by average position for the window.",
3004
+ tags: ["Analytics"],
3005
+ examples: {
3006
+ request: {
3007
+ params: { siteId: "s_01" },
3008
+ query: {
3009
+ startDate: "2026-06-01",
3010
+ endDate: "2026-06-28"
3011
+ }
3012
+ },
3013
+ response: {
3014
+ data: {
3015
+ distribution: [],
3016
+ meta: {
3017
+ siteUrl: "sc-domain:example.com",
3018
+ syncStatus: "synced"
3019
+ }
3020
+ },
3021
+ meta: {
3022
+ requestId: "req_01",
3023
+ surface: "partner",
3024
+ version: "1.0"
3025
+ }
3026
+ }
3027
+ }
3028
+ }
3029
+ }),
3030
+ getTopAssociation: defineHttpOperation({
3031
+ id: "partner.sites.top.association.get",
3032
+ method: "GET",
3033
+ path: "/sites/{siteId}/top-association",
3034
+ visibility: "public",
3035
+ semantics: {
3036
+ kind: "query",
3037
+ sideEffects: "none",
3038
+ idempotent: true,
3039
+ retry: "idempotent",
3040
+ readConsistency: "primary"
3041
+ },
3042
+ auth: {
3043
+ credentials: ["user_key", "partner_key"],
3044
+ scopes: ["analytics:read"],
3045
+ ownership: [{
3046
+ credential: "user_key",
3047
+ rule: "authorized_site"
3048
+ }, {
3049
+ credential: "partner_key",
3050
+ rule: "authorized_site"
3051
+ }]
3052
+ },
3053
+ request: {
3054
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3055
+ query: topAssociationQuery,
3056
+ headers: requestHeaders,
3057
+ body: null
3058
+ },
3059
+ responses: { 200: topAssociationResponse },
3060
+ errors: partnerSiteErrors,
3061
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
3062
+ resources: {
3063
+ reads: [{
3064
+ type: "site.analytics",
3065
+ idFrom: "params.siteId"
3066
+ }],
3067
+ changes: []
3068
+ },
3069
+ lifecycle: { introduced: "1.2.0" },
3070
+ docs: {
3071
+ summary: "Get top association",
3072
+ description: "Returns the single best-performing page for a keyword, or keyword for a page, over the window.",
3073
+ tags: ["Analytics"],
3074
+ examples: {
3075
+ request: {
3076
+ params: { siteId: "s_01" },
3077
+ query: {
3078
+ type: "topKeyword",
3079
+ identifier: "/docs",
3080
+ startDate: "2026-06-01",
3081
+ endDate: "2026-06-28"
3082
+ }
3083
+ },
3084
+ response: {
3085
+ data: { value: null },
3086
+ meta: {
3087
+ requestId: "req_01",
3088
+ surface: "partner",
3089
+ version: "1.0"
3090
+ }
3091
+ }
3092
+ }
3093
+ }
3094
+ }),
3095
+ getIndexPercent: defineHttpOperation({
3096
+ id: "partner.sites.index.percent.get",
3097
+ method: "GET",
3098
+ path: "/sites/{siteId}/index-percent",
3099
+ visibility: "public",
3100
+ semantics: {
3101
+ kind: "query",
3102
+ sideEffects: "none",
3103
+ idempotent: true,
3104
+ retry: "idempotent",
3105
+ readConsistency: "primary"
3106
+ },
3107
+ auth: {
3108
+ credentials: ["user_key", "partner_key"],
3109
+ scopes: ["indexing:read"],
3110
+ ownership: [{
3111
+ credential: "user_key",
3112
+ rule: "authorized_site"
3113
+ }, {
3114
+ credential: "partner_key",
3115
+ rule: "authorized_site"
3116
+ }]
3117
+ },
3118
+ request: {
3119
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3120
+ query: indexPercentQuery,
3121
+ headers: requestHeaders,
3122
+ body: null
3123
+ },
3124
+ responses: { 200: indexPercentResponse },
3125
+ errors: partnerSiteErrors,
3126
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
3127
+ resources: {
3128
+ reads: [{
3129
+ type: "site.indexing",
3130
+ idFrom: "params.siteId"
3131
+ }, {
3132
+ type: "site.sitemaps",
3133
+ idFrom: "params.siteId"
3134
+ }],
3135
+ changes: []
3136
+ },
3137
+ lifecycle: { introduced: "1.2.0" },
3138
+ docs: {
3139
+ summary: "Get sitemap index-percent",
3140
+ description: "Returns the sitemap visibility trend, invisible URLs, orphan pages, and per-sitemap counts.",
3141
+ tags: ["Indexing"],
3142
+ examples: {
3143
+ request: {
3144
+ params: { siteId: "s_01" },
3145
+ query: { invisibleLimit: 100 }
3146
+ },
3147
+ response: {
3148
+ data: {
3149
+ trend: [],
3150
+ invisibleUrls: [],
3151
+ invisibleCount: 0,
3152
+ orphanPages: [],
3153
+ orphanCount: 0,
3154
+ sitemaps: [],
3155
+ summary: {
3156
+ currentPercent: 0,
3157
+ totalSitemapUrls: 0,
3158
+ visibleUrls: 0,
3159
+ change7d: null,
3160
+ change28d: null,
3161
+ dataDate: "2026-06-28"
3162
+ },
3163
+ meta: {
3164
+ siteUrl: "sc-domain:example.com",
3165
+ syncStatus: "synced",
3166
+ newestDateSynced: null
3167
+ }
3168
+ },
3169
+ meta: {
3170
+ requestId: "req_01",
3171
+ surface: "partner",
3172
+ version: "1.0"
3173
+ }
3174
+ }
3175
+ }
3176
+ }
2450
3177
  })
2451
3178
  }
2452
3179
  });