def test_can_get_retention_week_interval(self):
        organization = create_organization(name="test")
        team = create_team(organization=organization)
        user = create_user(email="*****@*****.**",
                           password="******",
                           organization=organization)

        self.client.force_login(user)

        update_or_create_person(distinct_ids=["person 1"], team_id=team.pk)
        update_or_create_person(distinct_ids=["person 2"], team_id=team.pk)

        setup_user_activity_by_day(
            daily_activity={
                "2020-01-01": {
                    "person 1": [{
                        "event": "target event"
                    }]
                },
                "2020-01-08": {
                    "person 2": [{
                        "event": "target event"
                    }]
                },
            },
            team=team,
        )

        retention = get_retention_ok(
            client=self.client,
            team_id=team.pk,
            request=RetentionRequest(
                target_entity={
                    "id": "target event",
                    "type": "events"
                },
                returning_entity={
                    "id": "target event",
                    "type": "events"
                },
                date_from="2020-01-01",
                total_intervals=2,
                date_to="2020-01-08",
                period="Week",
                retention_type="retention_first_time",
            ),
        )

        retention_by_cohort_by_period = get_by_cohort_by_period_for_response(
            client=self.client, response=retention)

        assert retention_by_cohort_by_period == {
            "Week 0": {
                "1": ["person 1"],
                "2": [],
            },
            "Week 1": {
                "1": ["person 2"]
            },
        }
Beispiel #2
0
    def test_can_specify_breakdown_person_property(self):
        """
        By default, we group users together by the first time they perform the
        `target_event`. However, we should also be able to specify, e.g. the
        users OS to be able to compare retention between the OSs.
        """
        organization = create_organization(name="test")
        team = create_team(organization=organization)
        user = create_user(email="*****@*****.**", password="******", organization=organization)

        self.client.force_login(user)

        update_or_create_person(distinct_ids=["person 1"], team_id=team.pk, properties={"os": "Chrome"})
        update_or_create_person(distinct_ids=["person 2"], team_id=team.pk, properties={"os": "Safari"})

        setup_user_activity_by_day(
            daily_activity={
                "2020-01-01": {"person 1": [{"event": "target event"}]},
                "2020-01-02": {"person 1": [{"event": "target event"}], "person 2": [{"event": "target event"}]},
                # IMPORTANT: we include data past the end of the requested
                # window, as we want to ensure that we pick up all retention
                # periods for a user. e.g. for "person 2" we do not want to miss
                # the count from 2020-01-03 e.g. the second period, otherwise we
                # will skew results for users that didn't perform their target
                # event right at the beginning of the requested range.
                "2020-01-03": {"person 1": [{"event": "target event"}], "person 2": [{"event": "target event"}]},
            },
            team=team,
        )

        retention = get_retention_ok(
            client=self.client,
            team_id=team.pk,
            request=RetentionRequest(
                target_entity={"id": "target event", "type": "events"},
                returning_entity={"id": "target event", "type": "events"},
                date_from="2020-01-01",
                total_intervals=2,
                date_to="2020-01-02",
                period="Day",
                retention_type="retention_first_time",
                breakdowns=[Breakdown(type="person", property="os")],
                # NOTE: we need to specify breakdown_type as well, as the
                # breakdown logic currently does not support multiple differing
                # types
                breakdown_type="person",
            ),
        )

        retention_by_cohort_by_period = get_by_cohort_by_period_for_response(client=self.client, response=retention)

        assert retention_by_cohort_by_period, {
            "Chrome": {"1": ["person 1"], "2": ["person 1"]},
            "Safari": {
                "1": ["person 2"],
                "2": ["person 2"],
            },  # IMPORTANT: the "2" value is from past the requested `date_to`
        }
Beispiel #3
0
    def test_can_specify_breakdown_event_property_and_retrieve_people(self):
        """
        This test is slightly different from the
        get_by_cohort_by_period_for_response based tests in that here we are
        checking a cohort/period specific people url that does not include the
        "appearances" detail.

        This is used, e.g. for the frontend retentions trend graph
        """
        organization = create_organization(name="test")
        team = create_team(organization=organization)
        user = create_user(email="*****@*****.**", password="******", organization=organization)

        self.client.force_login(user)

        update_or_create_person(distinct_ids=["person 1"], team_id=team.pk)
        update_or_create_person(distinct_ids=["person 2"], team_id=team.pk)

        setup_user_activity_by_day(
            daily_activity={
                "2020-01-01": {
                    "person 1": [{"event": "target event", "properties": {"os": "Chrome"}}],
                    "person 2": [{"event": "target event", "properties": {"os": "Safari"}}],
                },
                "2020-01-02": {"person 1": [{"event": "target event"}], "person 2": [{"event": "target event"}],},
            },
            team=team,
        )

        retention = get_retention_ok(
            client=self.client,
            team_id=team.pk,
            request=RetentionRequest(
                target_entity={"id": "target event", "type": "events"},
                returning_entity={"id": "target event", "type": "events"},
                date_from="2020-01-01",
                total_intervals=2,
                date_to="2020-01-02",
                period="Day",
                retention_type="retention_first_time",
                breakdowns=[Breakdown(type="event", property="os")],
                # NOTE: we need to specify breakdown_type as well, as the
                # breakdown logic currently does not support multiple differing
                # types
                breakdown_type="event",
            ),
        )

        chrome_cohort = [cohort for cohort in retention["result"] if cohort["label"] == "Chrome"][0]
        people_url = chrome_cohort["values"][0]["people_url"]
        people_response = self.client.get(people_url)
        assert people_response.status_code == 200

        people = people_response.json()["result"]

        assert [distinct_id for person in people for distinct_id in person["distinct_ids"]] == ["person 1"]
Beispiel #4
0
    def test_retention_test_account_filters(self):

        organization = create_organization(name="test")
        team = create_team(organization=organization)
        user = create_user(email="*****@*****.**", password="******", organization=organization)

        self.client.force_login(user)

        team.test_account_filters = [
            {"key": "email", "type": "person", "value": "posthog.com", "operator": "not_icontains"}
        ]
        team.save()

        update_or_create_person(distinct_ids=["person 1"], team_id=team.pk, properties={"email": "posthog.com"})
        update_or_create_person(distinct_ids=["person 2"], team_id=team.pk)
        update_or_create_person(distinct_ids=["person 3"], team_id=team.pk)

        setup_user_activity_by_day(
            daily_activity={
                "2020-01-01": {"person 1": [{"event": "target event"}], "person 2": [{"event": "target event"}]},
                "2020-01-02": {"person 1": [{"event": "target event"}], "person 3": [{"event": "target event"}]},
                "2020-01-03": {"person 1": [{"event": "target event"}], "person 3": [{"event": "target event"}]},
            },
            team=team,
        )

        retention = get_retention_ok(
            client=self.client,
            team_id=team.pk,
            request=RetentionRequest(
                target_entity={"id": "target event", "type": "events"},
                returning_entity={"id": "target event", "type": "events"},
                date_from="2020-01-01",
                total_intervals=2,
                date_to="2020-01-02",
                period="Day",
                retention_type="retention_first_time",
                filter_test_accounts="true",
            ),
        )

        retention_by_cohort_by_period = get_by_cohort_by_period_for_response(client=self.client, response=retention)

        assert retention_by_cohort_by_period == {
            "Day 0": {"1": ["person 2"], "2": [],},
            "Day 1": {"1": ["person 3"]},
        }
    def test_properties_correlation_endpoint_provides_people_drill_down_urls(
            self):
        """
        Here we are setting up three users, two with a specified property but
        differing values, and one with this property absent. We expect to be
        able to use the correlation people drill down urls to retrieve the
        associated people for each.
        """

        with freeze_time("2020-01-01"):
            self.client.force_login(self.user)

            update_or_create_person(distinct_ids=["Person 1"],
                                    team_id=self.team.pk,
                                    properties={"$browser": "1"})
            update_or_create_person(distinct_ids=["Person 2"],
                                    team_id=self.team.pk,
                                    properties={"$browser": "1"})

            events = {
                "Person 1": [
                    # Failure / $browser::1
                    {
                        "event": "signup",
                        "timestamp": datetime(2020, 1, 1)
                    },
                ],
                "Person 2": [
                    # Success / $browser::1
                    {
                        "event": "signup",
                        "timestamp": datetime(2020, 1, 1)
                    },
                    {
                        "event": "view insights",
                        "timestamp": datetime(2020, 1, 3)
                    },
                ],
                "Person 3": [
                    # Success / $browser not set
                    {
                        "event": "signup",
                        "timestamp": datetime(2020, 1, 1)
                    },
                    {
                        "event": "view insights",
                        "timestamp": datetime(2020, 1, 3)
                    },
                ],
            }

            journeys_for(events_by_person=events, team=self.team)

            odds = get_funnel_correlation_ok(
                client=self.client,
                team_id=self.team.pk,
                request=FunnelCorrelationRequest(
                    events=json.dumps([
                        EventPattern(id="signup"),
                        EventPattern(id="view insights")
                    ]),
                    date_to="2020-04-04",
                    funnel_correlation_type=FunnelCorrelationType.PROPERTIES,
                    funnel_correlation_names=json.dumps(["$browser"]),
                ),
            )

            (browser_correlation, ) = [
                correlation for correlation in odds["result"]["events"]
                if correlation["event"]["event"] == "$browser::1"
            ]

            (notset_correlation, ) = [
                correlation for correlation in odds["result"]["events"]
                if correlation["event"]["event"] == "$browser::"
            ]

            assert get_people_for_correlation_ok(
                client=self.client, correlation=browser_correlation) == {
                    "success": ["Person 2"],
                    "failure": ["Person 1"],
                }

            assert get_people_for_correlation_ok(
                client=self.client, correlation=notset_correlation) == {
                    "success": ["Person 3"],
                    "failure": [],
                }
Beispiel #6
0
def test_includes_only_intervals_within_range(client: Client):
    """
    This is the case highlighted by https://github.com/PostHog/posthog/issues/2675

    Here the issue is that we request, for instance, 14 days as the
    date_from, display at weekly intervals but previously we
    were displaying 4 ticks on the date axis. If we were exactly on the
    beginning of the week for two weeks then we'd want 2 ticks.
    Otherwise we would have 3 ticks as the range would be intersecting
    with three weeks. We should never need to display 4 ticks.
    """
    organization = create_organization(name="test org")
    team = create_team(organization=organization)
    user = create_user("user", "pass", organization)

    client.force_login(user)
    cache.clear()

    #  I'm creating a cohort here so that I can use as a breakdown, just because
    #  this is what was used demonstrated in
    #  https://github.com/PostHog/posthog/issues/2675 but it might not be the
    #  simplest way to reproduce

    # "2021-09-19" is a sunday, i.e. beginning of week
    with freeze_time("2021-09-20T16:00:00"):
        #  First identify as a member of the cohort
        distinct_id = "abc"
        update_or_create_person(distinct_ids=[distinct_id],
                                team_id=team.id,
                                properties={"cohort_identifier": 1})
        cohort = create_cohort_ok(client=client,
                                  team_id=team.id,
                                  name="test cohort",
                                  groups=[{
                                      "properties": {
                                          "cohort_identifier": 1
                                      }
                                  }])

        journeys_for(
            events_by_person={
                distinct_id: [
                    {
                        "event": "$pageview",
                        "timestamp": "2021-09-04"
                    },
                    {
                        "event": "$pageview",
                        "timestamp": "2021-09-05"
                    },
                    {
                        "event": "$pageview",
                        "timestamp": "2021-09-12"
                    },
                    {
                        "event": "$pageview",
                        "timestamp": "2021-09-19"
                    },
                ]
            },
            team=team,
        )

        trends = get_trends_ok(
            client,
            team=team,
            request=TrendsRequestBreakdown(
                date_from="-14days",
                date_to="2021-09-21",
                interval="week",
                insight="TRENDS",
                breakdown=json.dumps([cohort["id"]]),
                breakdown_type="cohort",
                display="ActionsLineGraph",
                events=[{
                    "id": "$pageview",
                    "math": "dau",
                    "name": "$pageview",
                    "custom_name": None,
                    "type": "events",
                    "order": 0,
                    "properties": [],
                    "math_property": None,
                }],
            ),
        )
        assert trends == {
            "is_cached":
            False,
            "last_refresh":
            "2021-09-20T16:00:00Z",
            "next":
            None,
            "result": [{
                "action": ANY,
                "breakdown_value": cohort["id"],
                "label": "$pageview - test cohort",
                "count": 3.0,
                "data": [1.0, 1.0, 1.0],
                # Prior to the fix this would also include '29-Aug-2021'
                "labels": ["5-Sep-2021", "12-Sep-2021", "19-Sep-2021"],
                "days": ["2021-09-05", "2021-09-12", "2021-09-19"],
                "persons_urls": ANY,
                "filter": ANY,
            }],
        }
    def test_retention_aggregation_by_distinct_id_and_retrieve_people(self):
        organization = create_organization(name="test")
        team = create_team(organization=organization)
        user = create_user(email="*****@*****.**",
                           password="******",
                           organization=organization)

        self.client.force_login(user)

        p1 = update_or_create_person(distinct_ids=["person 1", "another one"],
                                     team_id=team.pk)
        p2 = update_or_create_person(distinct_ids=["person 2"],
                                     team_id=team.pk)

        setup_user_activity_by_day(
            daily_activity={
                "2020-01-01": {
                    "person 1": [{
                        "event": "target event",
                    }],
                    "another one": [{
                        "event": "target event",
                    }],
                },
                "2020-01-02": {
                    "person 1": [{
                        "event": "target event"
                    }],
                    "person 2": [{
                        "event": "target event"
                    }]
                },
                "2020-01-03": {
                    "another one": [{
                        "event": "target event"
                    }],
                },
            },
            team=team,
        )

        with override_config(AGGREGATE_BY_DISTINCT_IDS_TEAMS=f"{team.pk}"):
            retention = get_retention_ok(
                client=self.client,
                team_id=team.pk,
                request=RetentionRequest(
                    target_entity={
                        "id": "target event",
                        "type": "events"
                    },
                    returning_entity={
                        "id": "target event",
                        "type": "events"
                    },
                    date_from="2020-01-01",
                    total_intervals=3,
                    date_to="2020-01-03",
                    period="Day",
                    retention_type="retention_first_time",
                ),
            )

            assert retention["result"][0]["values"][0][
                "count"] == 2  #  person 1 and another one
            assert retention["result"][0]["values"][1]["count"] == 1  # person 1
            assert retention["result"][0]["values"][2][
                "count"] == 1  # another one

            #  person 2
            assert retention["result"][1]["values"][0]["count"] == 1
            assert retention["result"][1]["values"][1]["count"] == 0

            people_url = retention["result"][0]["values"][0]["people_url"]
            people_response = self.client.get(people_url)
            assert people_response.status_code == 200

            people = people_response.json()["result"]
            # person1 and another one are the same person
            assert len(people) == 1
            assert people[0]["id"] == str(p1.uuid)

            people_url = retention["result"][1]["values"][0]["people_url"]
            people_response = self.client.get(people_url)
            assert people_response.status_code == 200

            people = people_response.json()["result"]
            assert len(people) == 1
            assert people[0]["id"] == str(p2.uuid)