Skip to main content
These are self-contained BigQuery SQL queries that you can run directly against your glean_customer_event table to reproduce the metrics shown in the Glean Insights dashboard. Before running:
  1. Replace <glean_customer_event_table> with your company’s actual table name (e.g., your_project.glean_customer_event.glean_customer_event_external)
  2. Adjust the start_date and end_date DECLARE values as needed

User Activity & Engagement

  • Output: Daily/Weekly/Monthly active users across Search, Assistant, and Agents
  • Grain: One row per day
  • Use Case: Track overall platform adoption trends over time
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
canonicalized_feature_usage AS (
SELECT datepartition,userid,num_searches,num_chats,num_ai_answers,num_summarizations,num_chat_upvotes,num_chat_downvotes,num_client_active_sessions,num_slackbot_useful_responses,num_slackbot_downvotes,num_slackbot_upvotes,num_slackbot_responses,is_active_other FROM canonicalized
),
agents_usage AS (
    SELECT
        agents_activity_precomputation.datepartition,
        agents_activity_precomputation.user_id,
        SUM(num_agent_runs) AS num_agent_runs,
        SUM(num_all_agent_runs) AS num_all_agent_runs
    FROM
        agents_activity_precomputation
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        agents_activity_precomputation.workflow_id = agent_workflow_id
    WHERE
        (num_agent_runs > 0 OR num_all_agent_runs > 0)
    GROUP BY
        1, 2
),
combined_usage AS (
    SELECT
        COALESCE(c.datepartition, a.datepartition) AS datepartition,
        COALESCE(c.userid, a.user_id) AS userid,
        COALESCE((c.num_searches + c.num_chats + c.num_client_active_sessions + c.num_slackbot_useful_responses + c.num_ai_answers + c.num_summarizations) > 0 OR c.is_active_other, false)
            OR COALESCE(a.num_agent_runs > 0, false) AS is_active_overall, -- Deliberately exclude proactive runs (num_all_agent_runs > 0)
        COALESCE(c.num_searches, 0) AS num_searches,
        COALESCE(c.num_chats, 0) + COALESCE(c.num_ai_answers, 0) + COALESCE(c.num_summarizations, 0) + COALESCE(c.num_slackbot_useful_responses, 0) AS num_assistant_interactions,
        COALESCE(a.num_agent_runs, 0) AS num_agent_runs,
        COALESCE(a.num_all_agent_runs, 0) AS num_all_agent_runs
    FROM
        canonicalized_feature_usage c
    FULL OUTER JOIN
        agents_usage a
    ON
        c.datepartition = a.datepartition
        AND c.userid = a.user_id
)
SELECT
    MetricDate,
    COUNT(DISTINCT CASE WHEN c.is_active_overall AND DATE(MetricDate) = c.datepartition THEN c.userid END) AS DailyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.is_active_overall AND c.datepartition BETWEEN DATE(MetricDate - INTERVAL '6' DAY) AND DATE(MetricDate) THEN c.userid END) AS WeeklyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.is_active_overall THEN c.userid END) AS MonthlyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_searches > 0 AND DATE(MetricDate) = c.datepartition THEN c.userid END) AS SearchDailyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_searches > 0 AND c.datepartition BETWEEN DATE(MetricDate - INTERVAL '6' DAY) AND DATE(MetricDate) THEN c.userid END) AS SearchWeeklyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_searches > 0 THEN c.userid END) AS SearchMonthlyActiveUsers,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN num_searches END), 0) AS DailySearchCount,
    COUNT(DISTINCT CASE WHEN c.num_assistant_interactions > 0 AND DATE(MetricDate) = c.datepartition THEN c.userid END) AS AssistantDailyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_assistant_interactions > 0 AND c.datepartition BETWEEN DATE(MetricDate - INTERVAL '6' DAY) AND DATE(MetricDate) THEN c.userid END) AS AssistantWeeklyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_assistant_interactions > 0 THEN c.userid END) AS AssistantMonthlyActiveUsers,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN num_assistant_interactions END), 0) AS DailyAssistantInteractionsCount,
    COUNT(DISTINCT CASE WHEN c.num_agent_runs > 0 AND DATE(MetricDate) = c.datepartition THEN c.userid END) AS AgentsDailyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_agent_runs > 0 AND c.datepartition BETWEEN DATE(MetricDate - INTERVAL '6' DAY) AND DATE(MetricDate) THEN c.userid END) AS AgentsWeeklyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.num_agent_runs > 0 THEN c.userid END) AS AgentsMonthlyActiveUsers,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN num_agent_runs END), 0) AS DailyAgentRunsCount,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN num_all_agent_runs END), 0) AS DailyAllAgentRunsCount
FROM
    UNNEST(GENERATE_TIMESTAMP_ARRAY(TIMESTAMP(start_date), TIMESTAMP(end_date), INTERVAL 1 DAY)) AS MetricDate
LEFT JOIN
    combined_usage c
ON
    c.datepartition BETWEEN DATE(MetricDate - INTERVAL '27' DAY) AND DATE(MetricDate)
-- Do not force Active Users to be present in the Org Chart; include qualifying activity even if not in org chart
LEFT JOIN
    glean_customer_event.latest_orgchart_data o
ON
    c.userid = o.userid
WHERE
    1=1
GROUP BY
    1
ORDER BY
    1
  • Output: Employee count, signup count, and active user counts per department
  • Grain: One row per department
  • Use Case: Compare adoption and engagement across organizational units
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
canonicalized_feature_usage AS (
    SELECT
        *
    FROM
        canonicalized
    WHERE
        num_searches > 0 OR num_chats > 0 OR num_client_active_sessions > 0 OR num_slackbot_useful_responses > 0 OR is_active_other
),
agents_usage AS (
    SELECT
        agents_activity_precomputation.datepartition,
        agents_activity_precomputation.user_id,
        SUM(num_agent_runs) AS num_agent_runs,
        SUM(num_all_agent_runs) AS num_all_agent_runs
    FROM
        agents_activity_precomputation
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        agents_activity_precomputation.workflow_id = agent_workflow_id
    WHERE
        (num_all_agent_runs > 0)
    GROUP BY
        1, 2
),
orgchart_full_join_feature_usage AS (
    SELECT
        o.department,
        o.userid AS orgchart_userid,
        o.signuptime,
        COALESCE(c.datepartition, a.datepartition) AS datepartition,
        COALESCE(c.userid, CASE WHEN a.num_agent_runs > 0 THEN a.user_id END) AS feature_usage_userid, -- Deliberately exclude proactive runs (num_all_agent_runs > 0)
        c.num_searches,
        c.num_chats,
        a.num_agent_runs,
        a.num_all_agent_runs
    FROM
        glean_customer_event.latest_orgchart_data o
    FULL OUTER JOIN
        -- Include users in org chart with no activity + users with activity but not in org chart
        canonicalized_feature_usage c
    ON
        c.userid = o.userid
    FULL OUTER JOIN
        agents_usage a
    ON
        c.datepartition = a.datepartition
        AND c.userid = a.user_id
    WHERE
        1=1
)
SELECT
    department,
    COUNT(DISTINCT orgchart_userid) AS NumEmployees,
    -- Users in the orgchart with AU-qualifying activity should never be considered not-signed-up.
    -- TODO: resolve the KI where users can be active on gleanbot without a signup time
    COUNT(DISTINCT CASE WHEN signuptime IS NOT NULL OR feature_usage_userid IS NOT NULL THEN orgchart_userid END) AS NumSignups,
    COUNT(DISTINCT CASE WHEN feature_usage_userid IS NOT NULL AND datepartition BETWEEN DATE(end_date) - INTERVAL '27' DAY AND DATE(end_date) THEN feature_usage_userid END) AS MonthlyActiveUsers,
    COUNT(DISTINCT CASE WHEN feature_usage_userid IS NOT NULL AND datepartition BETWEEN DATE(end_date) - INTERVAL '6' DAY AND DATE(end_date) THEN feature_usage_userid END) AS WeeklyActiveUsers,
    COALESCE(SUM(CASE WHEN datepartition BETWEEN DATE(start_date) AND DATE(end_date) THEN num_searches ELSE 0 END), 0) AS NumSearches,
    COUNT(DISTINCT CASE WHEN num_searches > 0 AND datepartition BETWEEN DATE(start_date) AND DATE(end_date) THEN feature_usage_userid END) AS NumSearchUsers,
    COALESCE(SUM(CASE WHEN datepartition BETWEEN DATE(start_date) AND DATE(end_date) THEN num_chats ELSE 0 END), 0) AS NumChats,
    COUNT(DISTINCT CASE WHEN num_chats > 0 AND datepartition BETWEEN DATE(start_date) AND DATE(end_date) THEN feature_usage_userid END) AS NumChatUsers,
    COUNT(DISTINCT CASE WHEN datepartition BETWEEN DATE(end_date) - INTERVAL '27' DAY AND DATE(end_date) AND num_searches > 0 THEN feature_usage_userid END) AS MonthlySearchActiveUsers,
    COUNT(DISTINCT CASE WHEN datepartition BETWEEN DATE(end_date) - INTERVAL '6' DAY AND DATE(end_date) AND num_searches > 0 THEN feature_usage_userid END) AS WeeklySearchActiveUsers,
    COUNT(DISTINCT CASE WHEN datepartition BETWEEN DATE(end_date) - INTERVAL '27' DAY AND DATE(end_date) AND num_chats > 0 THEN feature_usage_userid END) AS MonthlyChatActiveUsers,
    COUNT(DISTINCT CASE WHEN datepartition BETWEEN DATE(end_date) - INTERVAL '6' DAY AND DATE(end_date) AND num_chats > 0 THEN feature_usage_userid END) AS WeeklyChatActiveUsers
FROM
    orgchart_full_join_feature_usage
GROUP BY
    1
  • Output: Per-user activity counts (searches, chats, sessions, agent runs)
  • Grain: One row per user
  • Use Case: Identify power users and engagement distribution
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
canonicalized_feature_usage AS (
    SELECT
        *
    FROM
        canonicalized c
    WHERE
        c.num_searches > 0 OR c.num_chats > 0 OR c.num_client_active_sessions > 0 OR c.num_slackbot_useful_responses > 0 OR c.is_active_other
),
agents_usage AS (
    SELECT
        agents_activity_precomputation.datepartition,
        agents_activity_precomputation.user_id,
        SUM(num_agent_runs) AS num_agent_runs,
        SUM(num_all_agent_runs) AS num_all_agent_runs
    FROM
        agents_activity_precomputation
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        agents_activity_precomputation.workflow_id = agent_workflow_id
    WHERE
        datepartition BETWEEN DATE(start_date) AND DATE(end_date)
        AND (num_agent_runs > 0 OR num_all_agent_runs > 0)
    GROUP BY
        1, 2
),
combined_usage AS (
    SELECT
        COALESCE(c.datepartition, a.datepartition) AS datepartition,
        COALESCE(c.userid, a.user_id) AS userid,
        COALESCE(c.num_searches, 0) AS num_searches,
        COALESCE(c.num_chats, 0) AS num_chats,
        COALESCE(c.num_client_active_sessions, 0) AS num_client_active_sessions,
        COALESCE(c.num_slackbot_useful_responses, 0) AS num_slackbot_useful_responses,
        COALESCE(c.is_active_other, false) AS is_active_other,
        COALESCE(c.num_ai_answers, 0) AS num_ai_answers,
        COALESCE(c.num_summarizations, 0) AS num_summarizations,
        COALESCE(a.num_agent_runs, 0) AS num_agent_runs,
        COALESCE(a.num_all_agent_runs, 0) AS num_all_agent_runs,
        COALESCE(c.num_searches > 0
            OR c.num_chats > 0
            OR c.num_client_active_sessions > 0
            OR c.num_slackbot_useful_responses > 0
            OR c.is_active_other
            OR c.num_ai_answers > 0
            OR c.num_summarizations > 0
            OR a.num_agent_runs > 0 -- Deliberately exclude proactive runs (num_all_agent_runs > 0)
        , FALSE) AS is_active

    FROM
        canonicalized_feature_usage c
    FULL OUTER JOIN
        agents_usage a
    ON
        c.datepartition = a.datepartition
        AND c.userid = a.user_id
)
SELECT
    o.userid AS UserId,
    COALESCE(COUNT(DISTINCT CASE WHEN is_active THEN datepartition END), 0) AS NumDaysActive,
    COALESCE(SUM(num_searches), 0) AS NumSearches,
    COALESCE(SUM(num_chats), 0) AS NumChats,
    COALESCE(SUM(num_client_active_sessions), 0) AS NumActiveSessions,
    COALESCE(SUM(num_slackbot_useful_responses), 0) AS NumGleanbotUsefulResponses,
    COALESCE(SUM(num_ai_answers), 0) AS NumAiAnswers,
    COALESCE(SUM(num_summarizations), 0) AS NumSummarizations,
    COALESCE(SUM(num_agent_runs), 0) AS NumAgentRuns,
    COALESCE(SUM(num_all_agent_runs), 0) AS NumAllAgentRuns
FROM
    glean_customer_event.latest_orgchart_data o
LEFT JOIN
    (SELECT DISTINCT userId FROM combined_usage WHERE is_active) au
ON
    au.userid = o.userid
LEFT JOIN
    (SELECT * FROM combined_usage WHERE is_active AND datepartition BETWEEN DATE(start_date) AND DATE(end_date)) c
ON
    c.userid = o.userid
WHERE
    (1=1)
    -- Users with AU-qualifying activity should never be considered not-signed-up.
    -- TODO: resolve the KI where users can be active on gleanbot without a signup time
    AND (o.signuptime IS NOT NULL OR au.userId IS NOT NULL)
GROUP BY
    o.userId
ORDER BY
    2 DESC, 3 DESC, 4 DESC, 5 DESC, 6 DESC
LIMIT 100
  • Output: Number of search result clicks per datasource
  • Grain: One row per datasource
  • Use Case: Understand which datasources drive the most search engagement
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
search_click_datasources AS (
SELECT
    gce.datepartition,
    o.department,
    gce.jsonPayload.searchclick.datasource,
    COALESCE(COUNT(DISTINCT gce.jsonPayload.searchclick.trackingtoken), 0) AS num_clicks
FROM
    glean_customer_event AS gce
LEFT JOIN
    id_to_alias
ON
    gce.jsonPayload.user.userid = id_to_alias.aliasid
    AND gce.datepartition = id_to_alias.datepartition
LEFT JOIN
    glean_customer_event.latest_orgchart_data AS o
ON
    COALESCE(id_to_alias.canonicalid, gce.jsonPayload.user.userid) = o.userid
    OR COALESCE(id_to_alias.canonicalid, gce.jsonPayload.user.userid) = o.loggingid
WHERE
    gce.jsonPayload.type = 'SEARCH_CLICK'
    AND COALESCE(gce.jsonPayload.searchclick.datasource, '') != ''
    AND LOWER(gce.jsonPayload.searchclick.doctype) != 'golink'
GROUP BY
    1, 2, 3
)
SELECT
    datasource AS Datasource,
    SUM(num_clicks) AS NumUses
FROM
    search_click_datasources
WHERE
    datepartition BETWEEN DATE(start_date) AND DATE(end_date)
    AND (1=1)
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 100
  • Output: Search session satisfaction rate (clicks / searches)
  • Grain: Single aggregate value
  • Use Case: Measure search quality via click-through rate
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
search_ssat AS (
SELECT
    searches.datepartition,
    o.department,
    COUNT(DISTINCT IF(search_clicks.qtt IS NOT NULL, searches.stt, NULL)) AS num_searches_with_clicks,
    COUNT(DISTINCT searches.stt) AS num_searches
FROM
    (
        SELECT
            DISTINCT jsonPayload.user.userid,
            datepartition,
            jsonPayload.Search.SessionTrackingToken AS stt,
            jsonPayload.Search.TrackingToken AS qtt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.Type = 'SEARCH'
            AND (
                jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD')
                AND LOWER(jsonPayload.Search.modality) NOT IN ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
            )
    ) AS searches
LEFT JOIN
    (
        SELECT
            DISTINCT jsonPayload.SearchClick.TrackingToken AS qtt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.Type = 'SEARCH_CLICK'
    ) AS search_clicks
ON
    searches.qtt = search_clicks.qtt
LEFT JOIN
    id_to_alias
ON
    searches.userid = id_to_alias.aliasid
    AND searches.datepartition = id_to_alias.datepartition
LEFT JOIN
    glean_customer_event.latest_orgchart_data AS o
ON
    COALESCE(id_to_alias.canonicalid, searches.userid) = o.userid
    OR COALESCE(id_to_alias.canonicalid, searches.userid) = o.loggingid
GROUP BY 1, 2
)
SELECT
    1.0 * SUM(num_searches_with_clicks)/GREATEST(SUM(num_searches), 1) AS SearchSSAT
FROM
    search_ssat
WHERE
    datepartition BETWEEN DATE(start_date) AND DATE(end_date)
    AND (1=1)

Assistant

  • Output: Daily/Weekly/Monthly active Assistant users
  • Grain: One row per day
  • Use Case: Track Assistant adoption trends over time
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
canonicalized_feature_usage AS (
SELECT datepartition,userid,num_searches,num_chats,num_ai_answers,num_summarizations,num_chat_upvotes,num_chat_downvotes,num_client_active_sessions,num_slackbot_useful_responses,num_slackbot_downvotes,num_slackbot_upvotes,num_slackbot_responses,is_active_other FROM canonicalized
),
canonicalized_active_usage AS (
    SELECT
        *
    FROM
        canonicalized_feature_usage c
    WHERE
        c.num_chats > 0 OR c.num_ai_answers > 0 OR c.num_summarizations > 0 OR c.num_slackbot_useful_responses > 0
)
SELECT
    MetricDate,
    COUNT(DISTINCT CASE WHEN DATE(MetricDate) = c.datepartition THEN c.userid END) AS DailyActiveUsers,
    COUNT(DISTINCT CASE WHEN c.datepartition BETWEEN DATE(MetricDate - INTERVAL '6' DAY) AND DATE(MetricDate) THEN c.userid END) AS WeeklyActiveUsers,
    COUNT(DISTINCT c.userid) AS MonthlyActiveUsers
FROM
    UNNEST(GENERATE_TIMESTAMP_ARRAY(TIMESTAMP(start_date), TIMESTAMP(end_date), INTERVAL 1 DAY)) AS MetricDate
LEFT JOIN
    canonicalized_active_usage c
ON
    c.datepartition BETWEEN DATE(MetricDate - INTERVAL '27' DAY) AND DATE(MetricDate)
-- Do not force Active Users to be present in the Org Chart; include qualifying activity even if not in org chart
LEFT JOIN
    glean_customer_event.latest_orgchart_data o
ON
    c.userid = o.userid
WHERE
    1=1
GROUP BY
    1
ORDER BY
    1
  • Output: Daily counts of chat messages, summarizations, AI answers, Gleanbot interactions, and feedback
  • Grain: One row per day
  • Use Case: Monitor Assistant feature usage volume and feedback trends
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
canonicalized_feature_usage AS (
SELECT datepartition,userid,num_searches,num_chats,num_ai_answers,num_summarizations,num_chat_upvotes,num_chat_downvotes,num_client_active_sessions,num_slackbot_useful_responses,num_slackbot_downvotes,num_slackbot_upvotes,num_slackbot_responses,is_active_other FROM canonicalized
)
SELECT
    MetricDate,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN c.num_chats ELSE 0 END), 0) AS ChatMessages,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN c.num_summarizations ELSE 0 END), 0) AS Summarizations,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN c.num_ai_answers ELSE 0 END), 0) AS AiAnswers,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN c.num_slackbot_useful_responses ELSE 0 END), 0) AS GleanbotInteractions,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN (COALESCE(c.num_chat_upvotes,0) + COALESCE(c.num_slackbot_useful_responses,0)) ELSE 0 END), 0) AS Upvotes,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = c.datepartition THEN COALESCE(c.num_chat_downvotes,0) ELSE 0 END), 0) AS Downvotes
FROM
    UNNEST(GENERATE_TIMESTAMP_ARRAY(TIMESTAMP(start_date), TIMESTAMP(end_date), INTERVAL 1 DAY)) AS MetricDate
LEFT JOIN
    canonicalized_feature_usage c
ON
    c.datepartition = DATE(MetricDate)
LEFT JOIN
    glean_customer_event.latest_orgchart_data o
ON
    c.userid = o.userid
WHERE
    1=1
GROUP BY
    1
ORDER BY
    1
  • Output: Signup count and active Assistant user counts (WAU/MAU)
  • Grain: Single aggregate row
  • Use Case: Quick snapshot of Assistant reach and engagement
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
canonicalized_feature_usage AS (
SELECT datepartition,userid,num_searches,num_chats,num_ai_answers,num_summarizations,num_chat_upvotes,num_chat_downvotes,num_client_active_sessions,num_slackbot_useful_responses,num_slackbot_downvotes,num_slackbot_upvotes,num_slackbot_responses,is_active_other FROM canonicalized
),
orgchart_full_join_feature_usage AS (
    SELECT
        o.department,
        o.userid AS orgchart_userid,
        o.signuptime,
        c.datepartition,
        c.userid AS feature_usage_userid,
        (c.num_chats > 0 OR c.num_ai_answers > 0 OR c.num_summarizations > 0 OR c.num_slackbot_useful_responses > 0) AS is_assistant_active
    FROM
        glean_customer_event.latest_orgchart_data o
    FULL OUTER JOIN
        canonicalized_feature_usage c
    ON
        c.userid = o.userid
    WHERE
        1=1
)
SELECT
    COUNT(DISTINCT CASE WHEN signuptime IS NOT NULL OR feature_usage_userid IS NOT NULL THEN orgchart_userid END) AS NumSignups,
    COUNT(DISTINCT CASE WHEN is_assistant_active AND datepartition BETWEEN DATE(end_date) - INTERVAL '27' DAY AND DATE(end_date) THEN feature_usage_userid END) AS MonthlyActiveUsers,
    COUNT(DISTINCT CASE WHEN is_assistant_active AND datepartition BETWEEN DATE(end_date) - INTERVAL '6' DAY AND DATE(end_date) THEN feature_usage_userid END) AS WeeklyActiveUsers
FROM
    orgchart_full_join_feature_usage
  • Output: Per-user Assistant activity counts (chats, AI answers, summarizations, Gleanbot)
  • Grain: One row per user
  • Use Case: Identify top Assistant users and engagement patterns
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
canonicalized_feature_usage AS (
SELECT datepartition,userid,num_searches,num_chats,num_ai_answers,num_summarizations,num_chat_upvotes,num_chat_downvotes,num_client_active_sessions,num_slackbot_useful_responses,num_slackbot_downvotes,num_slackbot_upvotes,num_slackbot_responses,is_active_other FROM canonicalized
),
canonicalized_assistant_usage AS (
    SELECT
        *
    FROM
        canonicalized_feature_usage c
    WHERE
        c.num_chats > 0 OR c.num_ai_answers > 0 OR c.num_summarizations > 0 OR c.num_slackbot_useful_responses > 0
)
SELECT
    o.userid AS UserId,
    COALESCE(SUM(num_chats), 0) AS NumChatMessages,
    COALESCE(SUM(num_ai_answers), 0) AS NumAiAnswers,
    COALESCE(SUM(num_summarizations), 0) AS NumSummarizations,
    COALESCE(SUM(num_slackbot_useful_responses), 0) AS NumGleanbotInteractions,
    COALESCE(COUNT(DISTINCT
      CASE WHEN num_chats > 0 OR num_ai_answers > 0 OR num_summarizations > 0 OR num_slackbot_useful_responses > 0
      THEN datepartition END
    ), 0) AS NumDaysActive
FROM
    glean_customer_event.latest_orgchart_data o
LEFT JOIN
    (SELECT DISTINCT userId FROM canonicalized_assistant_usage) au
ON
    au.userid = o.userid
LEFT JOIN
    (SELECT * FROM canonicalized_assistant_usage WHERE datepartition BETWEEN DATE(start_date) AND DATE(end_date)) c
ON
    c.userid = o.userid
WHERE
    (1=1)
    -- Users with AU-qualifying activity should never be considered not-signed-up.
    -- TODO: resolve the KI where users can be active on gleanbot without a signup time
    AND (o.signuptime IS NOT NULL OR au.userId IS NOT NULL)
GROUP BY
    o.userId
ORDER BY
    SUM(num_chats) + SUM(num_ai_answers) + SUM(num_summarizations) + SUM(num_slackbot_useful_responses) DESC
LIMIT 100

Agents

  • Output: Daily/Weekly/Monthly active Agent users and run counts
  • Grain: One row per day
  • Use Case: Track Agent adoption and execution trends over time
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
_precomp_agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
agents_activity_precomputation AS (
    SELECT
        aap.*,
        o.department
    FROM
        _precomp_agents_activity_precomputation aap
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        aap.workflow_id = agent_workflow_id
    LEFT JOIN
        glean_customer_event.latest_orgchart_data o
    ON
        aap.user_id = o.userid
    WHERE
        num_agent_runs > 0 -- Deliberately exclude proactive runs (num_all_agent_runs > 0)
        AND 1=1
        AND 1=1
)
SELECT
    MetricDate,
    COUNT(DISTINCT CASE WHEN DATE(MetricDate) = aap.datepartition THEN aap.user_id END) AS DailyActiveUsers,
    COUNT(DISTINCT CASE WHEN aap.datepartition BETWEEN DATE(MetricDate - INTERVAL '6' DAY) AND DATE(MetricDate) THEN aap.user_id END) AS WeeklyActiveUsers,
    COUNT(DISTINCT aap.user_id) AS MonthlyActiveUsers
FROM
    -- Equivalent to the following when running on BQ console
    -- UNNEST(GENERATE_TIMESTAMP_ARRAY(TIMESTAMP '2025-07-21', TIMESTAMP '2025-07-28', INTERVAL '1' DAY)) AS MetricDate
    UNNEST(GENERATE_TIMESTAMP_ARRAY(TIMESTAMP(start_date), TIMESTAMP(end_date), INTERVAL 1 DAY)) AS MetricDate
LEFT JOIN
    agents_activity_precomputation aap
ON
    aap.datepartition BETWEEN DATE(MetricDate - INTERVAL '27' DAY) AND DATE(MetricDate)
GROUP BY
    1
ORDER BY
    1
  • Output: Daily Agent upvote and downvote counts
  • Grain: One row per day
  • Use Case: Monitor Agent quality via user feedback trends
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
_precomp_agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
agents_activity_precomputation AS (
    SELECT
        _precomp_agents_activity_precomputation.*
    FROM
        _precomp_agents_activity_precomputation
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        _precomp_agents_activity_precomputation.workflow_id = agent_workflow_id
    WHERE
        (num_upvotes > 0 OR num_downvotes > 0)
)
SELECT
    MetricDate,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = aap.datepartition THEN aap.num_upvotes END), 0) AS Upvotes,
    COALESCE(SUM(CASE WHEN DATE(MetricDate) = aap.datepartition THEN aap.num_downvotes END), 0) AS Downvotes
FROM
    UNNEST(GENERATE_TIMESTAMP_ARRAY(TIMESTAMP(start_date), TIMESTAMP(end_date), INTERVAL 1 DAY)) AS MetricDate
LEFT JOIN
    agents_activity_precomputation aap
ON
    aap.datepartition = DATE(MetricDate)
LEFT JOIN
    glean_customer_event.latest_orgchart_data o
ON
    aap.user_id = o.userid
WHERE
    1=1
    AND 1=1
GROUP BY
    1
ORDER BY
    1
  • Output: Agent run counts, user counts, and top agent per department
  • Grain: One row per department
  • Use Case: Compare Agent adoption across organizational units
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
agents_info AS (
    SELECT
        DISTINCT workflow_id
        , MAX_BY(name, datepartition) AS AgentName
    FROM
        all_agents
    WHERE is_agent
    GROUP BY
        1
),
department_agent_user_run_counts AS (
    SELECT
        latest_orgchart_data.department
        , agents_activity_precomputation.user_id
        , agents_activity_precomputation.workflow_id
        , ai.AgentName
        , SUM(agents_activity_precomputation.num_agent_runs) AS num_agent_runs
        , SUM(agents_activity_precomputation.num_all_agent_runs) AS num_all_agent_runs
    FROM
        agents_activity_precomputation
    INNER JOIN
        agents_info AS ai
    ON
        agents_activity_precomputation.workflow_id = ai.workflow_id
    LEFT JOIN
        glean_customer_event.latest_orgchart_data
    ON
        agents_activity_precomputation.user_id = latest_orgchart_data.userid
    WHERE
        1=1
        AND latest_orgchart_data.department IS NOT NULL
        AND agents_activity_precomputation.datepartition BETWEEN DATE(start_date) AND DATE(end_date)
        AND (agents_activity_precomputation.num_agent_runs > 0 OR agents_activity_precomputation.num_all_agent_runs > 0)
    GROUP BY
        1, 2, 3, 4
),
department_run_counts AS (
    SELECT
        department
        , SUM(num_agent_runs) AS num_agent_runs
        , SUM(num_all_agent_runs) AS num_all_agent_runs
        , COUNT(DISTINCT user_id) AS num_agent_runners
    FROM
        department_agent_user_run_counts
    GROUP BY
        1
),
department_top_agents AS (
    SELECT
        department
        , MAX_BY(workflow_id, num_agent_runners) AS top_agent_id
        , MAX_BY(AgentName, num_agent_runners) AS top_agent_name
    FROM (
        SELECT
            department
            , workflow_id
            , AgentName
            , COUNT(DISTINCT user_id) AS num_agent_runners
        FROM
            department_agent_user_run_counts
        GROUP BY
            1, 2, 3
    )
    GROUP BY
        1
),
department_sizes AS (
    SELECT
        department
        , COUNT(DISTINCT userid) AS total_employees
    FROM
        glean_customer_event.latest_orgchart_data
    GROUP BY
        1
)
SELECT
    COALESCE(department_run_counts.department, department_sizes.department) AS Department
    , COALESCE(department_top_agents.top_agent_id, '') AS TopAgentId
    , COALESCE(department_top_agents.top_agent_name, '') AS TopAgentName
    , COALESCE(department_run_counts.num_agent_runs, 0) AS RunCount
    , COALESCE(department_run_counts.num_all_agent_runs, 0) AS AllRunCount
    , COALESCE(department_run_counts.num_agent_runners, 0) AS UserCount
    , COALESCE(department_sizes.total_employees, 0) AS TotalEmployees
FROM
    department_run_counts
LEFT JOIN
    department_top_agents
ON
    department_run_counts.department = department_top_agents.department
LEFT JOIN
    department_sizes
ON
    department_run_counts.department = department_sizes.department
  • Output: Per-day agent run counts with department breakdown
  • Grain: One row per day
  • Use Case: Track Agent execution volume and identify peak usage
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
_precomp_agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
agents_activity_precomputation AS (
    SELECT
        aap.*,
        o.department
    FROM
        _precomp_agents_activity_precomputation aap
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        aap.workflow_id = agent_workflow_id
    LEFT JOIN
        glean_customer_event.latest_orgchart_data o
    ON
        aap.user_id = o.userid
    WHERE
        (num_agent_runs > 0 OR num_all_agent_runs > 0)
        AND 1=1
        AND 1=1
),
-- Ensures that there is a date available even when no user used agent on that day
all_dates AS (
    SELECT
        MetricDate
    FROM
    UNNEST(
        GENERATE_TIMESTAMP_ARRAY(TIMESTAMP(start_date), TIMESTAMP(end_date), INTERVAL 1 DAY)
    ) AS MetricDate
)
SELECT
    MetricDate
    , COALESCE(SUM(aap.num_agent_runs),0) AS NumAgentRuns
    , COALESCE(SUM(aap.num_all_agent_runs),0) AS NumAllAgentRuns
FROM
    all_dates
LEFT JOIN
    agents_activity_precomputation AS aap
ON
    MetricDate = CAST(aap.datepartition AS TIMESTAMP)
GROUP BY
    1
ORDER BY 1
  • Output: Agent run counts per user per agent per day
  • Grain: One row per (agent, day, user)
  • Use Case: Detailed Agent usage breakdown for specific users or agents
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
)
SELECT
    agents_activity_precomputation.workflow_id AS AgentId
     , CAST(datepartition AS TIMESTAMP) AS DatePartition
     , user_id AS UserId
     , SUM(num_agent_runs) AS RunCount
     , SUM(num_all_agent_runs) AS AllRunCount
FROM
    agents_activity_precomputation
INNER JOIN
    (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
ON
    agents_activity_precomputation.workflow_id = agent_workflow_id
WHERE
    datepartition BETWEEN DATE(start_date) AND DATE(end_date)
    AND (num_agent_runs > 0 OR num_all_agent_runs > 0)
GROUP BY
    1, 2, 3
ORDER BY
    4 DESC
  • Output: Weekly and Monthly active Agent user counts
  • Grain: Single aggregate row
  • Use Case: Quick snapshot of Agent user engagement
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
_precomp_agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
agents_activity_precomputation AS (
    SELECT
        _precomp_agents_activity_precomputation.*
    FROM
        _precomp_agents_activity_precomputation
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        _precomp_agents_activity_precomputation.workflow_id = agent_workflow_id
    WHERE
        num_agent_runs > 0 -- Deliberately exclude proactive runs (num_all_agent_runs > 0)
)
SELECT
    COUNT(DISTINCT CASE
        WHEN aap.datepartition BETWEEN DATE(end_date) - INTERVAL '6' DAY AND DATE(end_date)
        THEN aap.user_id
    END) AS WeeklyActiveAgentUsers,
    COUNT(DISTINCT CASE
        WHEN aap.datepartition BETWEEN DATE(end_date) - INTERVAL '27' DAY AND DATE(end_date)
        THEN aap.user_id
    END) AS MonthlyActiveAgentUsers
FROM
    agents_activity_precomputation aap
LEFT JOIN
    glean_customer_event.latest_orgchart_data o
ON
    aap.user_id = o.userid
WHERE
    aap.datepartition BETWEEN DATE(end_date) - INTERVAL '27' DAY AND DATE(end_date)
    AND 1=1
    AND 1=1
  • Output: Per-agent user count, run count, and feedback counts
  • Grain: One row per agent
  • Use Case: Identify most popular and highest-quality agents
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
agents_info AS (
    SELECT
        DISTINCT workflow_id
        , MAX_BY(name, datepartition) AS AgentName
    FROM
        all_agents
    WHERE is_agent
    GROUP BY
        1
)

SELECT
    aap.workflow_id as AgentId
    , COALESCE(ai.AgentName, '') AS AgentName
    , COUNT(DISTINCT aap.user_id) AS UserCount
    , COALESCE(SUM(aap.num_agent_runs), 0) AS RunCount
    , COALESCE(SUM(aap.num_all_agent_runs), 0) AS AllRunCount
    , COALESCE(SUM(aap.num_upvotes), 0) AS UpvoteCount
    , COALESCE(SUM(aap.num_downvotes), 0) AS DownvoteCount
FROM
    agents_activity_precomputation aap
INNER JOIN
    agents_info AS ai
ON
    aap.workflow_id = ai.workflow_id
LEFT JOIN
    glean_customer_event.latest_orgchart_data ocd
ON
    aap.user_id = ocd.userid
WHERE
    aap.datepartition BETWEEN DATE(start_date) AND DATE(end_date)
    AND (aap.num_agent_runs > 0 OR aap.num_all_agent_runs > 0 OR aap.num_upvotes > 0 OR aap.num_downvotes > 0)
    AND aap.workflow_id IS NOT NULL
    AND ai.AgentName IS NOT NULL
    AND 1=1
GROUP BY
    1,2
ORDER BY
    3 DESC
  • Output: Per-user agent usage counts (agents used, runs, creations)
  • Grain: One row per user
  • Use Case: Identify power users of the Agents platform
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
canonicalized_feature_usage AS (
SELECT datepartition,userid,num_searches,num_chats,num_ai_answers,num_summarizations,num_chat_upvotes,num_chat_downvotes,num_client_active_sessions,num_slackbot_useful_responses,num_slackbot_downvotes,num_slackbot_upvotes,num_slackbot_responses,is_active_other FROM canonicalized
),
all_workflow_executions AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , workflow_execution.workflowid AS workflow_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , COALESCE(jsonPayload.workflowrun.initiator = 'RECOMMENDATION', FALSE) AS is_proactively_executed
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        AND (jsonPayload.workflowrun.feature != 'AGENT_LIVE_PREVIEW' OR jsonPayload.workflowrun.feature IS NULL)
        AND (
            jsonPayload.workflowrun.initiator IN ('USER', 'REST_API', 'AUTOMATION', 'RECOMMENDATION')
            OR (
                -- Null handling only during buggy period: https://askscio.slack.com/archives/C08BYEY9TC6/p1757033877342169
                datepartition >= DATE '2025-08-12'
                AND datepartition < DATE '2025-09-22'
                AND jsonPayload.workflowrun.initiator IS NULL
            )
        )
        AND workflow_execution.status = 'SUCCESS'
        AND workflow_execution.workflowid IS NOT NULL
        AND workflow_execution.workflowid NOT LIKE 'UNSAVED_%'
        AND workflow_execution.workflowid != 'AGENTIC_WORKFLOW_ID'

),
agent_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        -- Proactively executed agent runs (mostly in gleanbot context) are not DAU worthy
        , COUNT(DISTINCT CASE WHEN NOT is_proactively_executed THEN run_id END) AS num_agent_runs
    FROM
        all_workflow_executions
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_gleanchat AS (

    SELECT
        datepartition
        , IF(
            jsonpayload.chat.workflowrunid IS NOT NULL
            AND jsonpayload.chat.workflowrunid != ''
            , jsonpayload.chat.workflowrunid
            , jsonpayload.chat.qtt
        ) AS run_id
        , jsonpayload.chat.applicationid AS workflow_id
        , resource.labels.project_id AS project_id
        , MIN_BY(jsonPayload.user.userid, timestamp) AS user_id
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'CHAT'
        -- Apps always have a 16 letters Id
        AND LENGTH(jsonpayload.chat.applicationid) = 16
        -- [Shantanu | To Do] Filter to user initiated queries
        -- [Shantanu | To Do] Do not read gleanchat data even for backfilling if
                    -- date is after YYYYMMDD
    GROUP BY
        1, 2, 3, 4

),
app_usage_from_chat_1_5 AS (

    SELECT DISTINCT
        datepartition
        , jsonpayload.workflowrun.runid AS run_id
        , resource.labels.project_id AS project_id
        , jsonPayload.user.userid AS user_id
        , jsonPayload.workflowrun.applicationid AS workflow_id
    FROM
        glean_customer_event
        , UNNEST(jsonpayload.workflowrun.workflowexecutions) AS workflow_execution
    WHERE
        jsonPayload.type = 'WORKFLOW_RUN'
        and jsonPayload.workflowrun.initiator = 'USER'
        AND jsonPayload.workflowrun.applicationid IS NOT NULL
        AND jsonPayload.workflowrun.applicationid != ''
        AND workflow_execution.status = 'SUCCESS'

),
app_usage AS (

    SELECT
        datepartition
        , project_id
        , user_id
        , workflow_id
        -- for ai app usage , num_all_agent_runs and num_agent_runs are same
        , COUNT(DISTINCT run_id) AS num_all_agent_runs
        , COUNT(DISTINCT run_id) AS num_agent_runs
    FROM (
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_gleanchat
        UNION ALL
        SELECT
            datepartition
            , project_id
            , user_id
            , workflow_id
            , run_id
        FROM
            app_usage_from_chat_1_5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_and_app_usage AS (

    SELECT
        COALESCE(agu.datepartition, apu.datepartition) AS datepartition
        , COALESCE(agu.user_id, apu.user_id) AS user_id
        , COALESCE(agu.project_id, apu.project_id) AS project_id
        , COALESCE(agu.workflow_id, apu.workflow_id) AS workflow_id
        -- Only rely on ai apps data if we cant find any agent usage data for it that day
        , IF(agu.num_all_agent_runs > 0, agu.num_all_agent_runs, COALESCE(apu.num_all_agent_runs, 0)) AS num_all_agent_runs
        , IF(agu.num_agent_runs > 0, agu.num_agent_runs, COALESCE(apu.num_agent_runs, 0)) AS num_agent_runs
    FROM
        agent_usage AS agu
    FULL OUTER JOIN
        app_usage AS apu
    ON
        agu.datepartition = apu.datepartition
        AND agu.user_id = apu.user_id
        AND agu.project_id = apu.project_id
        AND agu.workflow_id = apu.workflow_id

),
agent_feedback AS (

    SELECT
        datepartition
        , project_id
        , workflow_id
        , user_id
        , SUM(CASE WHEN vote = 'UPVOTE' THEN 1 ELSE 0 END) AS num_upvotes
        , SUM(CASE WHEN vote = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_downvotes
    FROM (
        SELECT
            datepartition
            -- group by message_id to avoid duplicate feedbacks
            , jsonPayload.chatfeedback.messageid AS message_id
            -- coalesce for backward compatibility with workflowid and agentid
            , COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) AS workflow_id
            , resource.labels.project_id AS project_id
            , jsonPayload.user.userid AS user_id
            -- take latest vote. disregard manual feedback
            , MAX_BY(jsonPayload.chatfeedback.event, timestamp) AS vote
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'CHAT_FEEDBACK'
            AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
        GROUP BY
            1, 2, 3, 4, 5
    )
    GROUP BY
        1, 2, 3, 4

),
agent_usage_and_feedback AS (

    SELECT
        COALESCE(agent_and_app_usage.datepartition, agent_feedback.datepartition) AS datepartition
        , COALESCE(agent_and_app_usage.project_id, agent_feedback.project_id) AS project_id
        , COALESCE(agent_and_app_usage.user_id, agent_feedback.user_id) AS user_id
        , COALESCE(agent_and_app_usage.workflow_id, agent_feedback.workflow_id) AS workflow_id
        , COALESCE(agent_and_app_usage.num_all_agent_runs, 0) AS num_all_agent_runs
        , COALESCE(agent_and_app_usage.num_agent_runs, 0) AS num_agent_runs
        , COALESCE(agent_feedback.num_upvotes, 0) AS num_upvotes
        , COALESCE(agent_feedback.num_downvotes, 0) AS num_downvotes
    FROM
        agent_and_app_usage
    FULL OUTER JOIN
        agent_feedback
    ON
        agent_and_app_usage.datepartition = agent_feedback.datepartition
        AND agent_and_app_usage.user_id = agent_feedback.user_id
        AND agent_and_app_usage.project_id = agent_feedback.project_id
        AND agent_and_app_usage.workflow_id = agent_feedback.workflow_id

),
_precomp_agents_activity_precomputation AS (

    SELECT
        agent_usage_and_feedback.datepartition
        , agent_usage_and_feedback.project_id
        , COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, agent_usage_and_feedback.user_id) AS user_id
        , agent_usage_and_feedback.workflow_id
        , SUM(agent_usage_and_feedback.num_all_agent_runs) AS num_all_agent_runs
        , SUM(agent_usage_and_feedback.num_agent_runs) AS num_agent_runs
        , SUM(agent_usage_and_feedback.num_upvotes) AS num_upvotes
        , SUM(agent_usage_and_feedback.num_downvotes) AS num_downvotes
    FROM
        agent_usage_and_feedback
    LEFT JOIN
        id_to_alias
    ON
        agent_usage_and_feedback.user_id = id_to_alias.aliasid
        AND agent_usage_and_feedback.project_id = id_to_alias.project_id
        AND agent_usage_and_feedback.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, agent_usage_and_feedback.user_id) = latest_orgchart_data.loggingid
    GROUP BY 1, 2, 3, 4

),
all_agents AS (
SELECT
    datepartition
    , jsonPayload.productsnapshot.workflow.workflowid AS workflow_id
    , jsonPayload.productsnapshot.workflow.name
    , PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) AS created_at
    , IF(PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) = DATE '0001-01-01', NULL, jsonPayload.productsnapshot.workflow.createdby) AS created_by
    , jsonPayload.productsnapshot.workflow.namespaceenum AS workflow_type
    , jsonPayload.productsnapshot.workflow.namespaceenum = 'AGENT'
        AND PARSE_DATE('%Y-%m-%d', SUBSTR(jsonPayload.productsnapshot.workflow.createdat, 1, 10)) != DATE '0001-01-01' AS is_agent
FROM
    glean_customer_event
WHERE
    jsonPayload.type = 'PRODUCT_SNAPSHOT'
    AND jsonPayload.productsnapshot.type = 'WORKFLOW'
),
canonicalized_active_usage AS (
    SELECT
        *
    FROM
        canonicalized_feature_usage c
    WHERE
        c.num_searches > 0 OR c.num_chats > 0 OR c.num_client_active_sessions > 0 OR c.num_slackbot_useful_responses > 0 OR c.is_active_other
),
agents_activity_precomputation AS (
    SELECT
        _precomp_agents_activity_precomputation.*
    FROM
        _precomp_agents_activity_precomputation
    INNER JOIN
        (SELECT DISTINCT workflow_id AS agent_workflow_id FROM all_agents WHERE is_agent) AS a
    ON
        _precomp_agents_activity_precomputation.workflow_id = agent_workflow_id
    WHERE
        datepartition BETWEEN DATE(start_date) AND DATE(end_date)
        AND (num_agent_runs > 0 OR num_all_agent_runs > 0)
        AND 1=1
),
agent_runs AS (
    SELECT
        user_id
        , COUNT(DISTINCT CASE WHEN num_agent_runs > 0 THEN workflow_id END) AS AgentsUsedCount
        , COUNT(DISTINCT CASE WHEN num_agent_runs > 0 THEN datepartition END) AS AgentRunDaysCount
        , SUM(num_agent_runs) AS RunCount
        , SUM(num_all_agent_runs) AS AllRunCount
    FROM
        agents_activity_precomputation
    GROUP BY
        1
),
agent_creations AS (
    SELECT
        created_by AS user_id
        , COUNT(DISTINCT workflow_id) AS AgentsCreatedCount
    FROM (
        SELECT
            workflow_id
            , MIN(created_at) AS created_at
            , MIN(created_by) AS created_by
        FROM
            all_agents
        WHERE
            is_agent
        GROUP BY
            1
    )
    WHERE
        created_at BETWEEN DATE(start_date) AND DATE(end_date)
        AND 1=1
    GROUP BY
        1
)
SELECT
    o.userid AS UserId
    , o.department AS DepartmentName
    , COALESCE(ar.AgentsUsedCount, 0) AS AgentsUsedCount
    , COALESCE(ar.AgentRunDaysCount, 0) AS AgentRunDaysCount
    , COALESCE(ar.RunCount, 0) AS RunCount
    , COALESCE(ar.AllRunCount, 0) AS AllRunCount
    , COALESCE(ac.AgentsCreatedCount, 0) AS AgentsCreatedCount
FROM
    glean_customer_event.latest_orgchart_data o
LEFT JOIN
    (SELECT DISTINCT userid FROM canonicalized_active_usage) au
ON
    au.userid = o.userid
LEFT JOIN
    agent_runs ar
ON
    o.userid = ar.user_id
LEFT JOIN
    agent_creations ac
ON
    o.userid = ac.user_id
WHERE
    1=1
    -- Users with AU-qualifying activity should never be considered not-signed-up.
    -- TODO: resolve the KI where users can be active on gleanbot without a signup time
    -- Also include users that have run agents as AU-qualifying activity.
    AND (o.signuptime IS NOT NULL OR au.userid IS NOT NULL OR ar.RunCount > 0)
ORDER BY
    3 DESC

Chat Datasources

  • Output: Number of chat citations per datasource
  • Grain: One row per datasource
  • Use Case: Understand which datasources are most cited in chat responses
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
chat_datasources AS (
SELECT
    citations.datepartition,
    o.department,
    citations.datasource,
    COUNT(DISTINCT CONCAT(citations.chatsessionid, '|', citations.docid)) AS num_citations
FROM (
    SELECT
        COALESCE(c.datepartition, w.datepartition) AS datepartition,
        COALESCE(c.userid, w.userid) AS userid,
        COALESCE(c.chatsessionid, w.chatsessionid) AS chatsessionid,
        COALESCE(c.docid, w.docid) AS docid,
        COALESCE(c.datasource, w.datasource) AS datasource
    FROM
        (
            SELECT
                datepartition,
                jsonPayload.user.userid,
                jsonPayload.chatcitations.chatsessionid,
                chat_citation.sourcedocument.id AS docid,
                chat_citation.sourcedocument.datasource
            FROM
                glean_customer_event
            CROSS JOIN
                UNNEST(jsonPayload.chatcitations.citations) AS chat_citation
            WHERE
                jsonPayload.type = 'CHAT_CITATIONS'
                AND jsonPayload.chatcitations.chatsessionid IS NOT NULL
                AND chat_citation.sourcedocument.id IS NOT NULL
                AND chat_citation.sourcedocument.datasource IS NOT NULL
        ) c
    FULL OUTER JOIN
        (
            SELECT
                DISTINCT datepartition,
                userid,
                chatsessionid,
                docid,
                datasource
            FROM (
                SELECT
                    datepartition,
                    jsonPayload.user.userid,
                    jsonPayload.workflow.chatsessionid,
                    workflow_citation.sourcedocument.id AS docid,
                    workflow_citation.sourcedocument.datasource
                FROM
                    glean_customer_event, UNNEST(jsonPayload.workflow.citations) AS workflow_citation
                WHERE
                    jsonPayload.workflow.workflowid IN ('DOC_CONTEXT_READER', 'ORIGINAL_MESSAGE_SEARCH', 'DIRECT_LLM_RESPONSE', 'REACT_TOOLS_2_HOPS','DEFAULT_CHAT','WORLD_MODE_V2','DEEP_RESEARCH_PYAGENT','DEEP_RESEARCH_PREVIEW')
                    AND jsonPayload.workflow.initiator = 'USER'
                    AND jsonPayload.workflow.chatsessionid IS NOT NULL
                    AND workflow_citation.sourcedocument.id IS NOT NULL
                    AND workflow_citation.sourcedocument.datasource IS NOT NULL
                UNION ALL
                SELECT
                    datepartition,
                    jsonPayload.user.userid,
                    jsonPayload.workflowrun.chatsessionid,
                    step_citation.sourcedocument.id AS docid,
                    step_citation.sourcedocument.datasource
                FROM
                    glean_customer_event,
                    UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution,
                    UNNEST(jsonPayload.workflowrun.stepexecutions) AS step_execution,
                    UNNEST(step_execution.citations) AS step_citation
                WHERE
                    jsonPayload.type = 'WORKFLOW_RUN'
                    AND jsonPayload.workflowrun.initiator = 'USER'
                    AND workflow_execution.workflowid IN ('DOC_CONTEXT_READER', 'ORIGINAL_MESSAGE_SEARCH', 'DIRECT_LLM_RESPONSE', 'REACT_TOOLS_2_HOPS','DEFAULT_CHAT','WORLD_MODE_V2','DEEP_RESEARCH_PYAGENT','DEEP_RESEARCH_PREVIEW')
            )
        ) w
    ON
        c.datepartition = w.datepartition
        AND c.userid = w.userid
        AND c.chatsessionid = w.chatsessionid
        AND c.docid = w.docid
        AND c.datasource = w.datasource
) AS citations
LEFT JOIN
    id_to_alias
ON
    citations.userid = id_to_alias.aliasid
    AND citations.datepartition = id_to_alias.datepartition
LEFT JOIN
    glean_customer_event.latest_orgchart_data AS o
ON
    COALESCE(id_to_alias.canonicalid, citations.userid) = o.userid
    OR COALESCE(id_to_alias.canonicalid, citations.userid) = o.loggingid
WHERE
    COALESCE(citations.datasource, '') != ''
GROUP BY
    1, 2, 3
)
SELECT
    datasource AS Datasource,
    SUM(num_citations) AS NumUses
FROM
    chat_datasources
WHERE
    datepartition BETWEEN DATE(start_date) AND DATE(end_date)
    AND (1=1)
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 100

Shortcuts

  • Output: Visit count and unique visitor count per shortcut
  • Grain: One row per shortcut
  • Use Case: Measure shortcut engagement and identify popular shortcuts
DECLARE start_date DATE DEFAULT DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
DECLARE end_date DATE DEFAULT CURRENT_DATE();

WITH
glean_customer_event AS (

    SELECT
        resource,
        DATE(DATE_TRUNC(timestamp, DAY)) AS datepartition,
        jsonPayload,
        timestamp,
    FROM `<glean_customer_event_table>`
    -- This filter is not strictly necessary - the external table enforces partition filtering via URI definitions.
    WHERE DATE(DATE_TRUNC(timestamp, DAY)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 270 DAY) AND CURRENT_DATE()

),
id_to_alias AS (

    SELECT DISTINCT
        datepartition,
        project_id,
        aliasid,
        userid AS canonicalid
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.productsnapshot.user.id AS userid,
            jsonPayload.productsnapshot.user.aliasids
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'PRODUCT_SNAPSHOT'
            AND jsonPayload.productsnapshot.type = 'USER'
    ), UNNEST(aliasids) AS aliasid

),
chat_usage AS (

    SELECT
        COALESCE(wf.datepartition, chat.datepartition) AS datepartition,
        COALESCE(wf.project_id, chat.project_id) AS project_id,
        COALESCE(wf.userid, chat.userid) AS userid,
        COUNT(DISTINCT wf.run_id) + COUNT(DISTINCT CASE WHEN wf.run_id IS NULL THEN chat.qtt END) AS num_chat_queries
    FROM (
      SELECT
        jsonPayload.workflow.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        MIN(datepartition) AS datepartition
      FROM glean_customer_event
      WHERE jsonPayload.workflow.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
        AND jsonPayload.workflow.initiator = 'USER'
      GROUP BY 1, 2, 3
      UNION ALL
      SELECT
        DISTINCT jsonPayload.workflowrun.runid AS run_id,
        jsonPayload.user.userid,
        resource.labels.project_id,
        datepartition
      FROM glean_customer_event, UNNEST(jsonPayload.workflowrun.workflowexecutions) AS workflow_execution
      WHERE jsonPayload.type = 'WORKFLOW_RUN'
        AND jsonPayload.workflowrun.initiator = 'USER'
        AND workflow_execution.workflowid IN (
          'DOC_CONTEXT_READER',
          'ORIGINAL_MESSAGE_SEARCH',
          'DIRECT_LLM_RESPONSE',
          'REACT_TOOLS_2_HOPS',
          'DEFAULT_CHAT',
          'WORLD_MODE_V2',
          'DEEP_RESEARCH_PYAGENT',
          'DEEP_RESEARCH_PREVIEW'
        )
    ) wf
    FULL OUTER JOIN (
      SELECT
        datepartition,
        resource.labels.project_id,
        jsonPayload.user.userid,
        jsonPayload.chat.qtt AS qtt,
        jsonPayload.chat.workflowrunid AS workflowrunid
      FROM glean_customer_event
      WHERE jsonPayload.type = 'CHAT'
        AND jsonPayload.chat.initiator = 'USER'
    ) chat
    ON wf.run_id = chat.workflowrunid
    GROUP BY 1, 2, 3

),
other_feature_usage AS (

    SELECT
        gce.datepartition,
        gce.resource.labels.project_id,
        gce.jsonPayload.user.userid,
        COUNT(
            DISTINCT CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND (
                    gce.jsonPayload.search.initiator IN ('USER', 'PAGE_LOAD', 'ONBOARDING')
                        AND LOWER(gce.jsonPayload.Search.modality) NOT IN
                            ('gleanbot', 'slackbot_command', 'slackbot_leaderboard', 'slackbot_retry', '')
                    )
            ) THEN gce.jsonPayload.search.trackingtoken END
        ) + COUNT(
            CASE WHEN (
                gce.jsonPayload.type = 'SEARCH'
                    AND gce.jsonPayload.search.isrestclientapi
            ) THEN 1 END
        ) AS num_searches,
        COUNT(
            DISTINCT CASE WHEN (
                -- Depending on category, opening links/documents counts towards DAU
                gce.jsonPayload.clientevent.event IN ('OpenDocument', 'OpenLink')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Search Result'
                    , 'Autocomplete'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    , 'New Tab Page'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    , 'Featured Question and Answer'
                    , 'Generated Question and Answer'
                    , 'Pins'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Verification'
                    , 'Datasource Auth'
                    , 'Insights'
                    -- Feature related interactions count towards DAU
                    , 'Chat'
                    , 'Result Preview'
                    , 'App Card'
                    , 'Customer Card'
                    , 'Search'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            OR (
                --  Depending on category, certain feature related clicks count towards DAU
                gce.jsonPayload.clientevent.event IN ('Click')
                AND gce.jsonPayload.clientevent.category IN (
                    -- Autocomplete and Search interactions count towards DAU
                    'Autocomplete'
                    , 'Search Result'
                    , 'Datasource Filter'
                    , 'Facets'
                    -- New tab page(NTP) and Homepage interactions count towards DAU
                    , 'Feed'
                    , 'Calendar'
                    -- Directory tab interactions count towards DAU
                    , 'Org Chart'
                    , 'Person Card'
                    , 'Teams'
                    , 'Profile'
                    , 'People Celebrations'
                    , 'Person Attribution'
                    -- Sidebar interactions count towards DAU
                    , 'Sidebar Tabs'
                    -- User Generated Content(UGC) interactions count towards DAU
                    , 'Announcements'
                    , 'Answers'
                    , 'Collections'
                    -- Golinks interactions counts towards DAU
                    , 'Shortcuts'
                    -- Admin and Setup page interactions count towards DAU
                    , 'Datasource Auth'
                    , 'User Menu'
                    , 'Admin Console'
                    -- Other tangible user interactions that count towards DAU
                    , 'Feedback'
                )
            )
            -- CRUD operations on User Generated Content(UGC) always count always count towards DAU
            OR (
                gce.jsonPayload.clientevent.event IN ('Add', 'Create', 'Delete')
                AND gce.jsonPayload.clientevent.category IN ('Announcements', 'Answers', 'Collections')
            )
            OR (
                gce.jsonPayload.clientevent.event IN ('View')
                AND gce.jsonPayload.clientevent.category IN (
                    -- User Generated Content(UGC) interactions count towards DAU
                    'Announcements'
                    ,'Answers'
                    ,'Collections'
                    -- Directory tab interactions count towards DAU
                    ,'Person Card'
                    ,'Team Card'
                    ,'Org Chart'
                )
                AND gce.jsonPayload.clientevent.pagepath NOT IN ('/', '/ntp', '/search')
            )
            /* Summarization expansion */
            OR (gce.jsonPayload.clientevent.event = 'Expand' AND gce.jsonPayload.clientevent.category = 'Summary' AND jsonPayload.clientevent.uielement = 'summarize-card')
            /* Counts Start events (user chat message in Chat tab) and Expand events (prompt expansion in Discover tab) from Sidebar V2 */
            OR (gce.jsonPayload.clientevent.event in ('Start', 'Expand') AND gce.jsonPayload.clientevent.category = 'Sidebar V2')
            /* Counts Start events (user query or preset click) from Inline Menu */
            OR (gce.jsonPayload.clientevent.event = 'Start' AND gce.jsonPayload.clientevent.category = 'Inline Menu')
            /* Counts visits to past chats via GleanChat Conversation History */
            OR (gce.jsonPayload.clientevent.event = 'Click' AND gce.jsonPayload.clientevent.category = 'Chat' AND jsonPayload.clientevent.uielement = 'chats-menu')
            THEN gce.jsonPayload.clientevent.SessionTrackingToken END
        ) AS num_client_active_sessions,
        COUNT(
            CASE WHEN (
                gce.jsonPayload.Type IN ('SEARCH_CLICK','CHAT_FEEDBACK','SEARCH_FEEDBACK')
                OR gce.jsonPayload.Type IN ('SHORTCUT')
                    AND gce.jsonPayload.shortcut.event IN ('REDIRECT', 'CREATE', 'DELETE', 'UPDATE')
            ) THEN 1 END
        ) >= 1 AS is_active_other
    FROM
        glean_customer_event gce
    WHERE
        gce.jsonPayload.type NOT IN ('CHAT','WORKFLOW')
    GROUP BY
        1, 2, 3

),
slackbot_usage AS (

    WITH event_traces AS (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.gleanbotactivity.eventtrackingtoken,
            jsonPayload.gleanbotactivity.responseevents,
            jsonPayload.gleanbotactivity.eventtype,
            jsonPayload.gleanbotactivity.workflowexecutionpoints,
            jsonPayload.gleanbotactivity.stt
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'GLEAN_BOT_ACTIVITY'
            AND LOWER(jsonPayload.gleanbotactivity.source) = 'slack'
    ),
    slack_reactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN bot_responded THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_reactive_bot_responses
        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                'REACTIVE_ACT_MESSAGE' IN UNNEST(message_data.responseevents)                            -- Messages that got a successful response from the bot should be counted
                    OR 'REACTIVE_GENERATION_RESPONSE_MODAL' IN UNNEST(message_data.responseevents)       -- Gleanbot added value to users other than the question asker by generating responses for them
                    OR 'COMMAND_SEARCH_RESULTS_MESSAGE' IN UNNEST(message_data.responseevents)           -- Messages that were triggered through a /glean command and got results as response
                    OR 'COMMAND_SEARCH_UPDATE_MODAL_WITH_RESULTS' IN UNNEST(message_data.responseevents) -- Messages that were triggered through a /glean command and got results as response on retry
                    OR 'COMMAND_WORKFLOW_SUCCESS' IN UNNEST(message_data.responseevents)                 -- Response was successfully generated after user queried through glean console
                    OR 'DISCUSSION_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                  -- [Slack Compete] Response to summarize a thread discussion was successfully sent through glean DM
                    OR 'SINGLE_CHANNEL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)              -- [Slack Compete] Response to summarize a channel discussion was successfully sent through glean DM
                    OR 'DOC_URL_SUMMARY_SENT' IN UNNEST(message_data.responseevents)                     -- [Slack Compete] Response to summarize a uploaded doc discussion was successfully sent through glean DM
                    AS bot_responded,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints) AS response_downvoted, -- Response was dismissed by the user
                'SHOW_SOURCES_CLICK_SUCCESS' IN UNNEST(interaction_data.workflowexecutionpoints) AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful -- Response was voted as not helpful
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack reactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'REACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)                     -- Identify messages where reactive workflow started successfully
                        OR 'REACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)             -- Identify messages where reactive workflow for assistant type started
                        OR 'REACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where reactive workflow for search type started
                        OR 'COMMAND_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)            -- Identify messages where /glean command was used to initiate a reactive search
                        OR 'COMMAND_DISCUSSION_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)        -- Identify messages where glean console was used to summarize a discussion/query
                        OR 'COMMAND_CHANNEL_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where glean console was used to summarize a channel
                        OR 'COMMAND_DOC_SUMMARIZE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)     -- Identify messages where glean console was used to summarize an attached/shared doc
                        OR eventtype IN (
                            'TAGGED_MESSAGE'           -- Identify messages where @glean was mentioned
                            , 'GENERATE_ANSWER'        -- Identify messages where someone clicked on generate answer button
                            , 'COMMAND'                -- Identify messages where /glean was mentioned
                            , 'DM_TO_GLEANBOT_MESSAGE' -- [Slack Compete] Identify messages where user sent DM to glean bot with a query
                        )
                    )
                    AND NOT 'REACTIVE_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints)                      -- Remove the events where reactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'REACTIVE_DISABLED_FAILURE_FOR_USER' IN UNNEST(workflowexecutionpoints)             -- Remove the events where reactive workflow cannont be triggered for the user Eg: Insufficient permissions
                    AND NOT 'COMMAND_BAD_REQUEST' IN UNNEST(workflowexecutionpoints)                            -- Remove the event where /glean command was triggered in an invalid channel/by invalid user
                    AND NOT 'COMMAND_SEARCH_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints)    -- Remove cases where /glean command failed to load results
                    AND NOT 'COMMAND_SEARCH_NO_RESULTS_MODAL_UPDATE_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove cases where /glean command failed to update and dispaly results
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE eventtype IN (
                    'SHOW_SOURCES'        -- All events where a user clicked on show sources modal
                    , 'SHARE_HELPFULNESS' -- All events for which helpful/not helpful buttons click was initiated
                    , 'SHARE_CLICK'       -- All events for which sharing workflow was started
                    , 'SUBMIT_FEEDBACK'   -- All events for which manual feedback workflow was started
                )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition,
            project_id,
            userid
    ),
    slack_proactive_bot_activity AS (
        SELECT
            datepartition,
            project_id,
            userid,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses,
            COUNT(DISTINCT CASE
                WHEN response_downvoted THEN NULL
                WHEN voted_helpful THEN eventtrackingtoken
                WHEN citations_shown THEN eventtrackingtoken
                WHEN response_shared THEN eventtrackingtoken
                WHEN bot_responded_on_users_request AND NOT voted_not_helpful AND NOT digest_consumed THEN eventtrackingtoken
                ELSE NULL END) AS num_useful_responses_without_digest,
            COUNT(DISTINCT CASE
                WHEN voted_not_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_downvotes,
            COUNT(DISTINCT CASE
                WHEN voted_helpful THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_upvotes,
            COUNT(DISTINCT CASE
                WHEN bot_responded THEN eventtrackingtoken
                ELSE NULL END) AS num_slack_proactive_bot_responses

        FROM (
            SELECT
                message_data.datepartition,
                message_data.project_id,
                message_data.userid,
                message_data.eventtrackingtoken,
                message_data.eventtype IN ('NON_TAGGED_MESSAGE', 'PROACTIVE_DISCUSSION_SUMMARIZER') AS workflow_started,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'PROACTIVE_MESSAGE' IN UNNEST(message_data.responseevents)
                    AS bot_responded,
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    OR 'VIEW_DIGEST' IN UNNEST(message_data.responseevents)
                    AS bot_responded_on_users_request,
                interaction_data.eventtype = 'SHARE_CLICK' AS response_shared, -- Response was shared by the user
                'SUBMIT_FEEDBACK_WORKFLOW_DOWNVOTE' IN UNNEST(interaction_data.workflowexecutionpoints)
                    OR interaction_data.eventtype = 'DISMISS_SUGGESTION'
                    AS response_downvoted, -- Response was dismissed by the user
                interaction_data.eventtype = 'SHOW_SOURCES' AS citations_shown, -- Response was checked for its citation source
                'SHARE_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_helpful, -- Response was voted as helpful
                'SHARE_NOT_HELPFUL' IN UNNEST(interaction_data.responseevents) AS voted_not_helpful, -- Response was voted as not helpful
                'DAILY_DIGEST_REMINDER_SENT' IN UNNEST(message_data.responseevents) AS digest_sent, -- Bot sent user daily digest over DM
                'VIEW_DIGEST' IN UNNEST(message_data.responseevents) AS digest_consumed, -- Digest was opened and viewed by the user
                'DISCUSSION_SUMMARY_THREAD_SUMMARY_SENT' IN UNNEST(message_data.responseevents)
                    OR 'DISCUSSION_SUMMARY_DM_RESPONSE_SENT' IN UNNEST(message_data.responseevents)
                    AS proactive_summary_sent
            FROM (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                -- Identify the set of valid slack proactive bot workflow starting points that could potentitally contribute to active users definition
                    (
                        'PROACTIVE_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)           -- Identify messages where proactive workflow started
                        OR 'PROACTIVE_CHAT_WORKFLOW_START' IN UNNEST(workflowexecutionpoints)   -- Identify messages where proactive workflow for assistant type started
                        OR 'PROACTIVE_SEARCH_WORKFLOW_START' IN UNNEST(workflowexecutionpoints) -- Identify messages where proactive workflow for search type started
                        OR eventtype IN (
                            'NON_TAGGED_MESSAGE'                -- All messages that were not DMs and did not mention @Glean or \glean fall in this category
                            , 'PROACTIVE_DISCUSSION_SUMMARIZER' -- All events for which proactive thread summarizer workflow is initiated
                            , 'VIEW_DIGEST_CLICK'               -- All events where proactive digest was clicked
                            , 'DAILY_DIGEST_REMINDER'           -- All events where digest was subscribed to and thus proactively sent over DM
                        )
                    )
                    AND NOT 'PROACTIVE_BOT_DISABLED_FAILURE' IN UNNEST(workflowexecutionpoints) -- Remove the events where proactive workflow cannont be triggered. Eg: Invalid Channel
                    AND NOT 'DROP_BOT_MESSAGE' IN UNNEST(workflowexecutionpoints)               -- Remove the events which represent messages sent by other bots, so we dont converse with slack automations
                    AND NOT 'DROP_EXTERNAL_CHANNEL_MESSAGE' IN UNNEST(workflowexecutionpoints)  -- Remove the events that correspond to messages sent on external channels.
            ) AS message_data
            LEFT JOIN (
                SELECT
                    *
                FROM
                    event_traces
                WHERE
                    eventtype IN (
                        'SHOW_SOURCES'         -- All events where a user clicked on show sources modal
                        , 'SHARE_HELPFULNESS'  -- All events for which helpful/not helpful buttons click was initiated
                        , 'SHARE_CLICK'        -- All events for which sharing workflow was started
                        , 'SUBMIT_FEEDBACK'    -- All events for which manual feedback workflow was started
                        , 'DISMISS_SUGGESTION' -- All events for which dismiss suggestion workflow was initiated
                    )
            ) AS interaction_data
            ON
                message_data.project_id = interaction_data.project_id
                AND message_data.eventtrackingtoken = interaction_data.stt
        )
        GROUP BY
            datepartition, project_id, userid
    )
    SELECT
        COALESCE(p.datepartition, r.datepartition) AS datepartition,
        COALESCE(p.project_id, r.project_id) AS project_id,
        COALESCE(p.userid, r.userid) AS userid,
        COALESCE(r.num_useful_responses, 0) AS reactive_num_useful_responses,
        COALESCE(p.num_useful_responses, 0) AS proactive_num_useful_responses,
        COALESCE(p.num_useful_responses_without_digest, 0) AS proactive_num_useful_responses_without_digest,
        COALESCE(r.num_useful_responses, 0) + COALESCE(p.num_useful_responses, 0) AS total_num_useful_responses,
        COALESCE(r.num_slack_reactive_bot_downvotes, 0)+ COALESCE(p.num_slack_proactive_bot_downvotes, 0) AS total_num_slackbot_downvotes,
        COALESCE(r.num_slack_reactive_bot_upvotes, 0)+ COALESCE(p.num_slack_proactive_bot_upvotes, 0) AS total_num_slackbot_upvotes,
        COALESCE(r.num_slack_reactive_bot_responses, 0)+ COALESCE(p.num_slack_proactive_bot_responses, 0) AS total_num_slackbot_responses
    FROM slack_proactive_bot_activity p
    FULL OUTER JOIN slack_reactive_bot_activity r
    ON p.datepartition = r.datepartition
    AND p.project_id = r.project_id
    AND p.userid = r.userid

),
ai_summarizations AS (

    SELECT
        summ_runs.datepartition,
        summ_runs.project_id,
        summ_runs.userid,
        COUNT(DISTINCT summ_runs.run_id) AS num_summarizations
    FROM (
        SELECT
            jsonPayload.workflow.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            MIN(datepartition) AS datepartition
        FROM
            glean_customer_event
        WHERE
            jsonPayload.workflow.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
            AND jsonPayload.workflow.initiator IN ('USER', 'SUMMARIZE')
        GROUP BY
            1, 2, 3
        UNION ALL
        SELECT DISTINCT
            jsonPayload.workflowrun.runid AS run_id,
            resource.labels.project_id,
            jsonPayload.user.userid,
            datepartition
        FROM
            glean_customer_event,
            UNNEST(jsonPayload.workflowrun.stepexecutions) AS stepexecutions
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.initiator IN ('USER', 'SUMMARIZE')
            AND stepexecutions.workflowid IN (
                'SUMMARIZE',
                'MEETING_SUMMARIZER',
                'DISCUSSION_SUMMARIZER',
                'MULTI_QUERY_SUMMARIZER'
            )
    ) summ_runs
    GROUP BY
        1, 2, 3

),
ai_answers AS (

    SELECT
        COALESCE(waa.datepartition, aa.datepartition) AS datepartition,
        COALESCE(waa.project_id, aa.project_id) AS project_id,
        COALESCE(waa.userid, aa.userid) AS userid,
        COUNT(DISTINCT waa.runid) + COUNT(DISTINCT CASE WHEN waa.runid IS NULL THEN aa.trackingtoken END) AS num_ai_answers
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.workflowrun.runid,
            jsonPayload.workflowrun.sourcetrackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'WORKFLOW_RUN'
            AND jsonPayload.workflowrun.feature = 'AI_ANSWER'
            AND jsonPayload.workflowrun.platform = 'WEB'
            AND jsonPayload.workflowrun.initiator = 'GLEAN'
    ) waa
    FULL OUTER JOIN (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            jsonPayload.aianswer.trackingtoken
        FROM
            glean_customer_event
        WHERE
            jsonPayload.type = 'AI_ANSWER'
            AND COALESCE(jsonPayload.aianswer.trackingtoken, '') != ''
    ) aa
    ON
        waa.project_id = aa.project_id
        AND waa.userid = aa.userid
        AND waa.sourcetrackingtoken = aa.trackingtoken
        AND waa.datepartition = aa.datepartition
    GROUP BY
        1, 2, 3

),
chat_feedback AS (

    SELECT
        datepartition,
        project_id,
        userid,
        SUM(CASE WHEN event = 'UPVOTE' THEN 1 ELSE 0 END) AS num_chat_upvotes,
        SUM(CASE WHEN event = 'DOWNVOTE' THEN 1 ELSE 0 END) AS num_chat_downvotes
    FROM (
        SELECT
            datepartition,
            resource.labels.project_id,
            jsonPayload.user.userid,
            COALESCE(
                jsonPayload.chatfeedback.runid,
                jsonPayload.chatfeedback.messageid,
                jsonPayload.aianswervote.trackingtoken,
                jsonPayload.aisummaryvote.trackingtoken
            ) AS requestid,
            -- take latest vote. disregard manual feedback
            MAX_BY(
                COALESCE(
                    jsonPayload.chatfeedback.event,
                    jsonPayload.aianswervote.vote,
                    jsonPayload.aisummaryvote.vote
                ),
                timestamp
            ) AS event
        FROM
            glean_customer_event
        WHERE
            (
                jsonPayload.type = 'CHAT_FEEDBACK'
                AND jsonPayload.chatfeedback.event IN ('UPVOTE', 'DOWNVOTE')
                -- coalesce for backward compatibility with workflowid and agentid
                AND COALESCE(jsonPayload.chatfeedback.agentid, jsonPayload.chatfeedback.workflowid) is NULL -- ignore feedback from agent workflows
            ) OR (
                jsonPayload.type = 'AI_ANSWER_VOTE'
                AND jsonPayload.aianswervote.vote IN ('UPVOTE', 'DOWNVOTE')
            ) OR (
                jsonPayload.type = 'AI_SUMMARY_VOTE'
                AND jsonPayload.aisummaryvote.vote IN ('UPVOTE', 'DOWNVOTE')
            )
        GROUP BY
            1, 2, 3, 4
    )
    GROUP BY
        1, 2, 3

),
feature_usage AS (

    WITH join_0 AS (
        SELECT
            COALESCE(other_feature_usage.datepartition, chat_usage.datepartition) AS datepartition,
            COALESCE(other_feature_usage.project_id, chat_usage.project_id) AS project_id,
            COALESCE(other_feature_usage.userid, chat_usage.userid) AS userid,
            COALESCE(other_feature_usage.num_searches, 0) AS _num_searches,
            COALESCE(other_feature_usage.num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(other_feature_usage.is_active_other, FALSE) AS _is_active_other,
            COALESCE(chat_usage.num_chat_queries, 0) AS _num_chats
        FROM
            other_feature_usage
        FULL OUTER JOIN
            chat_usage
        ON
            other_feature_usage.datepartition = chat_usage.datepartition
            AND other_feature_usage.project_id = chat_usage.project_id
            AND other_feature_usage.userid = chat_usage.userid
    ),
    join_1 AS (
        SELECT
            COALESCE(join_0.datepartition, slackbot_usage.datepartition) AS datepartition,
            COALESCE(join_0.project_id, slackbot_usage.project_id) AS project_id,
            COALESCE(join_0.userid, slackbot_usage.userid) AS userid,
            COALESCE(join_0._num_searches, 0) AS _num_searches,
            COALESCE(join_0._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_0._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_0._num_chats, 0) AS _num_chats,
            COALESCE(slackbot_usage.total_num_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(slackbot_usage.total_num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(slackbot_usage.total_num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(slackbot_usage.total_num_slackbot_responses, 0) AS _num_slackbot_responses
        FROM
            join_0
        FULL OUTER JOIN
            slackbot_usage
        ON
            join_0.datepartition = slackbot_usage.datepartition
            AND join_0.project_id = slackbot_usage.project_id
            AND join_0.userid = slackbot_usage.userid
    ),
    join_2 AS (
        SELECT
            COALESCE(join_1.datepartition, ai_summarizations.datepartition) AS datepartition,
            COALESCE(join_1.project_id, ai_summarizations.project_id) AS project_id,
            COALESCE(join_1.userid, ai_summarizations.userid) AS userid,
            COALESCE(join_1._num_searches, 0) AS _num_searches,
            COALESCE(join_1._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_1._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_1._num_chats, 0) AS _num_chats,
            COALESCE(join_1._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_1._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_1._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_1._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(ai_summarizations.num_summarizations, 0) AS _num_summarizations
        FROM
            join_1
        FULL OUTER JOIN
            ai_summarizations
        ON
            join_1.datepartition = ai_summarizations.datepartition
            AND join_1.project_id = ai_summarizations.project_id
            AND join_1.userid = ai_summarizations.userid
    ),
    join_3 AS (
        SELECT
            COALESCE(join_2.datepartition, ai_answers.datepartition) AS datepartition,
            COALESCE(join_2.project_id, ai_answers.project_id) AS project_id,
            COALESCE(join_2.userid, ai_answers.userid) AS userid,
            COALESCE(join_2._num_searches, 0) AS _num_searches,
            COALESCE(join_2._num_client_active_sessions, 0) AS _num_client_active_sessions,
            COALESCE(join_2._is_active_other, FALSE) AS _is_active_other,
            COALESCE(join_2._num_chats, 0) AS _num_chats,
            COALESCE(join_2._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
            COALESCE(join_2._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
            COALESCE(join_2._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
            COALESCE(join_2._num_slackbot_responses, 0) AS _num_slackbot_responses,
            COALESCE(join_2._num_summarizations, 0) AS _num_summarizations,
            COALESCE(ai_answers.num_ai_answers, 0) AS _num_ai_answers
        FROM
            join_2
        FULL OUTER JOIN
            ai_answers
        ON
            join_2.datepartition = ai_answers.datepartition
            AND join_2.project_id = ai_answers.project_id
            AND join_2.userid = ai_answers.userid
    )

    SELECT
        COALESCE(join_3.datepartition, chat_feedback.datepartition) AS datepartition,
        COALESCE(join_3.project_id, chat_feedback.project_id) AS project_id,
        COALESCE(join_3.userid, chat_feedback.userid) AS userid,
        COALESCE(join_3._num_searches, 0) AS _num_searches,
        COALESCE(join_3._num_ai_answers, 0) AS _num_ai_answers,
        COALESCE(join_3._num_client_active_sessions, 0) AS _num_client_active_sessions,
        COALESCE(join_3._is_active_other, FALSE) AS _is_active_other,
        COALESCE(join_3._num_chats, 0) AS _num_chats,
        COALESCE(join_3._num_slackbot_useful_responses, 0) AS _num_slackbot_useful_responses,
        COALESCE(join_3._num_slackbot_downvotes, 0) AS _num_slackbot_downvotes,
        COALESCE(join_3._num_slackbot_upvotes, 0) AS _num_slackbot_upvotes,
        COALESCE(join_3._num_slackbot_responses, 0) AS _num_slackbot_responses,
        COALESCE(join_3._num_summarizations, 0) AS _num_summarizations,
        COALESCE(chat_feedback.num_chat_upvotes, 0) AS _num_chat_upvotes,
        COALESCE(chat_feedback.num_chat_downvotes, 0) AS _num_chat_downvotes
    FROM
        join_3
    FULL OUTER JOIN
        chat_feedback
    ON
        join_3.datepartition = chat_feedback.datepartition
        AND join_3.project_id = chat_feedback.project_id
        AND join_3.userid = chat_feedback.userid

),
canonicalized AS (

    SELECT
        feature_usage.datepartition,
        feature_usage.project_id,
        COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, feature_usage.userid) AS userid,
        COALESCE(SUM(_num_searches), 0) AS num_searches,
        COALESCE(SUM(_num_chats), 0) AS num_chats,
        COALESCE(SUM(_num_ai_answers), 0) AS num_ai_answers,
        COALESCE(SUM(_num_summarizations), 0) AS num_summarizations,
        COALESCE(SUM(_num_chat_upvotes), 0) AS num_chat_upvotes,
        COALESCE(SUM(_num_chat_downvotes), 0) AS num_chat_downvotes,
        COALESCE(SUM(_num_client_active_sessions), 0) AS num_client_active_sessions,
        COALESCE(SUM(_num_slackbot_useful_responses), 0) AS num_slackbot_useful_responses,
        COALESCE(SUM(_num_slackbot_downvotes), 0) AS num_slackbot_downvotes,
        COALESCE(SUM(_num_slackbot_upvotes), 0) AS num_slackbot_upvotes,
        COALESCE(SUM(_num_slackbot_responses), 0) AS num_slackbot_responses,
        COALESCE(LOGICAL_OR(_is_active_other), FALSE) AS is_active_other
    FROM
        feature_usage
    LEFT JOIN
        id_to_alias
    ON
        feature_usage.project_id = id_to_alias.project_id
        AND feature_usage.userid = id_to_alias.aliasid
        AND feature_usage.datepartition = id_to_alias.datepartition
    LEFT JOIN
        glean_customer_event.latest_orgchart_data AS latest_orgchart_data
    ON
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) = latest_orgchart_data.loggingid
    WHERE
        COALESCE(id_to_alias.canonicalid, feature_usage.userid) IS NOT NULL
    GROUP BY
        1, 2, 3
    HAVING
        COALESCE(SUM(_num_searches), 0) > 0
        OR COALESCE(SUM(_num_chats), 0) > 0
        OR COALESCE(SUM(_num_ai_answers), 0) > 0
        OR COALESCE(SUM(_num_summarizations), 0) > 0
        OR COALESCE(SUM(_num_client_active_sessions), 0) > 0
        OR COALESCE(SUM(_num_slackbot_useful_responses), 0) > 0
        OR COALESCE(SUM(_num_chat_upvotes), 0) > 0
        OR COALESCE(SUM(_num_chat_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_downvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_upvotes), 0) > 0
        OR COALESCE(SUM(_num_slackbot_responses), 0) > 0
        OR COALESCE(LOGICAL_OR(_is_active_other), FALSE)

),
shortcut_events AS (

    SELECT
        datepartition,
        jsonPayload.user.userid AS user_id,
        'SHORTCUT' AS ugc_type,
        CAST(CAST(jsonPayload.shortcut.id AS INT) AS STRING) AS ugc_id,
        UPPER(jsonPayload.shortcut.event) AS event_type,
        COUNT(*) AS frequency
    FROM
        glean_customer_event
    WHERE
        jsonPayload.type = 'SHORTCUT'
        AND UPPER(jsonPayload.shortcut.event) = ('REDIRECT')
        AND jsonPayload.shortcut.id IS NOT NULL
        AND jsonPayload.user.userid IS NOT NULL
    GROUP BY
        1, 2, 3, 4, 5

),
ugc_usage AS (
SELECT
    shortcut_events.datepartition,
    COALESCE(latest_orgchart_data.userid, id_to_alias.canonicalid, shortcut_events.user_id) AS user_id,
    shortcut_events.ugc_type,
    shortcut_events.ugc_id,
    shortcut_events.event_type,
    SUM(shortcut_events.frequency) AS frequency
FROM
    shortcut_events
LEFT JOIN
    id_to_alias
ON
    shortcut_events.user_id = id_to_alias.aliasid
    AND shortcut_events.datepartition = id_to_alias.datepartition
LEFT JOIN
    glean_customer_event.latest_orgchart_data AS latest_orgchart_data
ON
    COALESCE(id_to_alias.canonicalid, shortcut_events.user_id) = latest_orgchart_data.loggingid
WHERE
    COALESCE(id_to_alias.canonicalid, shortcut_events.user_id) IS NOT NULL
GROUP BY 1, 2, 3, 4, 5
)
SELECT
    CAST(u.ugc_id AS INT) AS ShortcutId,
    COALESCE(SUM(frequency), 0) AS VisitCount,
    COUNT(DISTINCT u.user_id) AS VisitorCount
FROM
    ugc_usage u
LEFT JOIN
    glean_customer_event.latest_orgchart_data o
ON
    u.user_id = o.userid
WHERE
    (1=1)
    AND u.ugc_type = 'SHORTCUT'
    AND u.datepartition BETWEEN DATE(start_date) AND DATE(end_date)
GROUP BY
    1
ORDER BY
    2 DESC
LIMIT 100