Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Funnel default event #5280

Merged
merged 5 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion frontend/src/lib/utils/getAppContext.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { AppContext } from '~/types'
import { AppContext, PathType } from '~/types'

export function getAppContext(): AppContext | undefined {
return (window as any)['POSTHOG_APP_CONTEXT'] || undefined
}

export function getDefaultEventName(): string {
return getAppContext()?.default_event_name || PathType.PageView
}
7 changes: 2 additions & 5 deletions frontend/src/scenes/funnels/funnelLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
FunnelStep,
FunnelsTimeConversionBins,
FunnelTimeConversionStep,
PathType,
PersonType,
ViewType,
FunnelStepWithNestedBreakdown,
Expand All @@ -27,10 +26,10 @@ import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS, FunnelLayout } from 'lib/constants'
import { preflightLogic } from 'scenes/PreflightCheck/logic'
import { FunnelStepReference } from 'scenes/insights/InsightTabs/FunnelTab/FunnelStepReferencePicker'
import { eventDefinitionsModel } from '~/models/eventDefinitionsModel'
import { calcPercentage, cleanBinResult, getLastFilledStep, getReferenceStep } from './funnelUtils'
import { personsModalLogic } from 'scenes/trends/personsModalLogic'
import { router } from 'kea-router'
import { getDefaultEventName } from 'lib/utils/getAppContext'

function aggregateBreakdownResult(breakdownList: FunnelStep[][]): FunnelStepWithNestedBreakdown[] {
if (breakdownList.length) {
Expand Down Expand Up @@ -521,9 +520,7 @@ export const funnelLogic = kea<funnelLogicType>({
if (!objectsEqual(currentParams, paramsToCheck)) {
const cleanedParams = cleanFunnelParams(searchParams)
if (isStepsEmpty(cleanedParams)) {
const event = eventDefinitionsModel.values.eventNames.includes(PathType.PageView)
? PathType.PageView
: eventDefinitionsModel.values.eventNames[0]
const event = getDefaultEventName()
cleanedParams.events = [
{
id: event,
Expand Down
22 changes: 6 additions & 16 deletions frontend/src/scenes/trends/trendsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
ChartDisplayType,
EntityTypes,
FilterType,
PathType,
PersonType,
PropertyFilter,
TrendResult,
Expand All @@ -24,6 +23,7 @@ import { eventDefinitionsModel } from '~/models/eventDefinitionsModel'
import { propertyDefinitionsModel } from '~/models/propertyDefinitionsModel'
import { sceneLogic } from 'scenes/sceneLogic'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { getDefaultEventName } from 'lib/utils/getAppContext'

interface TrendResponse {
result: TrendResult[]
Expand Down Expand Up @@ -121,16 +121,9 @@ export function parsePeopleParams(peopleParams: PeopleParamType, filters: Partia
return toAPIParams({ ...params, ...restParams })
}

function getDefaultFilters(currentFilters: Partial<FilterType>, eventNames: string[]): Partial<FilterType> {
/* Opening /insights without any params, will set $pageview as the default event (or
the first random event). We load this default events when `currentTeam` is loaded (because that's when
`eventNames` become available) and on every view change (through the urlToAction map) */
if (!currentFilters.actions?.length && !currentFilters.events?.length && eventNames.length) {
const event = eventNames.includes(PathType.PageView)
? PathType.PageView
: eventNames.includes(PathType.Screen)
? PathType.Screen
: eventNames[0]
function getDefaultFilters(currentFilters: Partial<FilterType>): Partial<FilterType> {
if (!currentFilters.actions?.length && !currentFilters.events?.length) {
const event = getDefaultEventName()

const defaultFilters = {
[EntityTypes.EVENTS]: [
Expand Down Expand Up @@ -386,7 +379,7 @@ export const trendsLogic = kea<trendsLogicType<IndexedTrendResult, TrendResponse
actions.setBreakdownValuesLoading(false)
},
[eventDefinitionsModel.actionTypes.loadEventDefinitionsSuccess]: async () => {
const newFilter = getDefaultFilters(values.filters, eventDefinitionsModel.values.eventNames)
const newFilter = getDefaultFilters(values.filters)
const mergedFilter: Partial<FilterType> = {
...values.filters,
...newFilter,
Expand Down Expand Up @@ -454,10 +447,7 @@ export const trendsLogic = kea<trendsLogicType<IndexedTrendResult, TrendResponse
cleanSearchParams['compare'] = false
}

Object.assign(
cleanSearchParams,
getDefaultFilters(cleanSearchParams, eventDefinitionsModel.values.eventNames)
)
Object.assign(cleanSearchParams, getDefaultFilters(cleanSearchParams))

if (!objectsEqual(cleanSearchParams, values.filters)) {
actions.setFilters(cleanSearchParams, false)
Expand Down
1 change: 1 addition & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ export type EventOrPropType = EventDefinition & PropertyDefinition
export interface AppContext {
current_user: UserType | null
preflight: PreflightStatus
default_event_name: string
}

export type StoredMetricMathOperations = 'max' | 'min' | 'sum'
23 changes: 22 additions & 1 deletion posthog/test/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from django.test import TestCase
from freezegun import freeze_time

from posthog.utils import get_available_timezones_with_offsets, mask_email_address, relative_date_parse
from posthog.models import EventDefinition
from posthog.test.base import BaseTest
from posthog.utils import (
get_available_timezones_with_offsets,
get_default_event_name,
mask_email_address,
relative_date_parse,
)


class TestGeneralUtils(TestCase):
Expand Down Expand Up @@ -57,3 +64,17 @@ def test_year(self):
@freeze_time("2020-01-31")
def test_normal_date(self):
self.assertEqual(relative_date_parse("2019-12-31").strftime("%Y-%m-%d"), "2019-12-31")


class TestDefaultEventName(BaseTest):
def test_no_events(self):
self.assertEqual(get_default_event_name(), "$pageview")

def test_take_screen(self):
EventDefinition.objects.create(name="$screen", team=self.team)
self.assertEqual(get_default_event_name(), "$screen")

def test_prefer_pageview(self):
EventDefinition.objects.create(name="$pageview", team=self.team)
EventDefinition.objects.create(name="$screen", team=self.team)
self.assertEqual(get_default_event_name(), "$pageview")
17 changes: 16 additions & 1 deletion posthog/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,14 @@ def render_template(template_name: str, request: HttpRequest, context: Dict = {}
# Set the frontend app context
if not request.GET.get("no-preloaded-app-context"):
from posthog.api.user import UserSerializer
from posthog.models import EventDefinition
from posthog.views import preflight_check

posthog_app_context: Dict = {"current_user": None, "preflight": json.loads(preflight_check(request).getvalue())}
posthog_app_context: Dict = {
"current_user": None,
"preflight": json.loads(preflight_check(request).getvalue()),
"default_event_name": get_default_event_name(),
}

if request.user.pk:
user = UserSerializer(request.user, context={"request": request}, many=False)
Expand All @@ -236,6 +241,16 @@ def render_template(template_name: str, request: HttpRequest, context: Dict = {}
return HttpResponse(html)


def get_default_event_name():
from posthog.models import EventDefinition

if EventDefinition.objects.filter(name="$pageview").exists():
return "$pageview"
elif EventDefinition.objects.filter(name="$screen").exists():
return "$screen"
return "$pageview"


def json_uuid_convert(o):
if isinstance(o, uuid.UUID):
return str(o)
Expand Down