1use crate::de::empty_or_vec;
2use serde::Deserialize;
3use serde_with::{serde_as, DisplayFromStr, PickFirst};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum VisitorType {
8 New,
9 Returning,
10 #[serde(other)]
11 Unknown,
12}
13
14#[serde_as]
20#[derive(Debug, Clone, Deserialize)]
21#[serde(rename_all = "camelCase")]
22pub struct Visit {
23 pub id_visit: i64,
25 #[serde(default)]
26 pub visitor_id: Option<String>,
27 #[serde(default)]
28 pub fingerprint: Option<String>,
29 #[serde(default)]
30 pub user_id: Option<String>,
31
32 #[serde(default)]
34 pub server_timestamp: Option<i64>,
35 #[serde(default)]
36 pub first_action_timestamp: Option<i64>,
37 #[serde(default)]
38 pub last_action_timestamp: Option<i64>,
39
40 #[serde(default)]
42 pub visit_count: i64,
43 #[serde(default)]
44 pub visit_duration: i64,
45 #[serde(default)]
46 pub actions: i64,
47 #[serde(default)]
48 pub searches: i64,
49 #[serde(default)]
50 pub interactions: i64,
51 #[serde(default)]
52 pub visitor_type: Option<VisitorType>,
53 #[serde_as(as = "PickFirst<(_, DisplayFromStr)>")]
54 #[serde(default)]
55 pub visit_converted: i64,
56
57 #[serde(default)]
59 pub referrer_type: Option<String>,
60 #[serde(default)]
61 pub referrer_name: Option<String>,
62 #[serde(default)]
63 pub referrer_keyword: Option<String>,
64 #[serde(default)]
65 pub referrer_url: Option<String>,
66
67 #[serde(default)]
69 pub continent: Option<String>,
70 #[serde(default)]
71 pub country: Option<String>,
72 #[serde(default)]
73 pub country_code: Option<String>,
74 #[serde(default)]
75 pub region: Option<String>,
76 #[serde(default)]
77 pub city: Option<String>,
78 #[serde_as(as = "Option<PickFirst<(DisplayFromStr, _)>>")]
80 #[serde(default)]
81 pub latitude: Option<f64>,
82 #[serde_as(as = "Option<PickFirst<(DisplayFromStr, _)>>")]
83 #[serde(default)]
84 pub longitude: Option<f64>,
85
86 #[serde(default)]
88 pub device_type: Option<String>,
89 #[serde(default)]
90 pub device_brand: Option<String>,
91 #[serde(default)]
92 pub device_model: Option<String>,
93 #[serde(default)]
94 pub operating_system_name: Option<String>,
95 #[serde(default)]
96 pub browser_name: Option<String>,
97 #[serde(default)]
98 pub browser_version: Option<String>,
99 #[serde(default)]
100 pub resolution: Option<String>,
101
102 #[serde(default)]
103 pub action_details: Vec<ActionDetail>,
104
105 #[serde(default, deserialize_with = "empty_or_vec")]
107 pub goal_conversions: Vec<GoalConversion>,
108}
109
110#[derive(Debug, Clone, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct GoalConversion {
114 #[serde(default)]
115 pub goal_id: Option<i64>,
116 #[serde(default)]
117 pub revenue: Option<f64>,
118 #[serde(default)]
119 pub url: Option<String>,
120 #[serde(default)]
121 pub timestamp: Option<i64>,
122}
123
124#[derive(Debug, Clone, Deserialize)]
129#[serde(tag = "type", rename_all = "lowercase")]
130pub enum ActionDetail {
131 Action(ActionPageview),
132 Download(ActionLink),
133 Outlink(ActionLink),
134 Event(ActionEvent),
135 Search(ActionSearch),
136 Goal(ActionGoal),
137 #[serde(other)]
138 Unknown,
139}
140
141#[derive(Debug, Clone, Deserialize)]
142#[serde(rename_all = "camelCase")]
143pub struct ActionPageview {
144 #[serde(default)]
145 pub url: Option<String>,
146 #[serde(default)]
147 pub page_title: Option<String>,
148 #[serde(default)]
149 pub page_id_action: Option<i64>,
150 #[serde(default)]
151 pub page_id: Option<i64>,
152 #[serde(default)]
153 pub idpageview: Option<String>,
154 #[serde(default)]
155 pub time_spent: Option<i64>,
156 #[serde(default)]
157 pub pageview_position: Option<i64>,
158 #[serde(default)]
159 pub timestamp: Option<i64>,
160}
161
162#[derive(Debug, Clone, Deserialize)]
163#[serde(rename_all = "camelCase")]
164pub struct ActionLink {
165 #[serde(default)]
166 pub url: Option<String>,
167 #[serde(default)]
168 pub page_title: Option<String>,
169 #[serde(default)]
170 pub page_id_action: Option<i64>,
171 #[serde(default)]
172 pub page_id: Option<i64>,
173 #[serde(default)]
174 pub idpageview: Option<String>,
175 #[serde(default)]
176 pub timestamp: Option<i64>,
177}
178
179#[derive(Debug, Clone, Deserialize)]
180#[serde(rename_all = "camelCase")]
181pub struct ActionEvent {
182 #[serde(default)]
183 pub event_category: Option<String>,
184 #[serde(default)]
185 pub event_action: Option<String>,
186 #[serde(default)]
187 pub event_name: Option<String>,
188 #[serde(default)]
189 pub timestamp: Option<i64>,
190}
191
192#[derive(Debug, Clone, Deserialize)]
193#[serde(rename_all = "camelCase")]
194pub struct ActionSearch {
195 #[serde(default)]
196 pub keyword: Option<String>,
197 #[serde(default)]
198 pub timestamp: Option<i64>,
199}
200
201#[derive(Debug, Clone, Deserialize)]
202#[serde(rename_all = "camelCase")]
203pub struct ActionGoal {
204 #[serde(default)]
205 pub goal_id: Option<i64>,
206 #[serde(default)]
207 pub revenue: Option<f64>,
208 #[serde(default)]
209 pub timestamp: Option<i64>,
210}