@dracoonghost/trndup-sdk 1.3.17 → 1.3.19

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/index.d.ts CHANGED
@@ -594,6 +594,523 @@ declare namespace Insights {
594
594
  /** Max number of data points (default: 30, max: 90) */
595
595
  limit?: number;
596
596
  }
597
+ /**
598
+ * How we calculated this insight - shown to user for transparency
599
+ */
600
+ interface CalculationExplanation {
601
+ /** Short description of the methodology */
602
+ method: string;
603
+ /** Time range analyzed */
604
+ timeRange: string;
605
+ /** Key factors that influenced the result */
606
+ factors: string[];
607
+ /** Data quality/reliability indicator */
608
+ dataQuality: 'high' | 'medium' | 'low';
609
+ /** Why data quality might be limited */
610
+ dataQualityNote?: string;
611
+ }
612
+ /**
613
+ * Common metadata for all insights
614
+ */
615
+ interface InsightMeta {
616
+ /** When this insight was calculated */
617
+ calculatedAt: string;
618
+ /** When this insight expires (should be recalculated) */
619
+ validUntil: string;
620
+ /** Algorithm version for tracking changes */
621
+ algorithmVersion: string;
622
+ /** Whether result came from cache */
623
+ fromCache: boolean;
624
+ /** How this was calculated (for transparency) */
625
+ howWeCalculatedThis: CalculationExplanation;
626
+ }
627
+ /**
628
+ * Response when there's not enough data for an insight
629
+ */
630
+ interface InsufficientDataResponse {
631
+ hasData: false;
632
+ reason: string;
633
+ minimumRequired: string;
634
+ currentAmount: string;
635
+ suggestion: string;
636
+ }
637
+ interface TopVideoData {
638
+ videoId: string;
639
+ title: string;
640
+ thumbnailUrl: string | null;
641
+ publishedAt: string;
642
+ /** Link to watch on YouTube */
643
+ watchUrl: string;
644
+ }
645
+ interface TopVideoMetrics {
646
+ views: number;
647
+ likes: number;
648
+ comments: number;
649
+ estimatedMinutesWatched: number;
650
+ engagementRate: number;
651
+ }
652
+ interface TopVideoComparison {
653
+ /** Performance vs user's average video */
654
+ vsChannelAverage: {
655
+ views: number;
656
+ engagement: number;
657
+ description: string;
658
+ };
659
+ /** Why this video performed well */
660
+ standoutReasons: string[];
661
+ }
662
+ interface BestPerformingVideoData {
663
+ /** Time range analyzed */
664
+ period: {
665
+ start: string;
666
+ end: string;
667
+ days: number;
668
+ };
669
+ /** The top performing video */
670
+ topVideo: TopVideoData;
671
+ /** Video's metrics for this period */
672
+ metrics: TopVideoMetrics;
673
+ /** How it compares to your other content */
674
+ comparison: TopVideoComparison;
675
+ /** Human-readable summary */
676
+ insight: string;
677
+ /** Runner-up videos (for context) */
678
+ runnersUp: Array<{
679
+ videoId: string;
680
+ title: string;
681
+ views: number;
682
+ thumbnailUrl: string | null;
683
+ }>;
684
+ }
685
+ type BestPerformingVideoResponse = (InsufficientDataResponse) | {
686
+ hasData: true;
687
+ data: BestPerformingVideoData;
688
+ _meta: InsightMeta;
689
+ };
690
+ interface DecayingVideo {
691
+ videoId: string;
692
+ title: string;
693
+ thumbnailUrl: string | null;
694
+ publishedAt: string;
695
+ watchUrl: string;
696
+ /** Age of video in days */
697
+ ageInDays: number;
698
+ /** Views in current period */
699
+ currentViews: number;
700
+ /** Views in previous period */
701
+ previousViews: number;
702
+ /** Decay rate as percentage (negative = declining) */
703
+ decayRate: number;
704
+ /** Severity of decay */
705
+ severity: 'severe' | 'moderate' | 'mild';
706
+ /** Actionable suggestion */
707
+ suggestion: string;
708
+ }
709
+ interface ContentDecayData {
710
+ /** Time range analyzed */
711
+ period: {
712
+ current: {
713
+ start: string;
714
+ end: string;
715
+ };
716
+ previous: {
717
+ start: string;
718
+ end: string;
719
+ };
720
+ days: number;
721
+ };
722
+ /** Number of videos analyzed */
723
+ videosAnalyzed: number;
724
+ /** Videos experiencing significant decay */
725
+ decayingVideos: DecayingVideo[];
726
+ /** Summary stats */
727
+ summary: {
728
+ totalDecaying: number;
729
+ severeCount: number;
730
+ moderateCount: number;
731
+ mildCount: number;
732
+ /** Combined view loss from all decaying videos */
733
+ totalViewsLost: number;
734
+ };
735
+ /** Human-readable summary */
736
+ insight: string;
737
+ /** What content decay means */
738
+ whatThisMeans: string;
739
+ }
740
+ type ContentDecayResponse = (InsufficientDataResponse) | {
741
+ hasData: true;
742
+ data: ContentDecayData;
743
+ _meta: InsightMeta;
744
+ };
745
+ interface DayPerformance {
746
+ day: string;
747
+ avgFirstDayViews: number;
748
+ avgEngagement: number;
749
+ videoCount: number;
750
+ /** Confidence in this data */
751
+ confidence: 'high' | 'medium' | 'low';
752
+ }
753
+ interface TimeSlotPerformance {
754
+ slot: string;
755
+ label: string;
756
+ avgFirstDayViews: number;
757
+ videoCount: number;
758
+ confidence: 'high' | 'medium' | 'low';
759
+ }
760
+ interface AudienceActivityData {
761
+ /** How many videos were analyzed */
762
+ videosAnalyzed: number;
763
+ /** Day when your audience is most active */
764
+ mostActiveDay: {
765
+ day: string;
766
+ confidence: 'high' | 'medium' | 'low';
767
+ /** Why this day shows highest activity */
768
+ reason: string;
769
+ };
770
+ /** Time slot when your audience is most active */
771
+ mostActiveTimeSlot: {
772
+ slot: string;
773
+ label: string;
774
+ confidence: 'high' | 'medium' | 'low';
775
+ reason: string;
776
+ };
777
+ /** Full breakdown by day */
778
+ dayBreakdown: DayPerformance[];
779
+ /** Full breakdown by time slot (if enough data) */
780
+ timeBreakdown: TimeSlotPerformance[] | null;
781
+ /** Human-readable summary */
782
+ insight: string;
783
+ /** Disclaimer about the data */
784
+ disclaimer: string;
785
+ }
786
+ type AudienceActivityResponse = (InsufficientDataResponse) | {
787
+ hasData: true;
788
+ data: AudienceActivityData;
789
+ _meta: InsightMeta;
790
+ };
791
+ /** @deprecated Use AudienceActivityData instead */
792
+ type BestUploadTimeData = AudienceActivityData;
793
+ /** @deprecated Use AudienceActivityResponse instead */
794
+ type BestUploadTimeResponse = AudienceActivityResponse;
795
+ interface FadingHitVideo {
796
+ videoId: string;
797
+ title: string;
798
+ thumbnailUrl: string | null;
799
+ publishedAt: string;
800
+ watchUrl: string;
801
+ /** How old the video is in days */
802
+ ageInDays: number;
803
+ /** Performance during peak period (actual peak, not just first 14 days) */
804
+ peakPerformance: {
805
+ /** Average daily views during peak window */
806
+ dailyViews: number;
807
+ /** Comparison to channel average (e.g., "45% above average") */
808
+ vsChannelAverage: string;
809
+ /** Was this a top performer (2x+ channel average)? */
810
+ wasTopPerformer: boolean;
811
+ /** When the actual peak occurred */
812
+ peakPeriod: {
813
+ start: string;
814
+ end: string;
815
+ /** How many days after upload the peak occurred */
816
+ daysAfterUpload: number;
817
+ /** True if video went viral later (not at launch) - delayed virality */
818
+ wasDelayedViral: boolean;
819
+ };
820
+ };
821
+ /** Performance in recent period (last 14 days) */
822
+ currentPerformance: {
823
+ /** Current average daily views */
824
+ dailyViews: number;
825
+ /** Percentage decline from peak (negative number) */
826
+ declineFromPeak: number;
827
+ };
828
+ /** How likely revival efforts would work */
829
+ revivalPotential: 'high' | 'medium' | 'low';
830
+ /** Why this video might be worth reviving */
831
+ whyRevive: string;
832
+ /** Specific suggestions to revive this video */
833
+ suggestions: string[];
834
+ }
835
+ interface FadingHitsData {
836
+ /** Time period for "current" performance check */
837
+ period: {
838
+ current: {
839
+ start: string;
840
+ end: string;
841
+ };
842
+ label: string;
843
+ };
844
+ /** Number of videos analyzed */
845
+ videosAnalyzed: number;
846
+ /** Videos that were performing above average but are now declining */
847
+ fadingHits: FadingHitVideo[];
848
+ /** Summary stats */
849
+ summary: {
850
+ totalFading: number;
851
+ highPotentialCount: number;
852
+ mediumPotentialCount: number;
853
+ lowPotentialCount: number;
854
+ /** Combined daily views being lost */
855
+ totalDailyViewsLost: number;
856
+ };
857
+ /** Human-readable summary */
858
+ insight: string;
859
+ /** What fading hits means */
860
+ whatThisMeans: string;
861
+ }
862
+ type FadingHitsResponse = (InsufficientDataResponse) | {
863
+ hasData: true;
864
+ data: FadingHitsData;
865
+ _meta: InsightMeta;
866
+ };
867
+ type SubscriberQualityLabel = 'excellent' | 'good' | 'fair' | 'needs_attention' | 'concerning';
868
+ interface SubscriberQualityData {
869
+ /** Time range analyzed */
870
+ period: {
871
+ start: string;
872
+ end: string;
873
+ days: number;
874
+ };
875
+ /** Overall quality score (0-100) */
876
+ qualityScore: number;
877
+ /** Score interpretation */
878
+ scoreLabel: SubscriberQualityLabel;
879
+ /** Core metrics */
880
+ metrics: {
881
+ /** Total subscribers gained */
882
+ subscribersGained: number;
883
+ /** Total subscribers lost */
884
+ subscribersLost: number;
885
+ /** Net subscriber change */
886
+ netSubscribers: number;
887
+ /** Retention rate (how many stay) */
888
+ retentionRate: number;
889
+ /** Average watch time per view */
890
+ avgWatchTimeMinutes: number;
891
+ /** Views per subscriber (engagement proxy) */
892
+ viewsPerSubscriber: number;
893
+ };
894
+ /** Comparison to previous period */
895
+ trend: {
896
+ scoreChange: number;
897
+ direction: 'improving' | 'stable' | 'declining';
898
+ description: string;
899
+ };
900
+ /** Human-readable summary */
901
+ insight: string;
902
+ /** Specific recommendations */
903
+ recommendations: string[];
904
+ }
905
+ type SubscriberQualityResponse = (InsufficientDataResponse) | {
906
+ hasData: true;
907
+ data: SubscriberQualityData;
908
+ _meta: InsightMeta;
909
+ };
910
+ type FatigueLevel = 'none' | 'low' | 'moderate' | 'high' | 'critical';
911
+ interface FatigueSignal {
912
+ /** Name of the signal */
913
+ name: string;
914
+ /** Current period value */
915
+ current: number;
916
+ /** Previous period value */
917
+ previous: number;
918
+ /** Change percentage (negative = declining) */
919
+ changePercent: number;
920
+ /** Whether this signal indicates fatigue */
921
+ indicatesFatigue: boolean;
922
+ /** Description of what this means */
923
+ interpretation: string;
924
+ }
925
+ interface AudienceFatigueData {
926
+ /** Time periods compared */
927
+ period: {
928
+ current: {
929
+ start: string;
930
+ end: string;
931
+ };
932
+ previous: {
933
+ start: string;
934
+ end: string;
935
+ };
936
+ daysPerPeriod: number;
937
+ };
938
+ /** Overall fatigue index (0-100, higher = more fatigue) */
939
+ fatigueIndex: number;
940
+ /** Human-readable fatigue level */
941
+ fatigueLevel: FatigueLevel;
942
+ /** Individual signals that contribute to the score */
943
+ signals: {
944
+ watchTimePerView: FatigueSignal;
945
+ engagementRate: FatigueSignal;
946
+ subscriberChurn: FatigueSignal;
947
+ viewsPerVideo: FatigueSignal;
948
+ };
949
+ /** Summary of signals */
950
+ summary: {
951
+ signalsIndicatingFatigue: number;
952
+ totalSignals: number;
953
+ primaryConcern: string | null;
954
+ };
955
+ /** Human-readable insight */
956
+ insight: string;
957
+ /** What to do about it */
958
+ recommendations: string[];
959
+ }
960
+ type AudienceFatigueResponse = (InsufficientDataResponse) | {
961
+ hasData: true;
962
+ data: AudienceFatigueData;
963
+ _meta: InsightMeta;
964
+ };
965
+ interface LengthBucketPerformance {
966
+ /** Bucket name (e.g., "5-10 minutes") */
967
+ bucket: string;
968
+ /** Bucket range in seconds */
969
+ range: {
970
+ min: number;
971
+ max: number | null;
972
+ };
973
+ /** Number of videos in this bucket */
974
+ videoCount: number;
975
+ /** Average retention as percentage */
976
+ avgRetention: number;
977
+ /** Average engagement rate */
978
+ avgEngagement: number;
979
+ /** Average views per video */
980
+ avgViews: number;
981
+ /** Combined performance score (0-100) */
982
+ performanceScore: number;
983
+ /** Is this the optimal bucket? */
984
+ isOptimal: boolean;
985
+ }
986
+ interface OptimalVideoLengthData {
987
+ /** How many videos were analyzed */
988
+ videosAnalyzed: number;
989
+ /** The recommended optimal length range */
990
+ optimalLength: {
991
+ bucket: string;
992
+ range: {
993
+ min: number;
994
+ max: number | null;
995
+ };
996
+ confidence: 'high' | 'medium' | 'low';
997
+ reason: string;
998
+ };
999
+ /** Performance breakdown by length bucket */
1000
+ breakdown: LengthBucketPerformance[];
1001
+ /** Key findings */
1002
+ findings: {
1003
+ bestRetention: {
1004
+ bucket: string;
1005
+ value: number;
1006
+ };
1007
+ bestEngagement: {
1008
+ bucket: string;
1009
+ value: number;
1010
+ };
1011
+ mostCommon: {
1012
+ bucket: string;
1013
+ count: number;
1014
+ };
1015
+ };
1016
+ /** Human-readable insight */
1017
+ insight: string;
1018
+ /** Specific recommendations */
1019
+ recommendations: string[];
1020
+ }
1021
+ type OptimalVideoLengthResponse = (InsufficientDataResponse) | {
1022
+ hasData: true;
1023
+ data: OptimalVideoLengthData;
1024
+ _meta: InsightMeta;
1025
+ };
1026
+ /** Consistency status levels */
1027
+ type ConsistencyStatus = 'excellent' | 'good' | 'needs_improvement' | 'poor' | 'inactive';
1028
+ /** Monthly upload breakdown */
1029
+ interface MonthlyUploadData {
1030
+ month: string;
1031
+ uploads: number;
1032
+ avgGap: number | null;
1033
+ }
1034
+ /** Upload consistency insight data */
1035
+ interface UploadConsistencyData {
1036
+ /** Period analyzed */
1037
+ period: {
1038
+ start: string;
1039
+ end: string;
1040
+ days: number;
1041
+ };
1042
+ /** Overall consistency score (0-100) */
1043
+ consistencyScore: number;
1044
+ /** Status label */
1045
+ status: ConsistencyStatus;
1046
+ /** Key metrics */
1047
+ metrics: {
1048
+ totalUploads: number;
1049
+ avgDaysBetweenUploads: number;
1050
+ uploadVariance: number;
1051
+ daysSinceLastUpload: number;
1052
+ lastUploadDate: string | null;
1053
+ };
1054
+ /** Upload pattern analysis */
1055
+ pattern: {
1056
+ isRegular: boolean;
1057
+ typicalGap: string;
1058
+ longestStreak: number;
1059
+ currentStreak: number;
1060
+ trend: 'increasing' | 'stable' | 'decreasing';
1061
+ trendDescription: string;
1062
+ };
1063
+ /** Monthly breakdown */
1064
+ monthlyBreakdown: MonthlyUploadData[];
1065
+ /** Frequency recommendation */
1066
+ recommendation: {
1067
+ suggested: string;
1068
+ current: string;
1069
+ reason: string;
1070
+ };
1071
+ /** Human-readable summary */
1072
+ insight: string;
1073
+ /** Actionable recommendations */
1074
+ recommendations: string[];
1075
+ }
1076
+ type UploadConsistencyResponse = (InsufficientDataResponse) | {
1077
+ hasData: true;
1078
+ data: UploadConsistencyData;
1079
+ _meta: InsightMeta;
1080
+ };
1081
+ interface AllInsightsData {
1082
+ bestPerformingVideo: BestPerformingVideoResponse;
1083
+ contentDecay: ContentDecayResponse;
1084
+ audienceActivity: AudienceActivityResponse;
1085
+ subscriberQuality: SubscriberQualityResponse;
1086
+ fadingHits: FadingHitsResponse;
1087
+ audienceFatigue: AudienceFatigueResponse;
1088
+ optimalLength: OptimalVideoLengthResponse;
1089
+ uploadConsistency: UploadConsistencyResponse;
1090
+ }
1091
+ interface AllInsightsResponse {
1092
+ data: AllInsightsData;
1093
+ _meta: {
1094
+ calculatedAt: string;
1095
+ insightsAvailable: string[];
1096
+ };
1097
+ }
1098
+ interface GetBestVideoParams {
1099
+ /** Number of days to analyze (1-90, default: 30) */
1100
+ period?: number;
1101
+ }
1102
+ interface GetContentDecayParams {
1103
+ /** Days per comparison period (3-14, default: 7) */
1104
+ period?: number;
1105
+ }
1106
+ interface GetSubscriberQualityParams {
1107
+ /** Number of days to analyze (14-180, default: 90) */
1108
+ period?: number;
1109
+ }
1110
+ interface GetAudienceFatigueParams {
1111
+ /** Days per comparison period (14-90, default: 30) */
1112
+ period?: number;
1113
+ }
597
1114
  }
598
1115
  declare namespace Activity {
599
1116
  /**
@@ -1092,6 +1609,278 @@ declare class InsightsModule {
1092
1609
  * GET /v1/insights/youtube/momentum/history
1093
1610
  */
1094
1611
  getYouTubeMomentumHistory(params?: Insights.GetMomentumHistoryParams): Promise<Insights.MomentumHistoryResponse>;
1612
+ /**
1613
+ * Get the best performing video in a time period
1614
+ *
1615
+ * Identifies your top video by views and explains WHY it performed well.
1616
+ *
1617
+ * @param params - Query parameters
1618
+ * @param params.period - Days to analyze (1-90, default: 30)
1619
+ *
1620
+ * @example
1621
+ * ```typescript
1622
+ * const result = await client.insights.getYouTubeBestVideo({ period: 30 });
1623
+ *
1624
+ * if (result.hasData) {
1625
+ * console.log(`🏆 ${result.data.topVideo.title}`);
1626
+ * console.log(`Views: ${result.data.metrics.views}`);
1627
+ * console.log(`${result.data.comparison.vsChannelAverage.description}`);
1628
+ * console.log(result.data.insight);
1629
+ *
1630
+ * // Show how it was calculated
1631
+ * console.log(result._meta.howWeCalculatedThis.method);
1632
+ * } else {
1633
+ * console.log(result.suggestion);
1634
+ * }
1635
+ * ```
1636
+ *
1637
+ * GET /v1/insights/youtube/best-video
1638
+ */
1639
+ getYouTubeBestVideo(params?: Insights.GetBestVideoParams): Promise<Insights.BestPerformingVideoResponse>;
1640
+ /**
1641
+ * Find videos that are losing momentum
1642
+ *
1643
+ * Compares current period vs previous period to identify declining videos.
1644
+ * Provides actionable suggestions for each decaying video.
1645
+ *
1646
+ * @param params - Query parameters
1647
+ * @param params.period - Days per comparison period (3-14, default: 7)
1648
+ *
1649
+ * @example
1650
+ * ```typescript
1651
+ * const result = await client.insights.getYouTubeContentDecay({ period: 7 });
1652
+ *
1653
+ * if (result.hasData) {
1654
+ * console.log(result.data.insight);
1655
+ * console.log(`${result.data.summary.totalDecaying} videos declining`);
1656
+ *
1657
+ * for (const video of result.data.decayingVideos) {
1658
+ * console.log(`📉 ${video.title}: ${video.decayRate}%`);
1659
+ * console.log(` ${video.suggestion}`);
1660
+ * }
1661
+ * }
1662
+ * ```
1663
+ *
1664
+ * GET /v1/insights/youtube/content-decay
1665
+ */
1666
+ getYouTubeContentDecay(params?: Insights.GetContentDecayParams): Promise<Insights.ContentDecayResponse>;
1667
+ /**
1668
+ * Get when your audience is most active
1669
+ *
1670
+ * Unlike generic advice, this is based on YOUR audience's behavior.
1671
+ * Analyzes first-day performance by publish day and time to identify
1672
+ * when your audience is most engaged.
1673
+ *
1674
+ * @example
1675
+ * ```typescript
1676
+ * const result = await client.insights.getYouTubeAudienceActivity();
1677
+ *
1678
+ * if (result.hasData) {
1679
+ * console.log(`📅 Most active day: ${result.data.mostActiveDay.day}`);
1680
+ * console.log(`⏰ Peak time: ${result.data.mostActiveTimeSlot.label}`);
1681
+ * console.log(result.data.insight);
1682
+ *
1683
+ * // Show day breakdown
1684
+ * for (const day of result.data.dayBreakdown) {
1685
+ * console.log(`${day.day}: ${day.avgFirstDayViews} avg views`);
1686
+ * }
1687
+ * }
1688
+ * ```
1689
+ *
1690
+ * GET /v1/insights/youtube/audience-activity
1691
+ */
1692
+ getYouTubeAudienceActivity(): Promise<Insights.AudienceActivityResponse>;
1693
+ /**
1694
+ * @deprecated Use `getYouTubeAudienceActivity()` instead
1695
+ */
1696
+ getYouTubeBestUploadTime(): Promise<Insights.BestUploadTimeResponse>;
1697
+ /**
1698
+ * Find videos that were hits but are now declining
1699
+ *
1700
+ * Identifies videos that performed above your channel average initially
1701
+ * but have since lost momentum. These are revival opportunities.
1702
+ *
1703
+ * @example
1704
+ * ```typescript
1705
+ * const result = await client.insights.getYouTubeFadingHits();
1706
+ *
1707
+ * if (result.hasData) {
1708
+ * console.log(result.data.insight);
1709
+ * console.log(`${result.data.summary.totalFading} videos could use a boost`);
1710
+ *
1711
+ * for (const video of result.data.fadingHits) {
1712
+ * console.log(`📉 ${video.title}`);
1713
+ * console.log(` Peak: ${video.peakPeriod.avgDailyViews} views/day`);
1714
+ * console.log(` Now: ${video.currentPeriod.avgDailyViews} views/day`);
1715
+ * console.log(` Decline: ${video.decline.percentage}%`);
1716
+ * console.log(` Revival potential: ${video.revivalPotential}`);
1717
+ * console.log(` ${video.whyRevive}`);
1718
+ * for (const suggestion of video.suggestions) {
1719
+ * console.log(` 💡 ${suggestion}`);
1720
+ * }
1721
+ * }
1722
+ * }
1723
+ * ```
1724
+ *
1725
+ * GET /v1/insights/youtube/fading-hits
1726
+ */
1727
+ getYouTubeFadingHits(): Promise<Insights.FadingHitsResponse>;
1728
+ /**
1729
+ * Measure subscriber quality score (0-100)
1730
+ *
1731
+ * Analyzes whether new subscribers are engaged or just numbers.
1732
+ * Helps identify fake growth or low-quality audiences.
1733
+ *
1734
+ * @param params - Query parameters
1735
+ * @param params.period - Days to analyze (7-90, default: 30)
1736
+ *
1737
+ * @example
1738
+ * ```typescript
1739
+ * const result = await client.insights.getYouTubeSubscriberQuality({ period: 90 });
1740
+ *
1741
+ * if (result.hasData) {
1742
+ * console.log(`Quality Score: ${result.data.qualityScore}/100 (${result.data.scoreLabel})`);
1743
+ * console.log(`Retention: ${result.data.metrics.retentionRate}%`);
1744
+ * console.log(result.data.insight);
1745
+ *
1746
+ * // Show recommendations
1747
+ * for (const rec of result.data.recommendations) {
1748
+ * console.log(`💡 ${rec}`);
1749
+ * }
1750
+ * }
1751
+ * ```
1752
+ *
1753
+ * GET /v1/insights/youtube/subscriber-quality
1754
+ */
1755
+ getYouTubeSubscriberQuality(params?: Insights.GetSubscriberQualityParams): Promise<Insights.SubscriberQualityResponse>;
1756
+ /**
1757
+ * Detect if your audience is getting tired of your content
1758
+ *
1759
+ * Compares key engagement metrics between recent and previous periods
1760
+ * to identify declining audience interest before it becomes critical.
1761
+ *
1762
+ * @param params - Query parameters
1763
+ * @param params.period - Days per comparison period (14-90, default: 30)
1764
+ *
1765
+ * @example
1766
+ * ```typescript
1767
+ * const result = await client.insights.getYouTubeAudienceFatigue({ period: 30 });
1768
+ *
1769
+ * if (result.hasData) {
1770
+ * console.log(`Fatigue Index: ${result.data.fatigueIndex}/100`);
1771
+ * console.log(`Level: ${result.data.fatigueLevel}`);
1772
+ * console.log(result.data.insight);
1773
+ *
1774
+ * // Check individual signals
1775
+ * if (result.data.signals.watchTimePerView.indicatesFatigue) {
1776
+ * console.log('⚠️ Watch time is declining');
1777
+ * }
1778
+ *
1779
+ * // Get recommendations
1780
+ * for (const rec of result.data.recommendations) {
1781
+ * console.log(`💡 ${rec}`);
1782
+ * }
1783
+ * }
1784
+ * ```
1785
+ *
1786
+ * GET /v1/insights/youtube/audience-fatigue
1787
+ */
1788
+ getYouTubeAudienceFatigue(params?: Insights.GetAudienceFatigueParams): Promise<Insights.AudienceFatigueResponse>;
1789
+ /**
1790
+ * Find the ideal video length for YOUR audience
1791
+ *
1792
+ * Unlike generic "8-12 minutes is best" advice, this is personalized
1793
+ * based on how YOUR videos perform at different lengths.
1794
+ *
1795
+ * @example
1796
+ * ```typescript
1797
+ * const result = await client.insights.getYouTubeOptimalLength();
1798
+ *
1799
+ * if (result.hasData) {
1800
+ * console.log(`Optimal: ${result.data.optimalLength.bucket}`);
1801
+ * console.log(`Confidence: ${result.data.optimalLength.confidence}`);
1802
+ * console.log(result.data.insight);
1803
+ *
1804
+ * // Show breakdown by length
1805
+ * for (const bucket of result.data.breakdown) {
1806
+ * const marker = bucket.isOptimal ? '🏆' : ' ';
1807
+ * console.log(`${marker} ${bucket.bucket}: ${bucket.avgRetention}% retention, ${bucket.avgEngagement}% engagement`);
1808
+ * }
1809
+ *
1810
+ * // Recommendations
1811
+ * for (const rec of result.data.recommendations) {
1812
+ * console.log(`💡 ${rec}`);
1813
+ * }
1814
+ * }
1815
+ * ```
1816
+ *
1817
+ * GET /v1/insights/youtube/optimal-length
1818
+ */
1819
+ getYouTubeOptimalLength(): Promise<Insights.OptimalVideoLengthResponse>;
1820
+ /**
1821
+ * Analyze your upload schedule consistency
1822
+ *
1823
+ * Measures how regularly you upload and provides recommendations
1824
+ * for maintaining a consistent schedule that helps algorithm performance.
1825
+ *
1826
+ * @example
1827
+ * ```typescript
1828
+ * const result = await client.insights.getYouTubeUploadConsistency();
1829
+ *
1830
+ * if (result.hasData) {
1831
+ * console.log(`Consistency Score: ${result.data.consistencyScore}/100`);
1832
+ * console.log(`Status: ${result.data.status}`);
1833
+ * console.log(`Avg gap: ${result.data.metrics.avgDaysBetweenUploads} days`);
1834
+ * console.log(`Days since last upload: ${result.data.metrics.daysSinceLastUpload}`);
1835
+ *
1836
+ * // Pattern analysis
1837
+ * console.log(`Pattern: ${result.data.pattern.typicalGap}`);
1838
+ * console.log(`Trend: ${result.data.pattern.trendDescription}`);
1839
+ *
1840
+ * // Recommendation
1841
+ * console.log(`Current: ${result.data.recommendation.current}`);
1842
+ * console.log(`Suggested: ${result.data.recommendation.suggested}`);
1843
+ *
1844
+ * // Monthly breakdown
1845
+ * for (const month of result.data.monthlyBreakdown) {
1846
+ * console.log(`${month.month}: ${month.uploads} uploads`);
1847
+ * }
1848
+ * }
1849
+ * ```
1850
+ *
1851
+ * GET /v1/insights/youtube/upload-consistency
1852
+ */
1853
+ getYouTubeUploadConsistency(): Promise<Insights.UploadConsistencyResponse>;
1854
+ /**
1855
+ * Get all YouTube insights in one call
1856
+ *
1857
+ * Efficient for dashboard display - fetches all insights in parallel.
1858
+ * Each insight has `hasData: boolean` to check availability.
1859
+ *
1860
+ * @example
1861
+ * ```typescript
1862
+ * const all = await client.insights.getYouTubeAllInsights();
1863
+ *
1864
+ * // Check which insights are available
1865
+ * console.log('Available:', all._meta.insightsAvailable);
1866
+ *
1867
+ * // Use each insight
1868
+ * if (all.data.bestPerformingVideo.hasData) {
1869
+ * console.log(`Best: ${all.data.bestPerformingVideo.data.topVideo.title}`);
1870
+ * }
1871
+ *
1872
+ * if (all.data.audienceFatigue.hasData) {
1873
+ * console.log(`Fatigue: ${all.data.audienceFatigue.data.fatigueLevel}`);
1874
+ * }
1875
+ *
1876
+ * if (all.data.uploadConsistency.hasData) {
1877
+ * console.log(`Consistency: ${all.data.uploadConsistency.data.consistencyScore}/100`);
1878
+ * }
1879
+ * ```
1880
+ *
1881
+ * GET /v1/insights/youtube/all
1882
+ */
1883
+ getYouTubeAllInsights(): Promise<Insights.AllInsightsResponse>;
1095
1884
  }
1096
1885
 
1097
1886
  /**