@ken-e/dataform-youtube 0.0.2

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.
Files changed (55) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/README.md +4 -0
  3. package/eslint.config.js +11 -0
  4. package/includes/column_descriptions.js +95 -0
  5. package/includes/constants.js +5 -0
  6. package/includes/definitions/sources/stg_ytc_annotation.js +91 -0
  7. package/includes/definitions/sources/stg_ytc_basic.js +109 -0
  8. package/includes/definitions/sources/stg_ytc_cards.js +89 -0
  9. package/includes/definitions/sources/stg_ytc_combined.js +97 -0
  10. package/includes/definitions/sources/stg_ytc_demographics.js +84 -0
  11. package/includes/definitions/sources/stg_ytc_device_os.js +90 -0
  12. package/includes/definitions/sources/stg_ytc_end_screens.js +69 -0
  13. package/includes/definitions/sources/stg_ytc_list_basic.js +91 -0
  14. package/includes/definitions/sources/stg_ytc_list_combined.js +92 -0
  15. package/includes/definitions/sources/stg_ytc_list_device_os.js +90 -0
  16. package/includes/definitions/sources/stg_ytc_list_playback.js +89 -0
  17. package/includes/definitions/sources/stg_ytc_list_province.js +91 -0
  18. package/includes/definitions/sources/stg_ytc_list_traffic_source.js +89 -0
  19. package/includes/definitions/sources/stg_ytc_lu_annotation_type.js +37 -0
  20. package/includes/definitions/sources/stg_ytc_lu_card_type.js +35 -0
  21. package/includes/definitions/sources/stg_ytc_lu_device_types.js +33 -0
  22. package/includes/definitions/sources/stg_ytc_lu_end_screen_element_type.js +36 -0
  23. package/includes/definitions/sources/stg_ytc_lu_operating_systems.js +57 -0
  24. package/includes/definitions/sources/stg_ytc_lu_playback_location.js +34 -0
  25. package/includes/definitions/sources/stg_ytc_lu_sharing_services.js +94 -0
  26. package/includes/definitions/sources/stg_ytc_lu_traffic_sources.js +50 -0
  27. package/includes/definitions/sources/stg_ytc_playback.js +90 -0
  28. package/includes/definitions/sources/stg_ytc_province.js +103 -0
  29. package/includes/definitions/sources/stg_ytc_share_platform.js +82 -0
  30. package/includes/definitions/sources/stg_ytc_subtitles.js +89 -0
  31. package/includes/definitions/sources/stg_ytc_traffic_source.js +107 -0
  32. package/includes/definitions/ytc_annotation.js +65 -0
  33. package/includes/definitions/ytc_basic.js +74 -0
  34. package/includes/definitions/ytc_cards.js +66 -0
  35. package/includes/definitions/ytc_combined.js +113 -0
  36. package/includes/definitions/ytc_demographics.js +69 -0
  37. package/includes/definitions/ytc_demographics_views.js +80 -0
  38. package/includes/definitions/ytc_device_os.js +80 -0
  39. package/includes/definitions/ytc_end_screens.js +65 -0
  40. package/includes/definitions/ytc_list_basic.js +84 -0
  41. package/includes/definitions/ytc_list_combined.js +97 -0
  42. package/includes/definitions/ytc_list_device_os.js +90 -0
  43. package/includes/definitions/ytc_list_playback.js +86 -0
  44. package/includes/definitions/ytc_list_province.js +83 -0
  45. package/includes/definitions/ytc_list_traffic_source.js +91 -0
  46. package/includes/definitions/ytc_playback.js +73 -0
  47. package/includes/definitions/ytc_province.js +71 -0
  48. package/includes/definitions/ytc_share_platform.js +76 -0
  49. package/includes/definitions/ytc_subtitles.js +69 -0
  50. package/includes/definitions/ytc_traffic_source.js +73 -0
  51. package/includes/helpers.js +8 -0
  52. package/includes/project_variables.js +15 -0
  53. package/index.js +312 -0
  54. package/package.json +30 -0
  55. package/prettier.config.js +14 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_end_screens", {
8
+ type: "incremental",
9
+ database: config.target.database,
10
+ schema: config.datasetStaging,
11
+ protected: config.protected,
12
+ tags: ["youtube", "source", "staging", "daily"],
13
+ bigquery: {
14
+ partitionBy: "interaction_date",
15
+ clusterBy: ["video_id", "end_screen_element_type"],
16
+ },
17
+ description: "Staging table for YouTube Channel End Screen data",
18
+ })
19
+ .preOps(
20
+ (ctx) => `
21
+ declare source_date_checkpoint default (
22
+ select date("${config.startDate}")
23
+ );
24
+
25
+ --Set the incremental update checkpoint based on current max partition value minus lookback.
26
+ set source_date_checkpoint = (
27
+ ${ctx.when(
28
+ ctx.incremental(),
29
+ `select
30
+ least(
31
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
32
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
33
+ )`,
34
+ `select date("${config.startDate}")`,
35
+ )}
36
+ );
37
+
38
+ ${ctx.when(
39
+ ctx.incremental(),
40
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
41
+ )}
42
+ `,
43
+ )
44
+ .query((ctx) =>
45
+ config.sources
46
+ .map((t) => {
47
+ return `
48
+ select
49
+ _PARTITIONDATE as source_partition_date,
50
+ parse_date('%Y%m%d', date) as interaction_date,
51
+ "${t.schema}" as site_nm,
52
+ current_timestamp() as updated_at,
53
+ channel_id,
54
+ video_id,
55
+ live_or_on_demand,
56
+ subscribed_status,
57
+ country_code,
58
+ end_screen_element_type,
59
+ end_screen_element_id,
60
+ end_screen_element_click_rate,
61
+ end_screen_element_impressions,
62
+ end_screen_element_clicks
63
+ from ${ctx.ref(t.database, t.schema, "p_channel_end_screens_a1_" + t.suffix)}
64
+ where _PARTITIONDATE > source_date_checkpoint
65
+ `;
66
+ })
67
+ .join(" union all "),
68
+ );
69
+ };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ const column_descriptions = require("../../column_descriptions");
6
+
7
+ module.exports = (config) => {
8
+ // eslint-disable-next-line no-undef
9
+ return publish("stg_ytc_list_basic", {
10
+ type: "incremental",
11
+ database: config.target.database,
12
+ schema: config.datasetStaging,
13
+ protected: config.protected,
14
+ tags: ["youtube", "source", "staging", "daily"],
15
+ bigquery: {
16
+ partitionBy: "interaction_date",
17
+ clusterBy: ["playlist_id", "video_id"],
18
+ },
19
+ assertions: {
20
+ // make sure rows have unique dimensions
21
+ uniqueKeys: [
22
+ [
23
+ "interaction_date",
24
+ "channel_id",
25
+ "playlist_id",
26
+ "video_id",
27
+ "live_or_on_demand",
28
+ "subscribed_status",
29
+ "country_code",
30
+ ],
31
+ ],
32
+ // make sure source partition and data dates match
33
+ rowConditions: ["interaction_date = source_partition_date"],
34
+ },
35
+ columns: column_descriptions.column_descriptions,
36
+ description: "YT Channel Playlist Basic Report Table - Staging",
37
+ })
38
+ .preOps(
39
+ (ctx) => `
40
+ declare source_date_checkpoint default (
41
+ select date("${config.startDate}")
42
+ );
43
+
44
+ --Set the incremental update checkpoint based on current max partition value minus lookback.
45
+ set source_date_checkpoint = (
46
+ ${ctx.when(
47
+ ctx.incremental(),
48
+ `select
49
+ least(
50
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
51
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
52
+ )`,
53
+ `select date("${config.startDate}")`,
54
+ )}
55
+ );
56
+
57
+ ${ctx.when(
58
+ ctx.incremental(),
59
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
60
+ )}
61
+ `,
62
+ )
63
+ .query((ctx) =>
64
+ config.sources
65
+ .map((t) => {
66
+ return `
67
+
68
+ select
69
+ _PARTITIONDATE as source_partition_date,
70
+ parse_date('%Y%m%d',date) as interaction_date,
71
+ "${t.schema}" as site_nm,
72
+ current_timestamp() as updated_at,
73
+ channel_id,
74
+ playlist_id,
75
+ video_id,
76
+ live_or_on_demand,
77
+ subscribed_status,
78
+ country_code,
79
+ views,
80
+ watch_time_minutes,
81
+ average_view_duration_seconds,
82
+ playlist_starts,
83
+ playlist_saves_added,
84
+ playlist_saves_removed
85
+ from ${ctx.ref(t.database, t.schema, "p_playlist_basic_a1_" + t.suffix)}
86
+ where _PARTITIONDATE > source_date_checkpoint
87
+ `;
88
+ })
89
+ .join(" union all "),
90
+ );
91
+ };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_list_combined", {
8
+ type: "incremental",
9
+ database: config.target.database,
10
+ schema: config.datasetStaging,
11
+ protected: config.protected,
12
+ tags: ["youtube", "source", "staging", "daily"],
13
+ bigquery: {
14
+ partitionBy: "interaction_date",
15
+ clusterBy: ["playlist_id", "video_id", "device_type", "operating_system"],
16
+ },
17
+ assertions: {
18
+ uniqueKeys: [
19
+ [
20
+ "interaction_date",
21
+ "channel_id",
22
+ "playlist_id",
23
+ "video_id",
24
+ "live_or_on_demand",
25
+ "subscribed_status",
26
+ "country_code",
27
+ "playback_location_type",
28
+ "traffic_source_type",
29
+ "device_type",
30
+ "operating_system",
31
+ ],
32
+ ],
33
+ rowConditions: ["interaction_date = source_partition_date"],
34
+ },
35
+ description: "Staging table for YouTube Channel Playlist Combined data",
36
+ })
37
+ .preOps(
38
+ (ctx) => `
39
+ declare source_date_checkpoint default (
40
+ select date("${config.startDate}")
41
+ );
42
+
43
+ set source_date_checkpoint = (
44
+ ${ctx.when(
45
+ ctx.incremental(),
46
+ `select
47
+ least(
48
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
49
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
50
+ )`,
51
+ `select date("${config.startDate}")`,
52
+ )}
53
+ );
54
+
55
+ ${ctx.when(
56
+ ctx.incremental(),
57
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
58
+ )}
59
+ `,
60
+ )
61
+ .query((ctx) =>
62
+ config.sources
63
+ .map((t) => {
64
+ return `
65
+ select
66
+ _PARTITIONDATE as source_partition_date,
67
+ parse_date('%Y%m%d', date) as interaction_date,
68
+ "${t.schema}" as site_nm,
69
+ current_timestamp() as updated_at,
70
+ channel_id,
71
+ playlist_id,
72
+ video_id,
73
+ live_or_on_demand,
74
+ subscribed_status,
75
+ country_code,
76
+ playback_location_type,
77
+ traffic_source_type,
78
+ device_type,
79
+ operating_system,
80
+ views,
81
+ watch_time_minutes,
82
+ average_view_duration_seconds,
83
+ playlist_starts,
84
+ playlist_saves_added,
85
+ playlist_saves_removed
86
+ from ${ctx.ref(t.database, t.schema, "p_playlist_combined_a1_" + t.suffix)}
87
+ where _PARTITIONDATE > source_date_checkpoint
88
+ `;
89
+ })
90
+ .join(" union all "),
91
+ );
92
+ };
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_list_device_os", {
8
+ type: "incremental",
9
+ database: config.target.database,
10
+ schema: config.datasetStaging,
11
+ protected: config.protected,
12
+ tags: ["youtube", "source", "staging", "daily"],
13
+ bigquery: {
14
+ partitionBy: "interaction_date",
15
+ clusterBy: ["playlist_id", "video_id", "device_type", "operating_system"],
16
+ },
17
+ assertions: {
18
+ uniqueKeys: [
19
+ [
20
+ "interaction_date",
21
+ "channel_id",
22
+ "playlist_id",
23
+ "video_id",
24
+ "live_or_on_demand",
25
+ "subscribed_status",
26
+ "country_code",
27
+ "device_type",
28
+ "operating_system",
29
+ ],
30
+ ],
31
+ rowConditions: ["interaction_date = source_partition_date"],
32
+ },
33
+ description:
34
+ "Staging table for YouTube Channel Playlist Device and OS data",
35
+ })
36
+ .preOps(
37
+ (ctx) => `
38
+ declare source_date_checkpoint default (
39
+ select date("${config.startDate}")
40
+ );
41
+
42
+ set source_date_checkpoint = (
43
+ ${ctx.when(
44
+ ctx.incremental(),
45
+ `select
46
+ least(
47
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
48
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
49
+ )`,
50
+ `select date("${config.startDate}")`,
51
+ )}
52
+ );
53
+
54
+ ${ctx.when(
55
+ ctx.incremental(),
56
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
57
+ )}
58
+ `,
59
+ )
60
+ .query((ctx) =>
61
+ config.sources
62
+ .map((t) => {
63
+ return `
64
+
65
+ select
66
+ _PARTITIONDATE as source_partition_date,
67
+ parse_date('%Y%m%d', date) as interaction_date,
68
+ "${t.schema}" as site_nm,
69
+ current_timestamp() as updated_at,
70
+ channel_id,
71
+ playlist_id,
72
+ video_id,
73
+ live_or_on_demand,
74
+ subscribed_status,
75
+ country_code,
76
+ device_type,
77
+ operating_system,
78
+ views,
79
+ watch_time_minutes,
80
+ average_view_duration_seconds,
81
+ playlist_starts,
82
+ playlist_saves_added,
83
+ playlist_saves_removed
84
+ from ${ctx.ref(t.database, t.schema, "p_playlist_device_os_a1_" + t.suffix)}
85
+ where _PARTITIONDATE > source_date_checkpoint
86
+ `;
87
+ })
88
+ .join(" union all "),
89
+ );
90
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_list_playback", {
8
+ type: "incremental",
9
+ database: config.target.database,
10
+ schema: config.datasetStaging,
11
+ protected: config.protected,
12
+ tags: ["youtube", "source", "staging", "daily"],
13
+ bigquery: {
14
+ partitionBy: "interaction_date",
15
+ clusterBy: ["playlist_id", "video_id", "playback_location_type"],
16
+ },
17
+ assertions: {
18
+ uniqueKeys: [
19
+ [
20
+ "interaction_date",
21
+ "channel_id",
22
+ "playlist_id",
23
+ "video_id",
24
+ "live_or_on_demand",
25
+ "subscribed_status",
26
+ "country_code",
27
+ "playback_location_type",
28
+ "playback_location_detail",
29
+ ],
30
+ ],
31
+ rowConditions: ["interaction_date = source_partition_date"],
32
+ },
33
+ description:
34
+ "Staging table for YouTube Channel Playlist Playback Location data",
35
+ })
36
+ .preOps(
37
+ (ctx) => `
38
+ declare source_date_checkpoint default (
39
+ select date("${config.startDate}")
40
+ );
41
+
42
+ set source_date_checkpoint = (
43
+ ${ctx.when(
44
+ ctx.incremental(),
45
+ `select
46
+ least(
47
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
48
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
49
+ )`,
50
+ `select date("${config.startDate}")`,
51
+ )}
52
+ );
53
+
54
+ ${ctx.when(
55
+ ctx.incremental(),
56
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
57
+ )}
58
+ `,
59
+ )
60
+ .query((ctx) =>
61
+ config.sources
62
+ .map((t) => {
63
+ return `
64
+ select
65
+ _PARTITIONDATE as source_partition_date,
66
+ parse_date('%Y%m%d', date) as interaction_date,
67
+ "${t.schema}" as site_nm,
68
+ current_timestamp() as updated_at,
69
+ channel_id,
70
+ playlist_id,
71
+ video_id,
72
+ live_or_on_demand,
73
+ subscribed_status,
74
+ country_code,
75
+ playback_location_type,
76
+ playback_location_detail,
77
+ views,
78
+ watch_time_minutes,
79
+ average_view_duration_seconds,
80
+ playlist_starts,
81
+ playlist_saves_added,
82
+ playlist_saves_removed
83
+ from ${ctx.ref(t.database, t.schema, "p_playlist_playback_location_a1_" + t.suffix)}
84
+ where _PARTITIONDATE > source_date_checkpoint
85
+ `;
86
+ })
87
+ .join(" union all "),
88
+ );
89
+ };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ const column_descriptions = require("../../column_descriptions");
6
+
7
+ module.exports = (config) => {
8
+ // eslint-disable-next-line no-undef
9
+ return publish("stg_ytc_list_province", {
10
+ type: "incremental",
11
+ database: config.target.database,
12
+ schema: config.datasetStaging,
13
+ protected: config.protected,
14
+ tags: ["youtube", "source", "staging", "daily"],
15
+ bigquery: {
16
+ partitionBy: "interaction_date",
17
+ clusterBy: ["playlist_id", "video_id"],
18
+ },
19
+ assertions: {
20
+ // make sure rows have unique dimensions
21
+ uniqueKeys: [
22
+ [
23
+ "interaction_date",
24
+ "channel_id",
25
+ "playlist_id",
26
+ "video_id",
27
+ "live_or_on_demand",
28
+ "subscribed_status",
29
+ "province_code",
30
+ ],
31
+ ],
32
+ // make sure source partition and data dates match
33
+ rowConditions: ["interaction_date = source_partition_date"],
34
+ },
35
+ columns: column_descriptions.column_descriptions,
36
+ description: "YT Channel Playlist Province Report Table - Staging",
37
+ })
38
+ .preOps(
39
+ (ctx) => `
40
+ declare source_date_checkpoint default (
41
+ select date("${config.startDate}")
42
+ );
43
+
44
+ --Set the incremental update checkpoint based on current max partition value minus lookback.
45
+ set source_date_checkpoint = (
46
+ ${ctx.when(
47
+ ctx.incremental(),
48
+ `select
49
+ least(
50
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
51
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
52
+ )`,
53
+ `select date("${config.startDate}")`,
54
+ )}
55
+ );
56
+
57
+ ${ctx.when(
58
+ ctx.incremental(),
59
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
60
+ )}
61
+ `,
62
+ )
63
+ .query((ctx) =>
64
+ config.sources
65
+ .map((t) => {
66
+ return `
67
+ select
68
+ _PARTITIONDATE as source_partition_date,
69
+ parse_date('%Y%m%d',date) as interaction_date,
70
+ "${t.schema}" as site_nm,
71
+ current_timestamp() as updated_at,
72
+ channel_id,
73
+ playlist_id,
74
+ video_id,
75
+ live_or_on_demand,
76
+ subscribed_status,
77
+ country_code,
78
+ province_code,
79
+ views,
80
+ watch_time_minutes,
81
+ average_view_duration_seconds,
82
+ playlist_starts,
83
+ playlist_saves_added,
84
+ playlist_saves_removed
85
+ from ${ctx.ref(t.database, t.schema, "p_playlist_province_a1_" + t.suffix)}
86
+ where _PARTITIONDATE > source_date_checkpoint
87
+ `;
88
+ })
89
+ .join(" union all "),
90
+ );
91
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_list_traffic_source", {
8
+ type: "incremental",
9
+ database: config.target.database,
10
+ schema: config.datasetStaging,
11
+ protected: config.protected,
12
+ tags: ["youtube", "source", "staging", "daily"],
13
+ bigquery: {
14
+ partitionBy: "interaction_date",
15
+ clusterBy: ["playlist_id", "video_id", "traffic_source_type"],
16
+ },
17
+ assertions: {
18
+ uniqueKeys: [
19
+ [
20
+ "interaction_date",
21
+ "channel_id",
22
+ "playlist_id",
23
+ "video_id",
24
+ "live_or_on_demand",
25
+ "subscribed_status",
26
+ "country_code",
27
+ "traffic_source_type",
28
+ "traffic_source_detail",
29
+ ],
30
+ ],
31
+ rowConditions: ["interaction_date = source_partition_date"],
32
+ },
33
+ description:
34
+ "Staging table for YouTube Channel Playlist Traffic Source data",
35
+ })
36
+ .preOps(
37
+ (ctx) => `
38
+ declare source_date_checkpoint default (
39
+ select date("${config.startDate}")
40
+ );
41
+
42
+ set source_date_checkpoint = (
43
+ ${ctx.when(
44
+ ctx.incremental(),
45
+ `select
46
+ least(
47
+ (select date_sub(current_date(), interval ${config.daysBack} day)),
48
+ (select date_sub(max(source_partition_date), interval ${config.daysBack} day) from ${ctx.self()})
49
+ )`,
50
+ `select date("${config.startDate}")`,
51
+ )}
52
+ );
53
+
54
+ ${ctx.when(
55
+ ctx.incremental(),
56
+ `delete ${ctx.self()} where source_partition_date > source_date_checkpoint`,
57
+ )}
58
+ `,
59
+ )
60
+ .query((ctx) =>
61
+ config.sources
62
+ .map((t) => {
63
+ return `
64
+ select
65
+ _PARTITIONDATE as source_partition_date,
66
+ parse_date('%Y%m%d', date) as interaction_date,
67
+ "${t.schema}" as site_nm,
68
+ current_timestamp() as updated_at,
69
+ channel_id,
70
+ playlist_id,
71
+ video_id,
72
+ live_or_on_demand,
73
+ subscribed_status,
74
+ country_code,
75
+ traffic_source_type,
76
+ traffic_source_detail,
77
+ views,
78
+ watch_time_minutes,
79
+ average_view_duration_seconds,
80
+ playlist_starts,
81
+ playlist_saves_added,
82
+ playlist_saves_removed
83
+ from ${ctx.ref(t.database, t.schema, "p_playlist_traffic_source_a1_" + t.suffix)}
84
+ where _PARTITIONDATE > source_date_checkpoint
85
+ `;
86
+ })
87
+ .join(" union all "),
88
+ );
89
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_lu_annotation_type", {
8
+ type: "table",
9
+ database: config.target.database,
10
+ schema: config.datasetOutput,
11
+ protected: config.protected,
12
+ tags: ["youtube", "lookup", "annotations"],
13
+ description:
14
+ "Lookup table for YouTube video annotation types and their names from YouTube Analytics API.",
15
+ }).query(
16
+ (ctx) =>
17
+ `
18
+
19
+ select
20
+ cast(annotation_type as int) as annotation_type,
21
+ annotation_type_name
22
+ from unnest([
23
+ struct(0 as annotation_type, "Unknown" as annotation_type_name),
24
+ struct(1 as annotation_type, "Note" as annotation_type_name),
25
+ struct(3 as annotation_type, "Spotlight" as annotation_type_name),
26
+ struct(4 as annotation_type, "Title" as annotation_type_name),
27
+ struct(8 as annotation_type, "Speech bubble" as annotation_type_name),
28
+ struct(9 as annotation_type, "Label" as annotation_type_name),
29
+ struct(10 as annotation_type, "Branding watermark" as annotation_type_name),
30
+ struct(11 as annotation_type, "Featured video" as annotation_type_name),
31
+ struct(12 as annotation_type, "Featured playlist" as annotation_type_name),
32
+ struct(30 as annotation_type, "Call-to-Action" as annotation_type_name)
33
+ ]) as annotation_types
34
+
35
+ `,
36
+ );
37
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (C) 2025 by KEN-E, LLC
3
+ */
4
+
5
+ module.exports = (config) => {
6
+ // eslint-disable-next-line no-undef
7
+ return publish("stg_ytc_lu_card_type", {
8
+ type: "table",
9
+ database: config.target.database,
10
+ schema: config.datasetOutput,
11
+ protected: config.protected,
12
+ tags: ["youtube", "lookup", "card_type"],
13
+ description: "Lookup table for YouTube card types and their descriptions.",
14
+ }).query(
15
+ (ctx) =>
16
+ `
17
+
18
+ select
19
+ cast(card_type as int) as card_type,
20
+ card_type_name
21
+ from unnest([
22
+ struct(0 as card_type, "Unknown" as card_type_name),
23
+ struct(60 as card_type, "Link" as card_type_name),
24
+ struct(61 as card_type, "Fundraising" as card_type_name),
25
+ struct(62 as card_type, "Video" as card_type_name),
26
+ struct(63 as card_type, "Playlist" as card_type_name),
27
+ struct(65 as card_type, "Fan Funding" as card_type_name),
28
+ struct(66 as card_type, "Merchandise" as card_type_name),
29
+ struct(68 as card_type, "Associated website" as card_type_name),
30
+ struct(69 as card_type, "Channel" as card_type_name)
31
+ ]) as card_types
32
+
33
+ `,
34
+ );
35
+ };