diff --git a/src/server/features/keywords/services/research/serp.ts b/src/server/features/keywords/services/research/serp.ts index 7fde940..8eb404f 100644 --- a/src/server/features/keywords/services/research/serp.ts +++ b/src/server/features/keywords/services/research/serp.ts @@ -41,7 +41,7 @@ function mapOrganicSerpItems(items: SerpLiveItem[]): SerpResultItem[] { return items .filter((item) => item.type === "organic") .map((item) => ({ - rank: item.rank_absolute ?? item.rank_group ?? 0, + rank: item.rank_group ?? item.rank_absolute ?? 0, title: item.title ?? "", url: item.url ?? "", domain: item.domain ?? "", diff --git a/src/server/features/onboarding/onboardingMarketTools.ts b/src/server/features/onboarding/onboardingMarketTools.ts index 4a12c42..142458a 100644 --- a/src/server/features/onboarding/onboardingMarketTools.ts +++ b/src/server/features/onboarding/onboardingMarketTools.ts @@ -87,7 +87,7 @@ export function marketTools(ctx: ToolContext): ToolSet { .filter((item) => item.type === "organic") .slice(0, 10) .map((item) => ({ - rank: item.rank_absolute ?? item.rank_group ?? null, + rank: item.rank_group ?? item.rank_absolute ?? null, domain: item.domain ?? null, title: item.title ?? null, url: item.url ?? null, diff --git a/src/server/lib/dataforseo/serp.test.ts b/src/server/lib/dataforseo/serp.test.ts index 75130f3..f0073ce 100644 --- a/src/server/lib/dataforseo/serp.test.ts +++ b/src/server/lib/dataforseo/serp.test.ts @@ -168,7 +168,7 @@ describe("rank check task queue", () => { result: { keywordId: "kw-1", keyword: "alpha", - position: 4, + position: 3, url: "https://www.example.com/page", serpFeatures: ["organic"], }, diff --git a/src/server/lib/dataforseo/serp.ts b/src/server/lib/dataforseo/serp.ts index 9ed6908..6d9d787 100644 --- a/src/server/lib/dataforseo/serp.ts +++ b/src/server/lib/dataforseo/serp.ts @@ -129,8 +129,11 @@ function buildRankCheckResult( return { keywordId: input.keywordId, keyword: input.keyword, + // rank_group = position among organic results only (what users count as + // "my ranking"). rank_absolute would also count SERP features (local + // pack, PAA, AI overviews) and reads as worse than what users see. position: organicMatch - ? (organicMatch.rank_absolute ?? organicMatch.rank_group ?? null) + ? (organicMatch.rank_group ?? organicMatch.rank_absolute ?? null) : null, url: organicMatch?.url ?? null, serpFeatures: [...new Set(items.map((item) => item.type).filter(Boolean))],