Growth data insights are often driven by time-to metrics (time to adoption, time to conversion) which requires a much more granular approach to data insights on a namespace- or user-level. Growth data insights are often grouped by the date of creation (just as namespace creation, user creation, or trial started).
This will provide a centralized location to find key snippets built for Growth data interests and that are tailored to allow for stated filtering needs.
Snippets are great ways to allow Sisense users to build charts without writing any SQL. Below is a list of snippets created specifically to help answer growth-related questions and have built-in data source joins to enable enhanced data granularity and filtering capabilities.
Some of the benefits of using these snippets include:
setup_for_company
selection and namespace_type
These snippets can be inserted into the SQL code for a Sisense chart in two ways:
[insert_snippet_name_here]
)Please note that the underlying queries for these snippets may change on occasion. If you copy/paste these snippet code, later changes won't be reflected in your reports. If you use the square bracket approach, any reports using these snippets will automatically update if the snippet code is updated.
As listed below in the documentation for each snippet, there will be a series of filtering options that need to be enabled on your Sisense report. To do this, please complete the following steps (screenshots coming soon):
Simplifed namespaces data set that includes enhanced filtering
Options for accessing this snippet:
[growth_data_namespaces]
into your Sisense report.Granularity: One record per namespace
Data Sets Used:
legacy.gitlab_dotcom_namespaces_xf
legacy.gitlab_dotcom_users_blocked_xf
legacy.gitlab_dotcom_members
legacy.gitlab_dotcom_user_preferences
Fields:
namespace_id
: Unique identifier of namespacecreator_id
: Unique user identifier (user_id
) of namespace creatornamespace_created_at
: Timestamp of namespace creationnamespace_creation_date
: Date of namespace creationcompany_setup_filter
: Transformed setup_for_company
: 'True'
, 'False'
, 'None'
. Used for
setup_for_company
filternamespace_visibility_level
: Visibility level of namespace: 'public'
, 'private'
, 'internal'
.
Used for visibility_level
filterAutomatic Filters:
Group
namespacesFiltering Options (if filters aren't enabled, will show all results):
setup_for_company
DateRange
: Select what range of namespace_created_at
dates you want included in the reportAggregation
: Aggregate how to group the namespace_created_at
dates (daily, weekly, monthly, etc)namespace_visibility
How to Use and Sample Output (if copy/pasted into Sisense):
These snippets are written as plug-and-play CTEs. You can apply your own name to these CTEs
WITH namespaces AS [growth_data_namespaces]
SELECT *
FROM namespaces
LIMIT 5
;
Simplifed namespaces data set that includes trials and subscriptions
Options for accessing this snippet:
[growth_data_namespaces_with_trials_subscriptions]
into your Sisense report.Granularity: One record per namespace
Data Sets Used:
legacy.gitlab_dotcom_namespaces_xf
legacy.gitlab_dotcom_users_blocked_xf
legacy.gitlab_dotcom_members
legacy.gitlab_dotcom_user_preferences
legacy.customers_db_trial_histories
restricted_safe_legacy.customers_db_charges_xf
Fields:
namespace_id
: Unique identifier of namespacecreator_id
: Unique user identifier (user_id
) of namespace creatornamespace_created_at
: Timestamp of namespace creationnamespace_creation_date
: Date of namespace creationcompany_setup_filter
: Transformed setup_for_company
: 'True'
, 'False'
, 'None'
namespace_visibility_level
: Visibility level of namespace: 'public'
, 'private'
, 'internal'
did_start_trial
: Boolean denoting whether namespace started a free trialtrial_start_date
: Start date of trialdid_start_subscription
: Boolean denoting whether namespace started a paid subscriptionmin_subscription_start_date
: Start date of namespace's first subscriptionfirst_paid_plan_name
: Plan name of namespace's first subscription: Premium
, Ultimate
,
Bronze
is_purchased_through_subscription_portal
: Boolean denoting whether namespace's first
subscription was purchased through a purchase order or directly from the web portal (will be NULL
if namespace did not start a subscription)
Automatic Filters:
[growth_data_namespaces]
snippetFiltering Options (if filters aren't enabled, will show all results):
[growth_data_namespaces]
snippetFiltering Options (if filters aren't enabled, will show all results):
setup_for_company
DateRange
: Select what range of namespace_created_at
dates you want included in the reportAggregation
: Aggregate how to group the namespace_created_at
dates (daily, weekly, monthly, etc)namespace_visibility
How to Use and Sample Output (if copy/pasted into Sisense):
These snippets are written as plug-and-play CTEs. You can apply your own name to these CTEs
WITH namespaces_w_trials_subs AS [growth_data_namespaces_with_trials_subscriptions]
SELECT *
FROM namespaces_w_trials_subs
LIMIT 5
;
See namespace stage adoption metrics such as stages adopted and active users within first X days since namespace creation.
Options for accessing this snippet:
[growth_data_spo]
into your Sisense report.Dependencies: Snippet includes [growth_data_namespaces]
snippet
DO NOT USE FOR: Individual stage insights (use stage adoption snippet for this)
Granularity: One record per namespace
Data Sets Used:
legacy.gitlab_dotcom_daily_usage_data_events
legacy.gitlab_dotcom_xmau_metrics
legacy.gitlab_dotcom_namespaces_xf
legacy.gitlab_dotcom_users_blocked_xf
legacy.gitlab_dotcom_members
legacy.gitlab_dotcom_user_preferences
Fields:
namespace_id
: Unique identifier of namespacenamespace_creation_date
: Date of namespace creationstage_count
: Count of unique stages with representative stage event adopted within time windowactive_users
: Count of unique namespace users that adopted at least one representative stage
event within time windowactive_days
: Count of unique days that at least one namespace user completed at least one
representative stage event within the time windowAutomatic Filters:
[growth_data_namespaces]
snippetmanage
and monitor
since reporting is not currently available for SaaSnamespace_created_at
dates that are immature, meaning they were created less
than First_X_Days_Filter
days before todayFiltering Options (if filters aren't enabled, will show all results):
[growth_data_namespaces]
snippetevent_plan_name
: Namespace's plan level at the time of the stage eventFirst_X_Days_Filter
: Filters for the first x days after namespace creationSee namespace-level stage adoption metrics such as time to first adoption, stage usage days, and unique namespace users that adopted stage
Options for accessing this snippet:
[growth_data_stage_adoption]
into your Sisense report.Dependencies: Snippet includes [growth_data_namespaces]
snippet
Granularity: One record per namespace per stage.
Do Not Use For:
[growth_data_spo]
snippet for a more general SpO analysis.Fields:
namespace_id
: Unique identifier of namespacenamespace_creation_date
: Date of namespace creationnamespace_creation_[aggregation]
: Date of namespace creation truncated by [aggregation]
stage_name
initial_stage_adopted_at
: Timestamp of first adoption of stagedays_till_first_adoption
: Count of days from namespace creation to the namespace's initial
stage adoptionstage_users
: Count of unique namespace users that adopted at least one representative stage
event within time windowstage_usage_days
: Count of unique days that at least one namespace user completed at least
one representative stage event within the time windowstage_order_adopted
: Order of stages adopted by namespace (integer)stages_adopted_by_namespace
: Total count of unique stages adopted in the namespace's first
[First_X_Days_Filter]
days after creationAutomatic Filters:
[growth_data_namespaces]
snippetmanage
and monitor
since reporting is not currently available for SaaSnamespace_created_at
dates that are immature, meaning they were created less than First_X_Days_Filter
days before today.Filtering Options (if filters aren't enabled, will show all results):
[growth_data_namespaces]
snippetevent_plan_name
: Namespace's plan level at the time of the stage eventFirst_X_Days_Filter
: Filters for the first x days after namespace creationWITH stages AS [growth_data_stage_adoption]
SELECT *
FROM stages
LIMIT 5
;
Group namespace-level invites. More details on invite data below
Options for accessing this snippet:
[growth_data_group_namespace_invites]
into your Sisense report.Dashboards:
The Invite Acceptance Dashboard
is a good jumping-off point for working with this data. It leverages the more granular snippet
detailed below, [growth_data_group_namespace_invites_w_metadata]
.
Granularity: One record per invited user per namespace (one record per member_id
)
Note: Currently this snippet only looks at invitations to the top-level namespace. It does not include invites to sub-groups or projects. This will be updated in a future iteration but is an important caveat when using the snippet in its current state.
Since the grain is at the member level, there can be multiple records per user (one for each
namespace they have been invited to) and multiple records per namespace (one per invited user).
Please be careful of this when JOIN
ing to other tables! You need to join on both the user_id
and the namespace_id
to avoid potential errors or duplicate records.
Dependencies: Snippet includes [growth_data_namespaces]
snippet
Data Sets Used:
legacy.gitlab_dotcom_namespaces_xf
legacy.gitlab_dotcom_users_blocked_xf
legacy.gitlab_dotcom_user_preferences
legacy.gitlab_dotcom_members
legacy.gitlab_dotcom_memberships
common.dim_user
Fields:
namespace_id
: Unique identifier of namespacenamespace_created_at
: Timestamp of namespace creationnamespace_visibility_level
: Visibility level of namespace: 'public'
, 'private'
, 'internal'
user_id
: Unique identifier of usermember_id
: Identifier unique to the user and namespaceinvite_created_at
: Timestamp that user was invited to namespaceinvite_accepted_at
: Timestamp that user accepted the invitation (will be NULL
if access was
automatically granted)invite_expires_at
: Timestamp of invite expiration, defined as invite_created_at
+ 90 days
(unless explicitly set by inviter)invite_success_at
: Timestamp that user joined the namespace (either via invite acceptance
or access granted)user_created_at
: Timestamp of user creationinvited_user_type
: 'NEW'
(user did not have GitLab account at time of invite) or
'EXISTING'
(user had GitLab account at time of invite)invite_status
: Current status of invite: 'INVITE_ACCEPTED'
, 'ACCESS_GRANTED'
,
'INVITE_EXPIRED'
, 'INVITE_PENDING'
invite_was_successful
: Denotes whether user successfully joined namespace
('INVITE_ACCEPTED'
or 'ACCESS_GRANTED'
)Automatic Filters:
[growth_data_namespaces]
snippetFiltering Options (if filters aren't enabled, will show all results):
[growth_data_namespaces]
snippetHow to Use and Sample Output (if copy/pasted into Sisense):
These snippets are written as plug-and-play CTEs. You can apply your own name to these CTEs
WITH invites AS [growth_data_group_namespace_invites]
SELECT *
FROM invites
LIMIT 5
;
Snippet with additional metadata:
There is another version of this snippet, [growth_data_group_namespace_invites_w_metadata]
,
which includes the following additional fields:
invite_created_rnk
: Order of invites createdinvite_accepted_rnk
: Order of invites accepted (does not include access granted use case)invite_success_at
: Order of successful invites (either accepted or access granted)days_from_namespace_created_to_invite_created
: Count of days between namespace creation and
invite creationdays_from_namespace_created_to_invite_accepted
: Count of days between namespace creation and
invite acceptance (does not include access granted use case)days_from_namespace_created_to_invite_success
: Count of days between namespace creation and
invite success (either accepted or access granted)days_from_invite_created_to_accepted
: Count of days between invite creation and invite
acceptance (does not include access granted use case)days_from_invite_created_to_success
: Count of days between invite creation and invite
success (either accepted or access granted)Additional details:
Please see below for additional details about invite data.
Collection of snippets, query templates, and dashboards designed to facilitate experimentation analysis.
Sisense snippet that can easily be adjusted any experiment using Snowplow events data.
Granularity: One record per event_id
Data Sets Used:
legacy.snowplow_structured_events_all
legacy.snowplow_gitlab_events_experiment_contexts_all
Fields:
event_id
: Unique identifier of Snowplow eventexperiment_name
experiment_variant
context_key
derived_tstamp
: Timestamp of event (with millisecond granularity)event_action
event_property
event_value
environment
: 'production'
or 'staging'
(based on app_id
)Filtering Options (if filters aren't enabled, will show all results):
select_experiment
: Applied to experiment_name
DateRange
: Applied to derived_tstamp
snowplow_environment
: 'production'
or 'staging'
NOTE: Due to the size of the Snowplow data set and performance concerns, please be sure to apply,
at minimum, the select_experiment
filter. Queries will be much more performant if you also
apply the DateRange
filter.
Sample Output:
WITH events AS ([experiment events])
SELECT *
FROM events
WHERE experiment_name = 'new_repo'
LIMIT 10
;
Template for calculating a funnel with multiple Snowplow events
Granularity: One record per stage
Dependencies: Utilizes the [Experiment Events]
snippet
Data Sets Used:
legacy.snowplow_structured_events_all
legacy.snowplow_gitlab_events_experiment_contexts_all
How to Use:
Note: Unlike the other snippets listed, this is meant to be used as a query template. The reason being is the user has to adjust this template to fit the specifications needed for the experiment such as number of events in the funnel, which fields are needed for filtering, and other requirements. There is documentation listed within the query template to help guide you to make the needed customizations.
event_action
, event_label
, and experiment_name
to fit the experiment you are analyzing.Note on Results: For a context_key
to be counted in later steps, that same key must be present in all previous steps. For example, a context_key
that is recorded as a step three conversion would also have to be present in steps one and two.
Sample Output:
Date-level granularity can be removed.
At a glance, see if the experiment is reporting data, for which events, and what the candidate/control distribution looks like.
How to Use:
select_experiment
filter dropdown. Data for your experiment will load in approximately two to five minutes.Sample of Charts included in Dashboard
A brief guide clarifying the granularity, important fields, recommended filters, and any data constraints or quality issues that come with using these data sets.
Provides helpful fields on every namespace such as the dim_namespace_id
, created_at
date, and namespace_type
.
common.dim_namespace
(dbt)
Data Team's Data Guide to Namespace Analysis
Product Data Insights documented differences between legacy and common models
Summary: Provides helpful fields on every namespace such as the dim_namespace_id
, created_at
date, and namespace_type
. This can be joined with numerous event, subscription, and member tables. In addition, this table can usefully be joined to certain user-centric tables for enhanced filtering capabilities such as removing blocked users and filtering for namespaces that are set up for a company account.
Granularity: 1 record per namespace
Key Filters:
namespace_is_internal = FALSE
: Excludes internal namespacesultimate_parent_namespace_id = dim_namespace_id
: Includes only top-level namespacesnamespace_type = 'Group'
: Recommended since most Growth initiatives are built around Group namespacesItems of Note:
Two main tables used to calculate invites, legacy.gitlab_dotcom_members
and legacy.gitlab_dotcom_memberships
.
Two different types of "invites"
There are two main invite use cases:
invite_status = 'INVITE_ACCEPTED'
invite_status = 'INVITE_PENDING'
or
invite_status = 'INVITE_EXPIRED'
invite_status = 'ACCESS_GRANTED'
legacy.gitlab_dotcom_members
(dbt)
Summary: legacy.gitlab_dotcom_members
is a type 2 table with records for both successful and
unsuccessful invites.
member_id
(unique to the
user_id
and source_id
)
PREP.gitlab_dotcom.gitlab_dotcom_members_source
member_id
) where is_currently_valid = TRUE
Notable columns:
member_id
: Unique identifier specific to the user_id
and source_id
(namespace/group/project)user_id
: Unique identifier of invited usersource_id
: Unique identifier of namespace/group/project user is invited to (ex: namespace_id
)member_source_type
: Type of entity user is invited to ('Namespace'
or 'Project'
)invite_created_at
Timestamp of invite creation
invite_accepted_at
: Timestamp of invite acceptance
NULL
for the "access granted" use caseaccess_level
: Numeric value that represents the member's permissions
at a point in time
legacy.gitlab_dotcom_memberships
(dbt)
Summary: legacy.gitlab_dotcom_memberships
has records if a user successfully joins a
group/namespace/project (the user has a "membership").
Notable columns:
user_id
: Unique identifier of namespace/group/project membermembership_source_id
: Unique identifier of namespace/group/projectis_billable
: Boolean denoting whether a member should be counted toward the seat count
for a subscription (source)
access_level
: Numeric value that represents the member's current permissions
access_level
. Use legacy.gitlab_dotcom_members
to view historicExample of how and when different use cases appear in the two tables:
Invite sent use case:
legacy.gitlab_dotcom_members
legacy.gitlab_dotcom_members
updated to reflect time of acceptance
(invite_accepted_at IS NOT NULL
)legacy.gitlab_dotcom_memberships
Access granted use case:
legacy.gitlab_dotcom_members
(where invite_accepted_at IS NULL
)legacy.gitlab_dotcom_memberships
Invite status
Product Analysis uses the following to define invite_status
:
INVITE_ACCEPTED
: Appears in memberships table, invite_accepted_at IS NOT NULL
ACCESS_GRANTED
: Appears in memberships table, invite_accepted_at IS NULL
INVITE_EXPIRED
: Does not appear in the memberships table, invite_created_at
over 90 days ago
OR past inviter-specified invite_expires_at
INVITE_PENDING
: Does not appear in the memberships table, invite_created_at
in last 90 days OR
before inviter-specific invite_expires_at
Successful invites
Invites with either the INVITE_ACCEPTED
or ACCESS_GRANTED
status are considered to be
"successful" invites. Since there is no single column in either table that represents the
time a user successfully joined the namespace/group/project, the Product Analysis team uses the
following definition for invite_success_at
(as of December 2021):
IFF(memberships.user_id IS NOT NULL, IFNULL(members.invite_accepted_at, members.invite_created_at), NULL)
We use invite_success_at
to determine member counts at any point in time.
"Invite Acceptance Rate" Calculations
The methodology to calculate "invite acceptance rate" has changed over time:
ACCESS_GRANTED
invites in the denominator,
but not in the numerator. As such, the metric was under-reported.ACCESS_GRANTED
invites are excluded).Member access_level
/permissions
As noted above, access_level
is present in both legacy.gitlab_dotcom_members
and legacy.gitlab_dotcom_memberships
legacy.gitlab_dotcom_members
will track changes to a member's access_level
over timelegacy.gitlab_dotcom_memberships
represents the member's current access_level
Here is a CASE
statement that can be used to map the numeric values to permissions
SELECT
access_level,
CASE access_level --https://docs.gitlab.com/ee/development/permissions.html#members
WHEN 50 THEN 'Owner'
WHEN 40 THEN 'Maintainer'
WHEN 30 THEN 'Developer'
WHEN 20 THEN 'Reporter'
WHEN 10 THEN 'Guest'
WHEN 5 THEN 'Minimal Access'
END AS member_permissions,
COUNT(*)
FROM legacy.gitlab_dotcom_memberships
GROUP BY 1
ORDER BY 1
;
This section will include a list of tips for dealing with data.
Feel free to submit any questions, comments, or suggestions to the issue associated with upcoming additions (internal link) to this page.