1use url::Url;
6
7pub const CAMPAIGN: &str = "codoseo_audit";
9
10pub fn link(base: &Url, domain: &str, pages: &[String], medium: &str) -> Url {
13 let mut url = base.clone();
14 {
15 let mut q = url.query_pairs_mut();
16 q.append_pair("domain", domain);
17 for page in pages {
18 q.append_pair("page", page);
19 }
20 q.append_pair("utm_source", "codoseo");
21 q.append_pair("utm_medium", medium);
22 q.append_pair("utm_campaign", CAMPAIGN);
23 }
24 url
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30
31 #[test]
32 fn carries_domain_pages_and_utm_tags_and_keeps_the_base_query() {
33 let base = Url::parse("https://rankorg.example/start?ref=abc").unwrap();
34 let pages = vec![
35 "https://example.com/a?x=1&y=2".to_owned(),
36 "https://example.com/b c".to_owned(),
37 ];
38 let url = link(&base, "example.com", &pages, "explorer");
39 let q: Vec<(String, String)> = url
40 .query_pairs()
41 .map(|(k, v)| (k.into_owned(), v.into_owned()))
42 .collect();
43 assert_eq!(q[0], ("ref".into(), "abc".into()));
44 assert!(q.contains(&("domain".into(), "example.com".into())));
45 let got: Vec<&str> = q
46 .iter()
47 .filter(|(k, _)| k == "page")
48 .map(|(_, v)| v.as_str())
49 .collect();
50 assert_eq!(
51 got,
52 ["https://example.com/a?x=1&y=2", "https://example.com/b c"]
53 );
54 assert!(q.contains(&("utm_source".into(), "codoseo".into())));
55 assert!(q.contains(&("utm_medium".into(), "explorer".into())));
56 assert!(q.contains(&("utm_campaign".into(), "codoseo_audit".into())));
57 assert!(url.as_str().contains("x%3D1%26y%3D2"), "{url}");
59 }
60}