You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@power-seo/analytics

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@power-seo/analytics - npm Package Compare versions

Comparing version
1.0.4
to
1.0.7
+21
LICENSE
MIT License
Copyright (c) 2026 CCBD SEO Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+45
-14

@@ -1,14 +0,44 @@

'use strict';
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var core = require('@power-seo/core');
// src/index.ts
var index_exports = {};
__export(index_exports, {
analyzeQueryRankings: () => analyzeQueryRankings,
analyzeTrend: () => analyzeTrend,
buildDashboardData: () => buildDashboardData,
buildTrendLines: () => buildTrendLines,
correlateScoreAndTraffic: () => correlateScoreAndTraffic,
detectAnomalies: () => detectAnomalies,
mergeGscWithAudit: () => mergeGscWithAudit,
trackPositionChanges: () => trackPositionChanges
});
module.exports = __toCommonJS(index_exports);
// src/merge.ts
var import_core = require("@power-seo/core");
function mergeGscWithAudit(gscData, auditResults) {
const auditMap = /* @__PURE__ */ new Map();
for (const result of auditResults) {
auditMap.set(core.normalizeUrl(result.url), result);
auditMap.set((0, import_core.normalizeUrl)(result.url), result);
}
const gscMap = /* @__PURE__ */ new Map();
for (const page of gscData) {
gscMap.set(core.normalizeUrl(page.url), page);
gscMap.set((0, import_core.normalizeUrl)(page.url), page);
}

@@ -243,12 +273,13 @@ const allUrls = /* @__PURE__ */ new Set([...auditMap.keys(), ...gscMap.keys()]);

}
exports.analyzeQueryRankings = analyzeQueryRankings;
exports.analyzeTrend = analyzeTrend;
exports.buildDashboardData = buildDashboardData;
exports.buildTrendLines = buildTrendLines;
exports.correlateScoreAndTraffic = correlateScoreAndTraffic;
exports.detectAnomalies = detectAnomalies;
exports.mergeGscWithAudit = mergeGscWithAudit;
exports.trackPositionChanges = trackPositionChanges;
//# sourceMappingURL=index.cjs.map
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
analyzeQueryRankings,
analyzeTrend,
buildDashboardData,
buildTrendLines,
correlateScoreAndTraffic,
detectAnomalies,
mergeGscWithAudit,
trackPositionChanges
});
//# sourceMappingURL=index.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/merge.ts","../src/trends.ts","../src/rankings.ts","../src/dashboard.ts"],"names":["normalizeUrl"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/analytics — Merge GSC + Audit Data\n// ============================================================================\n\nimport { normalizeUrl } from '@power-seo/core';\nimport type { GscPageData, PageInsight, AuditCategory, CategoryResult } from './types.js';\n\ninterface AuditData {\n url: string;\n score: number;\n categories: Record<AuditCategory, CategoryResult>;\n recommendations: string[];\n}\n\nexport function mergeGscWithAudit(\n gscData: GscPageData[],\n auditResults: AuditData[],\n): PageInsight[] {\n const auditMap = new Map<string, AuditData>();\n for (const result of auditResults) {\n auditMap.set(normalizeUrl(result.url), result);\n }\n\n const gscMap = new Map<string, GscPageData>();\n for (const page of gscData) {\n gscMap.set(normalizeUrl(page.url), page);\n }\n\n const allUrls = new Set([...auditMap.keys(), ...gscMap.keys()]);\n const insights: PageInsight[] = [];\n\n for (const url of allUrls) {\n const gsc = gscMap.get(url);\n const audit = auditMap.get(url);\n const opportunities: string[] = [];\n\n if (gsc && audit) {\n if (gsc.clicks > 50 && audit.score < 70) {\n opportunities.push(\n `High-traffic page (${gsc.clicks} clicks) with low audit score (${audit.score}). Fixing issues could significantly boost organic performance.`,\n );\n }\n if (gsc.position > 10 && gsc.impressions > 100) {\n opportunities.push(\n `Page has ${gsc.impressions} impressions at position ${gsc.position.toFixed(1)}. Improving to page 1 could unlock significant traffic.`,\n );\n }\n if (audit.recommendations.length > 0) {\n opportunities.push(...audit.recommendations.slice(0, 3));\n }\n } else if (gsc && !audit) {\n opportunities.push(\n 'Page receives search traffic but has not been audited. Run an audit to identify improvement opportunities.',\n );\n } else if (!gsc && audit) {\n if (audit.score < 50) {\n opportunities.push(\n `Page has a low audit score (${audit.score}) and no search traffic. Consider improving or removing the page.`,\n );\n }\n }\n\n insights.push({\n url,\n gscMetrics: gsc\n ? { clicks: gsc.clicks, impressions: gsc.impressions, ctr: gsc.ctr, position: gsc.position }\n : undefined,\n auditScore: audit?.score,\n auditCategories: audit?.categories,\n opportunities,\n });\n }\n\n return insights;\n}\n\nexport function correlateScoreAndTraffic(insights: PageInsight[]): {\n correlation: number;\n topOpportunities: PageInsight[];\n} {\n const paired = insights.filter((i) => i.gscMetrics && i.auditScore !== undefined);\n\n if (paired.length < 2) {\n return { correlation: 0, topOpportunities: [] };\n }\n\n const scores = paired.map((i) => i.auditScore!);\n const clicks = paired.map((i) => i.gscMetrics!.clicks);\n\n const n = scores.length;\n const meanScore = scores.reduce((a, b) => a + b, 0) / n;\n const meanClicks = clicks.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denomScore = 0;\n let denomClicks = 0;\n\n for (let i = 0; i < n; i++) {\n const diffScore = (scores[i] ?? 0) - meanScore;\n const diffClicks = (clicks[i] ?? 0) - meanClicks;\n numerator += diffScore * diffClicks;\n denomScore += diffScore * diffScore;\n denomClicks += diffClicks * diffClicks;\n }\n\n const denominator = Math.sqrt(denomScore * denomClicks);\n const correlation = denominator === 0 ? 0 : numerator / denominator;\n\n // Top opportunities: high traffic, low score\n const topOpportunities = [...paired]\n .filter((i) => i.gscMetrics!.clicks > 0)\n .sort((a, b) => {\n const scoreA = a.gscMetrics!.clicks / (a.auditScore! || 1);\n const scoreB = b.gscMetrics!.clicks / (b.auditScore! || 1);\n return scoreB - scoreA;\n })\n .slice(0, 10);\n\n return { correlation: Math.round(correlation * 1000) / 1000, topOpportunities };\n}\n","// ============================================================================\n// @power-seo/analytics — Trend Analysis\n// ============================================================================\n\nimport type { TrendPoint, TrendDirection, TrendAnalysis, AuditSnapshot } from './types.js';\n\nexport function analyzeTrend(points: TrendPoint[], metric = 'value'): TrendAnalysis {\n if (points.length === 0) {\n return { metric, trend: 'stable', change: 0, points: [] };\n }\n\n if (points.length === 1) {\n return { metric, trend: 'stable', change: 0, points };\n }\n\n // Linear regression for slope\n const n = points.length;\n const xs = points.map((_, i) => i);\n const ys = points.map((p) => p.value);\n\n const meanX = xs.reduce((a, b) => a + b, 0) / n;\n const meanY = ys.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denominator = 0;\n for (let i = 0; i < n; i++) {\n const xi = xs[i] ?? 0;\n const yi = ys[i] ?? 0;\n numerator += (xi - meanX) * (yi - meanY);\n denominator += (xi - meanX) * (xi - meanX);\n }\n\n const slope = denominator === 0 ? 0 : numerator / denominator;\n\n // Percentage change first→last\n const first = points[0]!.value;\n const last = points[points.length - 1]!.value;\n const change = first === 0 ? 0 : Math.round(((last - first) / Math.abs(first)) * 10000) / 100;\n\n // Classify trend based on slope relative to mean\n const threshold = Math.abs(meanY) * 0.02; // 2% of mean\n let trend: TrendDirection;\n if (slope > threshold) {\n trend = 'improving';\n } else if (slope < -threshold) {\n trend = 'declining';\n } else {\n trend = 'stable';\n }\n\n return { metric, trend, change, points };\n}\n\nexport function buildTrendLines(snapshots: AuditSnapshot[]): Record<string, TrendAnalysis> {\n if (snapshots.length === 0) {\n return {};\n }\n\n // Sort by date\n const sorted = [...snapshots].sort((a, b) => a.date.localeCompare(b.date));\n\n // Overall score trend\n const overallPoints: TrendPoint[] = sorted.map((s) => ({ date: s.date, value: s.score }));\n const result: Record<string, TrendAnalysis> = {\n overall: analyzeTrend(overallPoints, 'overall'),\n };\n\n // Per-category trends\n const categories = Object.keys(sorted[0]!.categories) as Array<\n keyof (typeof sorted)[0]['categories']\n >;\n for (const category of categories) {\n const categoryPoints: TrendPoint[] = sorted.map((s) => ({\n date: s.date,\n value: s.categories[category],\n }));\n result[category] = analyzeTrend(categoryPoints, category);\n }\n\n return result;\n}\n\nexport function detectAnomalies(points: TrendPoint[], threshold = 2): TrendPoint[] {\n if (points.length < 3) {\n return [];\n }\n\n const values = points.map((p) => p.value);\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / values.length;\n const stdDev = Math.sqrt(variance);\n\n if (stdDev === 0) {\n return [];\n }\n\n return points.filter((p) => Math.abs(p.value - mean) > threshold * stdDev);\n}\n","// ============================================================================\n// @power-seo/analytics — Query Ranking Analysis\n// ============================================================================\n\nimport type { GscQueryData, RankingAnalysis, RankingBucket, PositionChange } from './types.js';\n\nconst BUCKET_RANGES = [\n { range: '1-3', min: 1, max: 3 },\n { range: '4-10', min: 4, max: 10 },\n { range: '11-20', min: 11, max: 20 },\n { range: '21-100', min: 21, max: 100 },\n];\n\nexport function analyzeQueryRankings(queries: GscQueryData[]): RankingAnalysis {\n if (queries.length === 0) {\n return {\n totalQueries: 0,\n buckets: BUCKET_RANGES.map((r) => ({ range: r.range, count: 0, queries: [] })),\n strikingDistance: [],\n };\n }\n\n const buckets: RankingBucket[] = BUCKET_RANGES.map((range) => {\n const matching = queries.filter((q) => q.position >= range.min && q.position <= range.max);\n return {\n range: range.range,\n count: matching.length,\n queries: matching,\n };\n });\n\n // Striking distance: position 4-20, sorted by impressions descending\n const strikingDistance = queries\n .filter((q) => q.position >= 4 && q.position <= 20)\n .sort((a, b) => b.impressions - a.impressions);\n\n return {\n totalQueries: queries.length,\n buckets,\n strikingDistance,\n };\n}\n\nexport function trackPositionChanges(\n current: GscQueryData[],\n previous: GscQueryData[],\n): PositionChange[] {\n if (current.length === 0 && previous.length === 0) {\n return [];\n }\n\n const prevMap = new Map<string, GscQueryData>();\n for (const q of previous) {\n prevMap.set(q.query, q);\n }\n\n const changes: PositionChange[] = [];\n\n for (const curr of current) {\n const prev = prevMap.get(curr.query);\n if (prev) {\n changes.push({\n query: curr.query,\n previousPosition: prev.position,\n currentPosition: curr.position,\n change: prev.position - curr.position, // positive = improvement\n impressionChange: curr.impressions - prev.impressions,\n });\n }\n }\n\n return changes;\n}\n","// ============================================================================\n// @power-seo/analytics — Dashboard Data Builder\n// ============================================================================\n\nimport type { DashboardInput, DashboardData, DashboardOverview } from './types.js';\nimport { buildTrendLines } from './trends.js';\n\nexport function buildDashboardData(input: DashboardInput): DashboardData {\n const { gscPages = [], gscQueries = [], auditResults = [], auditHistory = [] } = input;\n\n // Overview metrics\n const totalClicks = gscPages.reduce((sum, p) => sum + p.clicks, 0);\n const totalImpressions = gscPages.reduce((sum, p) => sum + p.impressions, 0);\n const averageCtr =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.ctr, 0) / gscPages.length) * 10000) / 10000\n : 0;\n const averagePosition =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.position, 0) / gscPages.length) * 10) / 10\n : 0;\n const averageAuditScore =\n auditResults.length > 0\n ? Math.round(auditResults.reduce((sum, r) => sum + r.score, 0) / auditResults.length)\n : 0;\n const totalPages = Math.max(gscPages.length, auditResults.length);\n\n const overview: DashboardOverview = {\n totalClicks,\n totalImpressions,\n averageCtr,\n averagePosition,\n averageAuditScore,\n totalPages,\n };\n\n // Top pages by clicks\n const topPages = [...gscPages].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Top queries by clicks\n const topQueries = [...gscQueries].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Trend lines from audit history\n const trendLines = buildTrendLines(auditHistory);\n\n // Collect issues from audit results\n const issues: string[] = [];\n for (const result of auditResults) {\n issues.push(...result.recommendations);\n }\n // Deduplicate and limit\n const uniqueIssues = [...new Set(issues)].slice(0, 20);\n\n return {\n overview,\n topPages,\n topQueries,\n trendLines,\n issues: uniqueIssues,\n };\n}\n"]}
{"version":3,"sources":["../src/index.ts","../src/merge.ts","../src/trends.ts","../src/rankings.ts","../src/dashboard.ts"],"sourcesContent":["// @power-seo/analytics — Public API\n// ----------------------------------------------------------------------------\n\nexport { mergeGscWithAudit, correlateScoreAndTraffic } from './merge.js';\nexport { analyzeTrend, buildTrendLines, detectAnomalies } from './trends.js';\nexport { analyzeQueryRankings, trackPositionChanges } from './rankings.js';\nexport { buildDashboardData } from './dashboard.js';\n\nexport type {\n GscPageData,\n GscQueryData,\n AuditSnapshot,\n TrendPoint,\n TrendDirection,\n TrendAnalysis,\n PageInsight,\n RankingBucket,\n RankingAnalysis,\n PositionChange,\n DashboardInput,\n DashboardOverview,\n DashboardData,\n AuditCategory,\n CategoryResult,\n PageAuditResult,\n} from './types.js';\n","// @power-seo/analytics — Merge GSC + Audit Data\n// ----------------------------------------------------------------------------\n\nimport { normalizeUrl } from '@power-seo/core';\nimport type { GscPageData, PageInsight, AuditCategory, CategoryResult } from './types.js';\n\ninterface AuditData {\n url: string;\n score: number;\n categories: Record<AuditCategory, CategoryResult>;\n recommendations: string[];\n}\n\nexport function mergeGscWithAudit(\n gscData: GscPageData[],\n auditResults: AuditData[],\n): PageInsight[] {\n const auditMap = new Map<string, AuditData>();\n for (const result of auditResults) {\n auditMap.set(normalizeUrl(result.url), result);\n }\n\n const gscMap = new Map<string, GscPageData>();\n for (const page of gscData) {\n gscMap.set(normalizeUrl(page.url), page);\n }\n\n const allUrls = new Set([...auditMap.keys(), ...gscMap.keys()]);\n const insights: PageInsight[] = [];\n\n for (const url of allUrls) {\n const gsc = gscMap.get(url);\n const audit = auditMap.get(url);\n const opportunities: string[] = [];\n\n if (gsc && audit) {\n if (gsc.clicks > 50 && audit.score < 70) {\n opportunities.push(\n `High-traffic page (${gsc.clicks} clicks) with low audit score (${audit.score}). Fixing issues could significantly boost organic performance.`,\n );\n }\n if (gsc.position > 10 && gsc.impressions > 100) {\n opportunities.push(\n `Page has ${gsc.impressions} impressions at position ${gsc.position.toFixed(1)}. Improving to page 1 could unlock significant traffic.`,\n );\n }\n if (audit.recommendations.length > 0) {\n opportunities.push(...audit.recommendations.slice(0, 3));\n }\n } else if (gsc && !audit) {\n opportunities.push(\n 'Page receives search traffic but has not been audited. Run an audit to identify improvement opportunities.',\n );\n } else if (!gsc && audit) {\n if (audit.score < 50) {\n opportunities.push(\n `Page has a low audit score (${audit.score}) and no search traffic. Consider improving or removing the page.`,\n );\n }\n }\n\n insights.push({\n url,\n gscMetrics: gsc\n ? { clicks: gsc.clicks, impressions: gsc.impressions, ctr: gsc.ctr, position: gsc.position }\n : undefined,\n auditScore: audit?.score,\n auditCategories: audit?.categories,\n opportunities,\n });\n }\n\n return insights;\n}\n\nexport function correlateScoreAndTraffic(insights: PageInsight[]): {\n correlation: number;\n topOpportunities: PageInsight[];\n} {\n const paired = insights.filter((i) => i.gscMetrics && i.auditScore !== undefined);\n\n if (paired.length < 2) {\n return { correlation: 0, topOpportunities: [] };\n }\n\n const scores = paired.map((i) => i.auditScore!);\n const clicks = paired.map((i) => i.gscMetrics!.clicks);\n\n const n = scores.length;\n const meanScore = scores.reduce((a, b) => a + b, 0) / n;\n const meanClicks = clicks.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denomScore = 0;\n let denomClicks = 0;\n\n for (let i = 0; i < n; i++) {\n const diffScore = (scores[i] ?? 0) - meanScore;\n const diffClicks = (clicks[i] ?? 0) - meanClicks;\n numerator += diffScore * diffClicks;\n denomScore += diffScore * diffScore;\n denomClicks += diffClicks * diffClicks;\n }\n\n const denominator = Math.sqrt(denomScore * denomClicks);\n const correlation = denominator === 0 ? 0 : numerator / denominator;\n\n // Top opportunities: high traffic, low score\n const topOpportunities = [...paired]\n .filter((i) => i.gscMetrics!.clicks > 0)\n .sort((a, b) => {\n const scoreA = a.gscMetrics!.clicks / (a.auditScore! || 1);\n const scoreB = b.gscMetrics!.clicks / (b.auditScore! || 1);\n return scoreB - scoreA;\n })\n .slice(0, 10);\n\n return { correlation: Math.round(correlation * 1000) / 1000, topOpportunities };\n}\n","// @power-seo/analytics — Trend Analysis\n// ----------------------------------------------------------------------------\n\nimport type { TrendPoint, TrendDirection, TrendAnalysis, AuditSnapshot } from './types.js';\n\nexport function analyzeTrend(points: TrendPoint[], metric = 'value'): TrendAnalysis {\n if (points.length === 0) {\n return { metric, trend: 'stable', change: 0, points: [] };\n }\n\n if (points.length === 1) {\n return { metric, trend: 'stable', change: 0, points };\n }\n\n // Linear regression for slope\n const n = points.length;\n const xs = points.map((_, i) => i);\n const ys = points.map((p) => p.value);\n\n const meanX = xs.reduce((a, b) => a + b, 0) / n;\n const meanY = ys.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denominator = 0;\n for (let i = 0; i < n; i++) {\n const xi = xs[i] ?? 0;\n const yi = ys[i] ?? 0;\n numerator += (xi - meanX) * (yi - meanY);\n denominator += (xi - meanX) * (xi - meanX);\n }\n\n const slope = denominator === 0 ? 0 : numerator / denominator;\n\n // Percentage change first→last\n const first = points[0]!.value;\n const last = points[points.length - 1]!.value;\n const change = first === 0 ? 0 : Math.round(((last - first) / Math.abs(first)) * 10000) / 100;\n\n // Classify trend based on slope relative to mean\n const threshold = Math.abs(meanY) * 0.02; // 2% of mean\n let trend: TrendDirection;\n if (slope > threshold) {\n trend = 'improving';\n } else if (slope < -threshold) {\n trend = 'declining';\n } else {\n trend = 'stable';\n }\n\n return { metric, trend, change, points };\n}\n\nexport function buildTrendLines(snapshots: AuditSnapshot[]): Record<string, TrendAnalysis> {\n if (snapshots.length === 0) {\n return {};\n }\n\n // Sort by date\n const sorted = [...snapshots].sort((a, b) => a.date.localeCompare(b.date));\n\n // Overall score trend\n const overallPoints: TrendPoint[] = sorted.map((s) => ({ date: s.date, value: s.score }));\n const result: Record<string, TrendAnalysis> = {\n overall: analyzeTrend(overallPoints, 'overall'),\n };\n\n // Per-category trends\n const categories = Object.keys(sorted[0]!.categories) as Array<\n keyof (typeof sorted)[0]['categories']\n >;\n for (const category of categories) {\n const categoryPoints: TrendPoint[] = sorted.map((s) => ({\n date: s.date,\n value: s.categories[category],\n }));\n result[category] = analyzeTrend(categoryPoints, category);\n }\n\n return result;\n}\n\nexport function detectAnomalies(points: TrendPoint[], threshold = 2): TrendPoint[] {\n if (points.length < 3) {\n return [];\n }\n\n const values = points.map((p) => p.value);\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / values.length;\n const stdDev = Math.sqrt(variance);\n\n if (stdDev === 0) {\n return [];\n }\n\n return points.filter((p) => Math.abs(p.value - mean) > threshold * stdDev);\n}\n","// @power-seo/analytics — Query Ranking Analysis\n// ----------------------------------------------------------------------------\n\nimport type { GscQueryData, RankingAnalysis, RankingBucket, PositionChange } from './types.js';\n\nconst BUCKET_RANGES = [\n { range: '1-3', min: 1, max: 3 },\n { range: '4-10', min: 4, max: 10 },\n { range: '11-20', min: 11, max: 20 },\n { range: '21-100', min: 21, max: 100 },\n];\n\nexport function analyzeQueryRankings(queries: GscQueryData[]): RankingAnalysis {\n if (queries.length === 0) {\n return {\n totalQueries: 0,\n buckets: BUCKET_RANGES.map((r) => ({ range: r.range, count: 0, queries: [] })),\n strikingDistance: [],\n };\n }\n\n const buckets: RankingBucket[] = BUCKET_RANGES.map((range) => {\n const matching = queries.filter((q) => q.position >= range.min && q.position <= range.max);\n return {\n range: range.range,\n count: matching.length,\n queries: matching,\n };\n });\n\n // Striking distance: position 4-20, sorted by impressions descending\n const strikingDistance = queries\n .filter((q) => q.position >= 4 && q.position <= 20)\n .sort((a, b) => b.impressions - a.impressions);\n\n return {\n totalQueries: queries.length,\n buckets,\n strikingDistance,\n };\n}\n\nexport function trackPositionChanges(\n current: GscQueryData[],\n previous: GscQueryData[],\n): PositionChange[] {\n if (current.length === 0 && previous.length === 0) {\n return [];\n }\n\n const prevMap = new Map<string, GscQueryData>();\n for (const q of previous) {\n prevMap.set(q.query, q);\n }\n\n const changes: PositionChange[] = [];\n\n for (const curr of current) {\n const prev = prevMap.get(curr.query);\n if (prev) {\n changes.push({\n query: curr.query,\n previousPosition: prev.position,\n currentPosition: curr.position,\n change: prev.position - curr.position, // positive = improvement\n impressionChange: curr.impressions - prev.impressions,\n });\n }\n }\n\n return changes;\n}\n","// @power-seo/analytics — Dashboard Data Builder\n// ----------------------------------------------------------------------------\n\nimport type { DashboardInput, DashboardData, DashboardOverview } from './types.js';\nimport { buildTrendLines } from './trends.js';\n\nexport function buildDashboardData(input: DashboardInput): DashboardData {\n const { gscPages = [], gscQueries = [], auditResults = [], auditHistory = [] } = input;\n\n // Overview metrics\n const totalClicks = gscPages.reduce((sum, p) => sum + p.clicks, 0);\n const totalImpressions = gscPages.reduce((sum, p) => sum + p.impressions, 0);\n const averageCtr =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.ctr, 0) / gscPages.length) * 10000) / 10000\n : 0;\n const averagePosition =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.position, 0) / gscPages.length) * 10) / 10\n : 0;\n const averageAuditScore =\n auditResults.length > 0\n ? Math.round(auditResults.reduce((sum, r) => sum + r.score, 0) / auditResults.length)\n : 0;\n const totalPages = Math.max(gscPages.length, auditResults.length);\n\n const overview: DashboardOverview = {\n totalClicks,\n totalImpressions,\n averageCtr,\n averagePosition,\n averageAuditScore,\n totalPages,\n };\n\n // Top pages by clicks\n const topPages = [...gscPages].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Top queries by clicks\n const topQueries = [...gscQueries].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Trend lines from audit history\n const trendLines = buildTrendLines(auditHistory);\n\n // Collect issues from audit results\n const issues: string[] = [];\n for (const result of auditResults) {\n issues.push(...result.recommendations);\n }\n // Deduplicate and limit\n const uniqueIssues = [...new Set(issues)].slice(0, 20);\n\n return {\n overview,\n topPages,\n topQueries,\n trendLines,\n issues: uniqueIssues,\n };\n}\n"],"mappings":"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","names":[]}

@@ -1,4 +0,3 @@

import { normalizeUrl } from '@power-seo/core';
// src/merge.ts
import { normalizeUrl } from "@power-seo/core";
function mergeGscWithAudit(gscData, auditResults) {

@@ -241,5 +240,12 @@ const auditMap = /* @__PURE__ */ new Map();

}
export { analyzeQueryRankings, analyzeTrend, buildDashboardData, buildTrendLines, correlateScoreAndTraffic, detectAnomalies, mergeGscWithAudit, trackPositionChanges };
//# sourceMappingURL=index.js.map
export {
analyzeQueryRankings,
analyzeTrend,
buildDashboardData,
buildTrendLines,
correlateScoreAndTraffic,
detectAnomalies,
mergeGscWithAudit,
trackPositionChanges
};
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/merge.ts","../src/trends.ts","../src/rankings.ts","../src/dashboard.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/analytics — Merge GSC + Audit Data\n// ============================================================================\n\nimport { normalizeUrl } from '@power-seo/core';\nimport type { GscPageData, PageInsight, AuditCategory, CategoryResult } from './types.js';\n\ninterface AuditData {\n url: string;\n score: number;\n categories: Record<AuditCategory, CategoryResult>;\n recommendations: string[];\n}\n\nexport function mergeGscWithAudit(\n gscData: GscPageData[],\n auditResults: AuditData[],\n): PageInsight[] {\n const auditMap = new Map<string, AuditData>();\n for (const result of auditResults) {\n auditMap.set(normalizeUrl(result.url), result);\n }\n\n const gscMap = new Map<string, GscPageData>();\n for (const page of gscData) {\n gscMap.set(normalizeUrl(page.url), page);\n }\n\n const allUrls = new Set([...auditMap.keys(), ...gscMap.keys()]);\n const insights: PageInsight[] = [];\n\n for (const url of allUrls) {\n const gsc = gscMap.get(url);\n const audit = auditMap.get(url);\n const opportunities: string[] = [];\n\n if (gsc && audit) {\n if (gsc.clicks > 50 && audit.score < 70) {\n opportunities.push(\n `High-traffic page (${gsc.clicks} clicks) with low audit score (${audit.score}). Fixing issues could significantly boost organic performance.`,\n );\n }\n if (gsc.position > 10 && gsc.impressions > 100) {\n opportunities.push(\n `Page has ${gsc.impressions} impressions at position ${gsc.position.toFixed(1)}. Improving to page 1 could unlock significant traffic.`,\n );\n }\n if (audit.recommendations.length > 0) {\n opportunities.push(...audit.recommendations.slice(0, 3));\n }\n } else if (gsc && !audit) {\n opportunities.push(\n 'Page receives search traffic but has not been audited. Run an audit to identify improvement opportunities.',\n );\n } else if (!gsc && audit) {\n if (audit.score < 50) {\n opportunities.push(\n `Page has a low audit score (${audit.score}) and no search traffic. Consider improving or removing the page.`,\n );\n }\n }\n\n insights.push({\n url,\n gscMetrics: gsc\n ? { clicks: gsc.clicks, impressions: gsc.impressions, ctr: gsc.ctr, position: gsc.position }\n : undefined,\n auditScore: audit?.score,\n auditCategories: audit?.categories,\n opportunities,\n });\n }\n\n return insights;\n}\n\nexport function correlateScoreAndTraffic(insights: PageInsight[]): {\n correlation: number;\n topOpportunities: PageInsight[];\n} {\n const paired = insights.filter((i) => i.gscMetrics && i.auditScore !== undefined);\n\n if (paired.length < 2) {\n return { correlation: 0, topOpportunities: [] };\n }\n\n const scores = paired.map((i) => i.auditScore!);\n const clicks = paired.map((i) => i.gscMetrics!.clicks);\n\n const n = scores.length;\n const meanScore = scores.reduce((a, b) => a + b, 0) / n;\n const meanClicks = clicks.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denomScore = 0;\n let denomClicks = 0;\n\n for (let i = 0; i < n; i++) {\n const diffScore = (scores[i] ?? 0) - meanScore;\n const diffClicks = (clicks[i] ?? 0) - meanClicks;\n numerator += diffScore * diffClicks;\n denomScore += diffScore * diffScore;\n denomClicks += diffClicks * diffClicks;\n }\n\n const denominator = Math.sqrt(denomScore * denomClicks);\n const correlation = denominator === 0 ? 0 : numerator / denominator;\n\n // Top opportunities: high traffic, low score\n const topOpportunities = [...paired]\n .filter((i) => i.gscMetrics!.clicks > 0)\n .sort((a, b) => {\n const scoreA = a.gscMetrics!.clicks / (a.auditScore! || 1);\n const scoreB = b.gscMetrics!.clicks / (b.auditScore! || 1);\n return scoreB - scoreA;\n })\n .slice(0, 10);\n\n return { correlation: Math.round(correlation * 1000) / 1000, topOpportunities };\n}\n","// ============================================================================\n// @power-seo/analytics — Trend Analysis\n// ============================================================================\n\nimport type { TrendPoint, TrendDirection, TrendAnalysis, AuditSnapshot } from './types.js';\n\nexport function analyzeTrend(points: TrendPoint[], metric = 'value'): TrendAnalysis {\n if (points.length === 0) {\n return { metric, trend: 'stable', change: 0, points: [] };\n }\n\n if (points.length === 1) {\n return { metric, trend: 'stable', change: 0, points };\n }\n\n // Linear regression for slope\n const n = points.length;\n const xs = points.map((_, i) => i);\n const ys = points.map((p) => p.value);\n\n const meanX = xs.reduce((a, b) => a + b, 0) / n;\n const meanY = ys.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denominator = 0;\n for (let i = 0; i < n; i++) {\n const xi = xs[i] ?? 0;\n const yi = ys[i] ?? 0;\n numerator += (xi - meanX) * (yi - meanY);\n denominator += (xi - meanX) * (xi - meanX);\n }\n\n const slope = denominator === 0 ? 0 : numerator / denominator;\n\n // Percentage change first→last\n const first = points[0]!.value;\n const last = points[points.length - 1]!.value;\n const change = first === 0 ? 0 : Math.round(((last - first) / Math.abs(first)) * 10000) / 100;\n\n // Classify trend based on slope relative to mean\n const threshold = Math.abs(meanY) * 0.02; // 2% of mean\n let trend: TrendDirection;\n if (slope > threshold) {\n trend = 'improving';\n } else if (slope < -threshold) {\n trend = 'declining';\n } else {\n trend = 'stable';\n }\n\n return { metric, trend, change, points };\n}\n\nexport function buildTrendLines(snapshots: AuditSnapshot[]): Record<string, TrendAnalysis> {\n if (snapshots.length === 0) {\n return {};\n }\n\n // Sort by date\n const sorted = [...snapshots].sort((a, b) => a.date.localeCompare(b.date));\n\n // Overall score trend\n const overallPoints: TrendPoint[] = sorted.map((s) => ({ date: s.date, value: s.score }));\n const result: Record<string, TrendAnalysis> = {\n overall: analyzeTrend(overallPoints, 'overall'),\n };\n\n // Per-category trends\n const categories = Object.keys(sorted[0]!.categories) as Array<\n keyof (typeof sorted)[0]['categories']\n >;\n for (const category of categories) {\n const categoryPoints: TrendPoint[] = sorted.map((s) => ({\n date: s.date,\n value: s.categories[category],\n }));\n result[category] = analyzeTrend(categoryPoints, category);\n }\n\n return result;\n}\n\nexport function detectAnomalies(points: TrendPoint[], threshold = 2): TrendPoint[] {\n if (points.length < 3) {\n return [];\n }\n\n const values = points.map((p) => p.value);\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / values.length;\n const stdDev = Math.sqrt(variance);\n\n if (stdDev === 0) {\n return [];\n }\n\n return points.filter((p) => Math.abs(p.value - mean) > threshold * stdDev);\n}\n","// ============================================================================\n// @power-seo/analytics — Query Ranking Analysis\n// ============================================================================\n\nimport type { GscQueryData, RankingAnalysis, RankingBucket, PositionChange } from './types.js';\n\nconst BUCKET_RANGES = [\n { range: '1-3', min: 1, max: 3 },\n { range: '4-10', min: 4, max: 10 },\n { range: '11-20', min: 11, max: 20 },\n { range: '21-100', min: 21, max: 100 },\n];\n\nexport function analyzeQueryRankings(queries: GscQueryData[]): RankingAnalysis {\n if (queries.length === 0) {\n return {\n totalQueries: 0,\n buckets: BUCKET_RANGES.map((r) => ({ range: r.range, count: 0, queries: [] })),\n strikingDistance: [],\n };\n }\n\n const buckets: RankingBucket[] = BUCKET_RANGES.map((range) => {\n const matching = queries.filter((q) => q.position >= range.min && q.position <= range.max);\n return {\n range: range.range,\n count: matching.length,\n queries: matching,\n };\n });\n\n // Striking distance: position 4-20, sorted by impressions descending\n const strikingDistance = queries\n .filter((q) => q.position >= 4 && q.position <= 20)\n .sort((a, b) => b.impressions - a.impressions);\n\n return {\n totalQueries: queries.length,\n buckets,\n strikingDistance,\n };\n}\n\nexport function trackPositionChanges(\n current: GscQueryData[],\n previous: GscQueryData[],\n): PositionChange[] {\n if (current.length === 0 && previous.length === 0) {\n return [];\n }\n\n const prevMap = new Map<string, GscQueryData>();\n for (const q of previous) {\n prevMap.set(q.query, q);\n }\n\n const changes: PositionChange[] = [];\n\n for (const curr of current) {\n const prev = prevMap.get(curr.query);\n if (prev) {\n changes.push({\n query: curr.query,\n previousPosition: prev.position,\n currentPosition: curr.position,\n change: prev.position - curr.position, // positive = improvement\n impressionChange: curr.impressions - prev.impressions,\n });\n }\n }\n\n return changes;\n}\n","// ============================================================================\n// @power-seo/analytics — Dashboard Data Builder\n// ============================================================================\n\nimport type { DashboardInput, DashboardData, DashboardOverview } from './types.js';\nimport { buildTrendLines } from './trends.js';\n\nexport function buildDashboardData(input: DashboardInput): DashboardData {\n const { gscPages = [], gscQueries = [], auditResults = [], auditHistory = [] } = input;\n\n // Overview metrics\n const totalClicks = gscPages.reduce((sum, p) => sum + p.clicks, 0);\n const totalImpressions = gscPages.reduce((sum, p) => sum + p.impressions, 0);\n const averageCtr =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.ctr, 0) / gscPages.length) * 10000) / 10000\n : 0;\n const averagePosition =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.position, 0) / gscPages.length) * 10) / 10\n : 0;\n const averageAuditScore =\n auditResults.length > 0\n ? Math.round(auditResults.reduce((sum, r) => sum + r.score, 0) / auditResults.length)\n : 0;\n const totalPages = Math.max(gscPages.length, auditResults.length);\n\n const overview: DashboardOverview = {\n totalClicks,\n totalImpressions,\n averageCtr,\n averagePosition,\n averageAuditScore,\n totalPages,\n };\n\n // Top pages by clicks\n const topPages = [...gscPages].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Top queries by clicks\n const topQueries = [...gscQueries].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Trend lines from audit history\n const trendLines = buildTrendLines(auditHistory);\n\n // Collect issues from audit results\n const issues: string[] = [];\n for (const result of auditResults) {\n issues.push(...result.recommendations);\n }\n // Deduplicate and limit\n const uniqueIssues = [...new Set(issues)].slice(0, 20);\n\n return {\n overview,\n topPages,\n topQueries,\n trendLines,\n issues: uniqueIssues,\n };\n}\n"]}
{"version":3,"sources":["../src/merge.ts","../src/trends.ts","../src/rankings.ts","../src/dashboard.ts"],"sourcesContent":["// @power-seo/analytics — Merge GSC + Audit Data\n// ----------------------------------------------------------------------------\n\nimport { normalizeUrl } from '@power-seo/core';\nimport type { GscPageData, PageInsight, AuditCategory, CategoryResult } from './types.js';\n\ninterface AuditData {\n url: string;\n score: number;\n categories: Record<AuditCategory, CategoryResult>;\n recommendations: string[];\n}\n\nexport function mergeGscWithAudit(\n gscData: GscPageData[],\n auditResults: AuditData[],\n): PageInsight[] {\n const auditMap = new Map<string, AuditData>();\n for (const result of auditResults) {\n auditMap.set(normalizeUrl(result.url), result);\n }\n\n const gscMap = new Map<string, GscPageData>();\n for (const page of gscData) {\n gscMap.set(normalizeUrl(page.url), page);\n }\n\n const allUrls = new Set([...auditMap.keys(), ...gscMap.keys()]);\n const insights: PageInsight[] = [];\n\n for (const url of allUrls) {\n const gsc = gscMap.get(url);\n const audit = auditMap.get(url);\n const opportunities: string[] = [];\n\n if (gsc && audit) {\n if (gsc.clicks > 50 && audit.score < 70) {\n opportunities.push(\n `High-traffic page (${gsc.clicks} clicks) with low audit score (${audit.score}). Fixing issues could significantly boost organic performance.`,\n );\n }\n if (gsc.position > 10 && gsc.impressions > 100) {\n opportunities.push(\n `Page has ${gsc.impressions} impressions at position ${gsc.position.toFixed(1)}. Improving to page 1 could unlock significant traffic.`,\n );\n }\n if (audit.recommendations.length > 0) {\n opportunities.push(...audit.recommendations.slice(0, 3));\n }\n } else if (gsc && !audit) {\n opportunities.push(\n 'Page receives search traffic but has not been audited. Run an audit to identify improvement opportunities.',\n );\n } else if (!gsc && audit) {\n if (audit.score < 50) {\n opportunities.push(\n `Page has a low audit score (${audit.score}) and no search traffic. Consider improving or removing the page.`,\n );\n }\n }\n\n insights.push({\n url,\n gscMetrics: gsc\n ? { clicks: gsc.clicks, impressions: gsc.impressions, ctr: gsc.ctr, position: gsc.position }\n : undefined,\n auditScore: audit?.score,\n auditCategories: audit?.categories,\n opportunities,\n });\n }\n\n return insights;\n}\n\nexport function correlateScoreAndTraffic(insights: PageInsight[]): {\n correlation: number;\n topOpportunities: PageInsight[];\n} {\n const paired = insights.filter((i) => i.gscMetrics && i.auditScore !== undefined);\n\n if (paired.length < 2) {\n return { correlation: 0, topOpportunities: [] };\n }\n\n const scores = paired.map((i) => i.auditScore!);\n const clicks = paired.map((i) => i.gscMetrics!.clicks);\n\n const n = scores.length;\n const meanScore = scores.reduce((a, b) => a + b, 0) / n;\n const meanClicks = clicks.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denomScore = 0;\n let denomClicks = 0;\n\n for (let i = 0; i < n; i++) {\n const diffScore = (scores[i] ?? 0) - meanScore;\n const diffClicks = (clicks[i] ?? 0) - meanClicks;\n numerator += diffScore * diffClicks;\n denomScore += diffScore * diffScore;\n denomClicks += diffClicks * diffClicks;\n }\n\n const denominator = Math.sqrt(denomScore * denomClicks);\n const correlation = denominator === 0 ? 0 : numerator / denominator;\n\n // Top opportunities: high traffic, low score\n const topOpportunities = [...paired]\n .filter((i) => i.gscMetrics!.clicks > 0)\n .sort((a, b) => {\n const scoreA = a.gscMetrics!.clicks / (a.auditScore! || 1);\n const scoreB = b.gscMetrics!.clicks / (b.auditScore! || 1);\n return scoreB - scoreA;\n })\n .slice(0, 10);\n\n return { correlation: Math.round(correlation * 1000) / 1000, topOpportunities };\n}\n","// @power-seo/analytics — Trend Analysis\n// ----------------------------------------------------------------------------\n\nimport type { TrendPoint, TrendDirection, TrendAnalysis, AuditSnapshot } from './types.js';\n\nexport function analyzeTrend(points: TrendPoint[], metric = 'value'): TrendAnalysis {\n if (points.length === 0) {\n return { metric, trend: 'stable', change: 0, points: [] };\n }\n\n if (points.length === 1) {\n return { metric, trend: 'stable', change: 0, points };\n }\n\n // Linear regression for slope\n const n = points.length;\n const xs = points.map((_, i) => i);\n const ys = points.map((p) => p.value);\n\n const meanX = xs.reduce((a, b) => a + b, 0) / n;\n const meanY = ys.reduce((a, b) => a + b, 0) / n;\n\n let numerator = 0;\n let denominator = 0;\n for (let i = 0; i < n; i++) {\n const xi = xs[i] ?? 0;\n const yi = ys[i] ?? 0;\n numerator += (xi - meanX) * (yi - meanY);\n denominator += (xi - meanX) * (xi - meanX);\n }\n\n const slope = denominator === 0 ? 0 : numerator / denominator;\n\n // Percentage change first→last\n const first = points[0]!.value;\n const last = points[points.length - 1]!.value;\n const change = first === 0 ? 0 : Math.round(((last - first) / Math.abs(first)) * 10000) / 100;\n\n // Classify trend based on slope relative to mean\n const threshold = Math.abs(meanY) * 0.02; // 2% of mean\n let trend: TrendDirection;\n if (slope > threshold) {\n trend = 'improving';\n } else if (slope < -threshold) {\n trend = 'declining';\n } else {\n trend = 'stable';\n }\n\n return { metric, trend, change, points };\n}\n\nexport function buildTrendLines(snapshots: AuditSnapshot[]): Record<string, TrendAnalysis> {\n if (snapshots.length === 0) {\n return {};\n }\n\n // Sort by date\n const sorted = [...snapshots].sort((a, b) => a.date.localeCompare(b.date));\n\n // Overall score trend\n const overallPoints: TrendPoint[] = sorted.map((s) => ({ date: s.date, value: s.score }));\n const result: Record<string, TrendAnalysis> = {\n overall: analyzeTrend(overallPoints, 'overall'),\n };\n\n // Per-category trends\n const categories = Object.keys(sorted[0]!.categories) as Array<\n keyof (typeof sorted)[0]['categories']\n >;\n for (const category of categories) {\n const categoryPoints: TrendPoint[] = sorted.map((s) => ({\n date: s.date,\n value: s.categories[category],\n }));\n result[category] = analyzeTrend(categoryPoints, category);\n }\n\n return result;\n}\n\nexport function detectAnomalies(points: TrendPoint[], threshold = 2): TrendPoint[] {\n if (points.length < 3) {\n return [];\n }\n\n const values = points.map((p) => p.value);\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / values.length;\n const stdDev = Math.sqrt(variance);\n\n if (stdDev === 0) {\n return [];\n }\n\n return points.filter((p) => Math.abs(p.value - mean) > threshold * stdDev);\n}\n","// @power-seo/analytics — Query Ranking Analysis\n// ----------------------------------------------------------------------------\n\nimport type { GscQueryData, RankingAnalysis, RankingBucket, PositionChange } from './types.js';\n\nconst BUCKET_RANGES = [\n { range: '1-3', min: 1, max: 3 },\n { range: '4-10', min: 4, max: 10 },\n { range: '11-20', min: 11, max: 20 },\n { range: '21-100', min: 21, max: 100 },\n];\n\nexport function analyzeQueryRankings(queries: GscQueryData[]): RankingAnalysis {\n if (queries.length === 0) {\n return {\n totalQueries: 0,\n buckets: BUCKET_RANGES.map((r) => ({ range: r.range, count: 0, queries: [] })),\n strikingDistance: [],\n };\n }\n\n const buckets: RankingBucket[] = BUCKET_RANGES.map((range) => {\n const matching = queries.filter((q) => q.position >= range.min && q.position <= range.max);\n return {\n range: range.range,\n count: matching.length,\n queries: matching,\n };\n });\n\n // Striking distance: position 4-20, sorted by impressions descending\n const strikingDistance = queries\n .filter((q) => q.position >= 4 && q.position <= 20)\n .sort((a, b) => b.impressions - a.impressions);\n\n return {\n totalQueries: queries.length,\n buckets,\n strikingDistance,\n };\n}\n\nexport function trackPositionChanges(\n current: GscQueryData[],\n previous: GscQueryData[],\n): PositionChange[] {\n if (current.length === 0 && previous.length === 0) {\n return [];\n }\n\n const prevMap = new Map<string, GscQueryData>();\n for (const q of previous) {\n prevMap.set(q.query, q);\n }\n\n const changes: PositionChange[] = [];\n\n for (const curr of current) {\n const prev = prevMap.get(curr.query);\n if (prev) {\n changes.push({\n query: curr.query,\n previousPosition: prev.position,\n currentPosition: curr.position,\n change: prev.position - curr.position, // positive = improvement\n impressionChange: curr.impressions - prev.impressions,\n });\n }\n }\n\n return changes;\n}\n","// @power-seo/analytics — Dashboard Data Builder\n// ----------------------------------------------------------------------------\n\nimport type { DashboardInput, DashboardData, DashboardOverview } from './types.js';\nimport { buildTrendLines } from './trends.js';\n\nexport function buildDashboardData(input: DashboardInput): DashboardData {\n const { gscPages = [], gscQueries = [], auditResults = [], auditHistory = [] } = input;\n\n // Overview metrics\n const totalClicks = gscPages.reduce((sum, p) => sum + p.clicks, 0);\n const totalImpressions = gscPages.reduce((sum, p) => sum + p.impressions, 0);\n const averageCtr =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.ctr, 0) / gscPages.length) * 10000) / 10000\n : 0;\n const averagePosition =\n gscPages.length > 0\n ? Math.round((gscPages.reduce((sum, p) => sum + p.position, 0) / gscPages.length) * 10) / 10\n : 0;\n const averageAuditScore =\n auditResults.length > 0\n ? Math.round(auditResults.reduce((sum, r) => sum + r.score, 0) / auditResults.length)\n : 0;\n const totalPages = Math.max(gscPages.length, auditResults.length);\n\n const overview: DashboardOverview = {\n totalClicks,\n totalImpressions,\n averageCtr,\n averagePosition,\n averageAuditScore,\n totalPages,\n };\n\n // Top pages by clicks\n const topPages = [...gscPages].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Top queries by clicks\n const topQueries = [...gscQueries].sort((a, b) => b.clicks - a.clicks).slice(0, 10);\n\n // Trend lines from audit history\n const trendLines = buildTrendLines(auditHistory);\n\n // Collect issues from audit results\n const issues: string[] = [];\n for (const result of auditResults) {\n issues.push(...result.recommendations);\n }\n // Deduplicate and limit\n const uniqueIssues = [...new Set(issues)].slice(0, 20);\n\n return {\n overview,\n topPages,\n topQueries,\n trendLines,\n issues: uniqueIssues,\n };\n}\n"],"mappings":"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","names":[]}
{
"name": "@power-seo/analytics",
"version": "1.0.4",
"version": "1.0.7",
"description": "Analytics data processing: merge GSC data with audit results, trend analysis, ranking insights",

@@ -20,18 +20,8 @@ "license": "MIT",

],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"clean": "rimraf dist"
},
"dependencies": {
"@power-seo/core": "workspace:*",
"@power-seo/audit": "workspace:*"
"@power-seo/core": "1.0.3",
"@power-seo/audit": "1.0.7"
},
"devDependencies": {
"rimraf": "^6.0.0",
"rimraf": "^6.1.3",
"tsup": "^8.3.0",

@@ -59,3 +49,21 @@ "typescript": "^5.7.0",

"access": "public"
},
"bugs": {
"url": "https://github.com/CyberCraftBD/power-seo/issues"
},
"homepage": "https://github.com/CyberCraftBD/power-seo/tree/main/packages/analytics#readme",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/cybercraftbd"
},
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"clean": "rimraf dist"
}
}
}