@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.
- package/.vscode/settings.json +3 -0
- package/README.md +4 -0
- package/eslint.config.js +11 -0
- package/includes/column_descriptions.js +95 -0
- package/includes/constants.js +5 -0
- package/includes/definitions/sources/stg_ytc_annotation.js +91 -0
- package/includes/definitions/sources/stg_ytc_basic.js +109 -0
- package/includes/definitions/sources/stg_ytc_cards.js +89 -0
- package/includes/definitions/sources/stg_ytc_combined.js +97 -0
- package/includes/definitions/sources/stg_ytc_demographics.js +84 -0
- package/includes/definitions/sources/stg_ytc_device_os.js +90 -0
- package/includes/definitions/sources/stg_ytc_end_screens.js +69 -0
- package/includes/definitions/sources/stg_ytc_list_basic.js +91 -0
- package/includes/definitions/sources/stg_ytc_list_combined.js +92 -0
- package/includes/definitions/sources/stg_ytc_list_device_os.js +90 -0
- package/includes/definitions/sources/stg_ytc_list_playback.js +89 -0
- package/includes/definitions/sources/stg_ytc_list_province.js +91 -0
- package/includes/definitions/sources/stg_ytc_list_traffic_source.js +89 -0
- package/includes/definitions/sources/stg_ytc_lu_annotation_type.js +37 -0
- package/includes/definitions/sources/stg_ytc_lu_card_type.js +35 -0
- package/includes/definitions/sources/stg_ytc_lu_device_types.js +33 -0
- package/includes/definitions/sources/stg_ytc_lu_end_screen_element_type.js +36 -0
- package/includes/definitions/sources/stg_ytc_lu_operating_systems.js +57 -0
- package/includes/definitions/sources/stg_ytc_lu_playback_location.js +34 -0
- package/includes/definitions/sources/stg_ytc_lu_sharing_services.js +94 -0
- package/includes/definitions/sources/stg_ytc_lu_traffic_sources.js +50 -0
- package/includes/definitions/sources/stg_ytc_playback.js +90 -0
- package/includes/definitions/sources/stg_ytc_province.js +103 -0
- package/includes/definitions/sources/stg_ytc_share_platform.js +82 -0
- package/includes/definitions/sources/stg_ytc_subtitles.js +89 -0
- package/includes/definitions/sources/stg_ytc_traffic_source.js +107 -0
- package/includes/definitions/ytc_annotation.js +65 -0
- package/includes/definitions/ytc_basic.js +74 -0
- package/includes/definitions/ytc_cards.js +66 -0
- package/includes/definitions/ytc_combined.js +113 -0
- package/includes/definitions/ytc_demographics.js +69 -0
- package/includes/definitions/ytc_demographics_views.js +80 -0
- package/includes/definitions/ytc_device_os.js +80 -0
- package/includes/definitions/ytc_end_screens.js +65 -0
- package/includes/definitions/ytc_list_basic.js +84 -0
- package/includes/definitions/ytc_list_combined.js +97 -0
- package/includes/definitions/ytc_list_device_os.js +90 -0
- package/includes/definitions/ytc_list_playback.js +86 -0
- package/includes/definitions/ytc_list_province.js +83 -0
- package/includes/definitions/ytc_list_traffic_source.js +91 -0
- package/includes/definitions/ytc_playback.js +73 -0
- package/includes/definitions/ytc_province.js +71 -0
- package/includes/definitions/ytc_share_platform.js +76 -0
- package/includes/definitions/ytc_subtitles.js +69 -0
- package/includes/definitions/ytc_traffic_source.js +73 -0
- package/includes/helpers.js +8 -0
- package/includes/project_variables.js +15 -0
- package/index.js +312 -0
- package/package.json +30 -0
- 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
|
+
};
|