Skip to main content

codoseo_web/
rankorg.rs

1//! The RankOrg link (spec sections 8 and 14): RankOrg is the sibling product CodoSEO feeds, and
2//! v0.1 connects them with links only. A link carries the domain, the site's top pages and UTM
3//! tags, so RankOrg can start from what the audit already found.
4
5use url::Url;
6
7/// Shown to RankOrg as `utm_campaign`.
8pub const CAMPAIGN: &str = "codoseo_audit";
9
10/// RankOrg's address with the domain, one `page` parameter per top page, and the UTM tags.
11/// `medium` says where the click came from: `audit_preview` or `explorer`.
12pub 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        // Special characters in a page URL stay inside their value.
58        assert!(url.as_str().contains("x%3D1%26y%3D2"), "{url}");
59    }
60}