@power-seo/analytics
Advanced tools
+10
-4
| { | ||
| "name": "@power-seo/analytics", | ||
| "version": "1.0.11", | ||
| "version": "1.0.12", | ||
| "description": "Analytics data processing: merge GSC data with audit results, trend analysis, ranking insights", | ||
@@ -40,7 +40,13 @@ "keywords": [ | ||
| "files": [ | ||
| "dist" | ||
| "dist", | ||
| "LICENSE" | ||
| ], | ||
| "engines": { | ||
| "node": ">=18.0.0", | ||
| "npm": ">=9.0.0", | ||
| "pnpm": ">=8.0.0" | ||
| }, | ||
| "dependencies": { | ||
| "@power-seo/core": "1.0.11", | ||
| "@power-seo/audit": "1.0.11" | ||
| "@power-seo/core": "1.0.12", | ||
| "@power-seo/audit": "1.0.12" | ||
| }, | ||
@@ -47,0 +53,0 @@ "devDependencies": { |
+104
-99
| # @power-seo/analytics | ||
|  | ||
|  | ||
@@ -10,3 +10,2 @@ Merge Google Search Console data with audit results, compute Pearson correlations, analyze trends, detect anomalies, and build dashboard-ready aggregated outputs. | ||
| [](https://socket.dev/npm/package/@power-seo/analytics) | ||
| [](https://github.com/CyberCraftBD/power-seo/actions) | ||
| [](https://opensource.org/licenses/MIT) | ||
@@ -36,4 +35,10 @@ [](https://www.typescriptlang.org/) | ||
|  | ||
|  | ||
| <p align="left"> | ||
| <a href="https://www.buymeacoffee.com/ccbd.dev" target="_blank"> | ||
| <img src="https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20coffee&emoji=&slug=ccbd.dev&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" /> | ||
| </a> | ||
| </p> | ||
| --- | ||
@@ -48,3 +53,3 @@ | ||
| - **Anomaly detection** — `detectAnomalies` flags statistically significant spikes and drops in a time series using a configurable standard deviation threshold, returning annotated anomaly objects with timestamps and delta values | ||
| - **Position bucket analysis** — `analyzeQueryRankings` groups queries into five standard SERP ranking tiers: 1–3 (top spots), 4–10 (first page), 11–20 (second page), 21–50 (deep pages), 50+ (not ranking meaningfully) | ||
| - **Position bucket analysis** — `analyzeQueryRankings` groups queries into four standard SERP ranking tiers: 1–3 (top spots), 4–10 (first page), 11–20 (second page), 21–100 (deep pages) | ||
| - **Position change tracking** — `trackPositionChanges` compares two ranking snapshots and produces a list of `PositionChange` objects showing which queries improved, declined, or are new/dropped | ||
@@ -56,3 +61,3 @@ - **Dashboard aggregation** — `buildDashboardData` accepts raw GSC pages, GSC queries, and audit results and returns a structured `DashboardData` object containing: overview metrics, top pages by traffic, top queries by clicks, trend lines, and a prioritized issue list | ||
|  | ||
|  | ||
@@ -75,3 +80,3 @@ --- | ||
|  | ||
|  | ||
@@ -124,3 +129,3 @@ --- | ||
|  | ||
|  | ||
@@ -156,12 +161,13 @@ --- | ||
| const auditResults: AuditSnapshot[] = [ | ||
| { url: '/blog/post-1', score: 91, issues: [] }, | ||
| const auditResults = [ | ||
| { url: '/blog/post-1', score: 91, categories: { performance: 88, seo: 91 }, recommendations: [] }, | ||
| { | ||
| url: '/blog/post-2', | ||
| score: 63, | ||
| issues: [{ rule: 'meta-description', severity: 'error', message: '...' }], | ||
| categories: { performance: 55, seo: 63 }, | ||
| recommendations: ['Improve meta description', 'Add more internal links'], | ||
| }, | ||
| ]; | ||
| const insights: PageInsight[] = mergeGscWithAudit({ gscPages, auditResults }); | ||
| const insights: PageInsight[] = mergeGscWithAudit(gscPages, auditResults); | ||
@@ -180,13 +186,17 @@ insights.forEach(({ url, clicks, position, auditScore }) => { | ||
| const insights = mergeGscWithAudit({ gscPages, auditResults }); | ||
| const correlation = correlateScoreAndTraffic(insights); | ||
| const insights = mergeGscWithAudit(gscPages, auditResults); | ||
| const result = correlateScoreAndTraffic(insights); | ||
| console.log(`Pearson r: ${correlation.coefficient.toFixed(3)}`); | ||
| console.log(`Pearson r: ${result.correlation.toFixed(3)}`); | ||
| // e.g. 0.741 — strong positive correlation | ||
| console.log(`Statistically significant: ${correlation.significant}`); | ||
| if (correlation.coefficient > 0.5) { | ||
| if (result.correlation > 0.5) { | ||
| console.log('Strong positive relationship: improving audit scores tends to increase traffic'); | ||
| } | ||
| // Top pages with high traffic but low scores | ||
| console.log( | ||
| 'Quick wins:', | ||
| result.topOpportunities.map((p) => p.url), | ||
| ); | ||
| ``` | ||
@@ -210,9 +220,13 @@ | ||
| const trend: TrendAnalysis = analyzeTrend(weeklyClicks); | ||
| console.log(trend.direction); // 'up' | 'down' | 'stable' | ||
| console.log(trend.rate); // % change per period, e.g. 5.8 | ||
| console.log(trend.confidence); // 0-1, linearity confidence, e.g. 0.87 | ||
| console.log(trend.trend); // 'improving' | 'declining' | 'stable' | ||
| console.log(trend.change); // % change from first to last, e.g. 32.5 | ||
| console.log(trend.metric); // name of metric, e.g. 'value' | ||
| // Build chart-ready trend line data | ||
| const trendLines = buildTrendLines(weeklyClicks); | ||
| // [{ date: '2026-01-05', actual: 1200, trend: 1195 }, ...] | ||
| // Build chart-ready trend line data from audit history | ||
| const auditSnapshots: AuditSnapshot[] = [ | ||
| { date: '2026-01-01', url: '/page', score: 75, categories: { performance: 85, seo: 72 } }, | ||
| // more snapshots... | ||
| ]; | ||
| const trendLines = buildTrendLines(auditSnapshots); | ||
| // { overall: TrendAnalysis, performance: TrendAnalysis, seo: TrendAnalysis } | ||
| ``` | ||
@@ -236,4 +250,7 @@ | ||
| const anomalies = detectAnomalies(dailyImpressions, { threshold: 2.0 }); | ||
| anomalies.forEach(({ date, value, type, delta }) => { | ||
| const anomalies = detectAnomalies(dailyImpressions, 2.0); | ||
| anomalies.forEach(({ date, value }) => { | ||
| const mean = dailyImpressions.reduce((s, p) => s + p.value, 0) / dailyImpressions.length; | ||
| const delta = value - mean; | ||
| const type = delta > 0 ? 'spike' : 'drop'; | ||
| console.log(`${date}: ${type} anomaly — value=${value}, delta=${delta.toFixed(0)} from baseline`); | ||
@@ -261,10 +278,8 @@ }); | ||
| console.log('Position 1-3:', analysis.buckets['1-3'].length, 'queries'); | ||
| console.log('Position 4-10:', analysis.buckets['4-10'].length, 'queries'); | ||
| console.log('Position 11-20:', analysis.buckets['11-20'].length, 'queries'); | ||
| console.log('Position 21-50:', analysis.buckets['21-50'].length, 'queries'); | ||
| console.log('Position 50+:', analysis.buckets['50+'].length, 'queries'); | ||
| analysis.buckets.forEach((bucket) => { | ||
| console.log(`Position ${bucket.range}: ${bucket.count} queries`); | ||
| }); | ||
| // Quick-win opportunities: ranked 11-20 with good impressions | ||
| const quickWins = analysis.buckets['11-20'].filter((q) => q.impressions > 2000); | ||
| // Quick-win opportunities: ranked 4-20 with good impressions (strikingDistance) | ||
| const quickWins = analysis.strikingDistance.filter((q) => q.impressions > 2000); | ||
| console.log( | ||
@@ -282,3 +297,3 @@ 'Quick-win queries:', | ||
| const snapshot1: GscQueryData[] = [ | ||
| const previousSnapshot: GscQueryData[] = [ | ||
| { query: 'react seo guide', clicks: 320, impressions: 8200, ctr: 0.039, position: 8.4 }, | ||
@@ -288,3 +303,3 @@ { query: 'seo audit', clicks: 45, impressions: 1900, ctr: 0.024, position: 22.0 }, | ||
| const snapshot2: GscQueryData[] = [ | ||
| const currentSnapshot: GscQueryData[] = [ | ||
| { query: 'react seo guide', clicks: 580, impressions: 9800, ctr: 0.059, position: 5.1 }, | ||
@@ -295,10 +310,9 @@ { query: 'seo audit', clicks: 88, impressions: 2200, ctr: 0.04, position: 14.3 }, | ||
| const changes: PositionChange[] = trackPositionChanges(snapshot1, snapshot2); | ||
| changes.forEach(({ query, before, after, delta, direction }) => { | ||
| const arrow = direction === 'improved' ? '↑' : direction === 'declined' ? '↓' : '→'; | ||
| console.log(`${arrow} "${query}": ${before ?? 'new'} → ${after ?? 'dropped'}`); | ||
| const changes: PositionChange[] = trackPositionChanges(currentSnapshot, previousSnapshot); | ||
| changes.forEach(({ query, previousPosition, currentPosition, change }) => { | ||
| const direction = change > 0 ? '↑' : change < 0 ? '↓' : '→'; | ||
| console.log(`${direction} "${query}": ${previousPosition} → ${currentPosition}`); | ||
| }); | ||
| // ↑ "react seo guide": 8.4 → 5.1 | ||
| // ↑ "seo audit": 22.0 → 14.3 | ||
| // → "seo typescript": new → 31.0 | ||
| ``` | ||
@@ -316,3 +330,3 @@ | ||
| auditResults: allAuditResults, | ||
| topN: 10, | ||
| auditHistory: allAuditSnapshots, | ||
| }); | ||
@@ -340,6 +354,4 @@ | ||
| // Prioritized issues — high-traffic pages with low audit scores | ||
| dashboard.issues.forEach(({ rule, severity, affectedPages }) => | ||
| console.log(`[${severity}] ${rule}: affects ${affectedPages} pages`), | ||
| ); | ||
| // Recommended issues — deduplicated and prioritized | ||
| dashboard.issues.forEach((issue) => console.log(`Issue: ${issue}`)); | ||
| ``` | ||
@@ -351,10 +363,10 @@ | ||
| ### `mergeGscWithAudit(input)` | ||
| ### `mergeGscWithAudit(gscData, auditResults)` | ||
| | Parameter | Type | Default | Description | | ||
| | -------------------- | ----------------- | -------- | ------------------------------------------- | | ||
| | `input.gscPages` | `GscPageData[]` | required | Google Search Console page performance data | | ||
| | `input.auditResults` | `AuditSnapshot[]` | required | Audit results with URL, score, and issues | | ||
| | Parameter | Type | Default | Description | | ||
| | -------------- | --------------- | -------- | ---------------------------------------------------------- | | ||
| | `gscData` | `GscPageData[]` | required | Google Search Console page performance data | | ||
| | `auditResults` | `AuditData[]` | required | Audit results with URL, score, categories, recommendations | | ||
| Returns `PageInsight[]` — merged records keyed by normalized URL. | ||
| Returns `PageInsight[]` — merged records keyed by normalized URL with opportunities identified. | ||
@@ -369,7 +381,7 @@ --- | ||
| Returns `{ coefficient: number; significant: boolean; sampleSize: number }`. | ||
| Returns `{ correlation: number; topOpportunities: PageInsight[] }` — Pearson correlation coefficient and highest-opportunity pages (high traffic, low score). | ||
| --- | ||
| ### `analyzeTrend(points)` | ||
| ### `analyzeTrend(points, metric?)` | ||
@@ -379,25 +391,26 @@ | Parameter | Type | Default | Description | | ||
| | `points` | `TrendPoint[]` | required | Time-ordered `{ date: string; value: number }` array | | ||
| | `metric` | `string` | 'value' | Name of the metric being analyzed | | ||
| Returns `TrendAnalysis`: `{ direction: TrendDirection; rate: number; confidence: number }`. | ||
| Returns `TrendAnalysis`: `{ metric: string; trend: TrendDirection; change: number; points: TrendPoint[] }`. Trend is determined by linear regression slope; change is percentage difference from first to last value. | ||
| --- | ||
| ### `buildTrendLines(points)` | ||
| ### `buildTrendLines(snapshots)` | ||
| | Parameter | Type | Default | Description | | ||
| | --------- | -------------- | -------- | ------------------------ | | ||
| | `points` | `TrendPoint[]` | required | Time-ordered data points | | ||
| | Parameter | Type | Default | Description | | ||
| | ----------- | ----------------- | -------- | --------------------------------------------------- | | ||
| | `snapshots` | `AuditSnapshot[]` | required | Audit snapshots with date, score, and category data | | ||
| Returns `Array<{ date: string; actual: number; trend: number }>`. | ||
| Returns `Record<string, TrendAnalysis>` — includes 'overall' trend plus per-category trends (e.g., 'performance', 'seo'). | ||
| --- | ||
| ### `detectAnomalies(points, options?)` | ||
| ### `detectAnomalies(points, threshold?)` | ||
| | Parameter | Type | Default | Description | | ||
| | ------------------- | -------------- | -------- | --------------------------------------------------- | | ||
| | `points` | `TrendPoint[]` | required | Time-ordered data points | | ||
| | `options.threshold` | `number` | `2.0` | Standard deviation multiplier for anomaly detection | | ||
| | Parameter | Type | Default | Description | | ||
| | ----------- | -------------- | -------- | --------------------------------------------------- | | ||
| | `points` | `TrendPoint[]` | required | Time-ordered data points | | ||
| | `threshold` | `number` | `2.0` | Standard deviation multiplier for anomaly detection | | ||
| Returns `Array<{ date: string; value: number; type: 'spike' | 'drop'; delta: number }>`. | ||
| Returns `TrendPoint[]` — data points that exceed the threshold (standard deviation multiple of the mean). Caller can determine if spike or drop based on mean. | ||
@@ -412,14 +425,14 @@ --- | ||
| Returns `RankingAnalysis`: `{ buckets: Record<RankingBucket, GscQueryData[]>; totalQueries: number }`. | ||
| Returns `RankingAnalysis`: `{ totalQueries: number; buckets: RankingBucket[]; strikingDistance: GscQueryData[] }`. Buckets are: 1–3, 4–10, 11–20, 21–100 (positions). Striking distance identifies 4–20 ranked queries with highest impressions for quick-win targeting. | ||
| --- | ||
| ### `trackPositionChanges(before, after)` | ||
| ### `trackPositionChanges(current, previous)` | ||
| | Parameter | Type | Default | Description | | ||
| | --------- | ---------------- | -------- | ---------------------------------------- | | ||
| | `before` | `GscQueryData[]` | required | Ranking snapshot from the earlier period | | ||
| | `after` | `GscQueryData[]` | required | Ranking snapshot from the later period | | ||
| | Parameter | Type | Default | Description | | ||
| | ---------- | ---------------- | -------- | ---------------------------------------- | | ||
| | `current` | `GscQueryData[]` | required | Ranking snapshot from the later period | | ||
| | `previous` | `GscQueryData[]` | required | Ranking snapshot from the earlier period | | ||
| Returns `PositionChange[]`. | ||
| Returns `PositionChange[]`: `{ query: string; previousPosition: number; currentPosition: number; change: number; impressionChange: number }`. Positive `change` indicates improvement (lower position number). | ||
@@ -430,11 +443,10 @@ --- | ||
| | Parameter | Type | Default | Description | | ||
| | -------------------- | ----------------- | -------- | --------------------------------------------------- | | ||
| | `input.gscPages` | `GscPageData[]` | required | GSC page performance data | | ||
| | `input.gscQueries` | `GscQueryData[]` | required | GSC query performance data | | ||
| | `input.auditResults` | `AuditSnapshot[]` | required | Audit results for correlation and issue aggregation | | ||
| | `input.trendData` | `TrendPoint[]` | `[]` | Optional time-series data for trend charts | | ||
| | `input.topN` | `number` | `10` | Number of top pages/queries to include | | ||
| | Parameter | Type | Default | Description | | ||
| | -------------------- | ----------------- | ------- | --------------------------------------------------- | | ||
| | `input.gscPages` | `GscPageData[]` | `[]` | GSC page performance data | | ||
| | `input.gscQueries` | `GscQueryData[]` | `[]` | GSC query performance data | | ||
| | `input.auditResults` | `AuditData[]` | `[]` | Audit results for correlation and issue aggregation | | ||
| | `input.auditHistory` | `AuditSnapshot[]` | `[]` | Audit history for trend analysis | | ||
| Returns `DashboardData`. | ||
| Returns `DashboardData`: aggregated overview, top pages/queries, trend lines per category, and recommended issues. | ||
@@ -447,15 +459,15 @@ --- | ||
| import type { | ||
| GscPageData, // { url, clicks, impressions, ctr, position } | ||
| GscQueryData, // { query, clicks, impressions, ctr, position } | ||
| AuditSnapshot, // { url, score, issues } | ||
| GscPageData, // { url, clicks, impressions, ctr, position, date? } | ||
| GscQueryData, // { query, clicks, impressions, ctr, position, date? } | ||
| AuditSnapshot, // { date, url, score, categories } | ||
| TrendPoint, // { date: string; value: number } | ||
| TrendDirection, // 'up' | 'down' | 'stable' | ||
| TrendAnalysis, // { direction, rate, confidence } | ||
| PageInsight, // Merged GscPageData + AuditSnapshot | ||
| RankingBucket, // '1-3' | '4-10' | '11-20' | '21-50' | '50+' | ||
| RankingAnalysis, // { buckets: Record<RankingBucket, GscQueryData[]>; totalQueries } | ||
| PositionChange, // { query, before?, after?, delta?, direction } | ||
| DashboardInput, // { gscPages, gscQueries, auditResults, trendData?, topN? } | ||
| DashboardOverview, // { totalClicks, totalImpressions, averageCtr, averagePosition, averageAuditScore, pagesWithErrors } | ||
| DashboardData, // { overview, topPages, topQueries, trendLines, issues } | ||
| TrendDirection, // 'improving' | 'declining' | 'stable' | ||
| TrendAnalysis, // { metric, trend, change, points } | ||
| PageInsight, // { url, gscMetrics?, auditScore?, auditCategories?, opportunities } | ||
| RankingBucket, // { range: string; count: number; queries: GscQueryData[] } | ||
| RankingAnalysis, // { totalQueries, buckets: RankingBucket[], strikingDistance } | ||
| PositionChange, // { query, previousPosition, currentPosition, change, impressionChange } | ||
| DashboardInput, // { gscPages?, gscQueries?, auditResults?, auditHistory? } | ||
| DashboardOverview, // { totalClicks, totalImpressions, averageCtr, averagePosition, averageAuditScore, totalPages } | ||
| DashboardData, // { overview, topPages, topQueries, trendLines: Record<string, TrendAnalysis>, issues: string[] } | ||
| } from '@power-seo/analytics'; | ||
@@ -493,3 +505,2 @@ ``` | ||
| - No `eval` or dynamic code execution | ||
| - npm provenance enabled — every release is signed via Sigstore through GitHub Actions | ||
| - CI-signed builds — all releases published via verified `github.com/CyberCraftBD/power-seo` workflow | ||
@@ -509,3 +520,3 @@ - Safe for SSR, Edge, and server environments | ||
| | [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta) | `npm i @power-seo/meta` | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR | | ||
| | [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 23 builders + 21 React components | | ||
| | [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 23 builders + 22 React components | | ||
| | [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components | | ||
@@ -527,8 +538,2 @@ | [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability) | `npm i @power-seo/readability` | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI | | ||
| ## Keywords | ||
| seo · analytics · gsc · google search console · trends · rankings · dashboard · position tracking · click through rate · impressions · seo insights · anomaly detection · traffic trends · nextjs · pearson correlation · seo reporting · ranking analysis · seo data · typescript · seo pipeline | ||
| --- | ||
| ## About [CyberCraft Bangladesh](https://ccbd.dev) | ||
@@ -535,0 +540,0 @@ |
94225
1.4%524
0.96%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated