github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/analytics.ts (about)

     1  import { Action, Location } from "history"
     2  import {
     3    FilterLevel,
     4    filterSetFromLocation,
     5    FilterSource,
     6    isRegexp,
     7    TermState,
     8  } from "./logfilters"
     9  
    10  export const emptyTags = Object.freeze({})
    11  
    12  export type Tags = {
    13    [key: string]: string | undefined
    14    action?: AnalyticsAction | Action
    15    type?: AnalyticsType
    16  }
    17  
    18  // The `type` tag describes what section of the UI
    19  // that the analytics event takes place in
    20  export enum AnalyticsType {
    21    Account = "account",
    22    Cluster = "cluster",
    23    Detail = "resource-detail",
    24    Grid = "grid", // aka Table View
    25    Shortcut = "shortcuts",
    26    Unknown = "unknown",
    27    Update = "update",
    28  }
    29  
    30  // The `action` tag describes the type of UI interaction
    31  export enum AnalyticsAction {
    32    Click = "click",
    33    Close = "close",
    34    Collapse = "collapse",
    35    Edit = "edit",
    36    Expand = "expand",
    37    Load = "load",
    38    Shortcut = "shortcut",
    39    Star = "star",
    40    Unstar = "unstar",
    41    SidebarToggle = "sidebarToggle",
    42  }
    43  
    44  // Fire and forget all analytics events
    45  export const incr = (name: string, tags: Tags = {}): void => {
    46    let url = `//${window.location.host}/api/analytics`
    47  
    48    // Uncomment to debug analytics events
    49    // console.log("analytics event: \nname:", name, "\npayload:", tags)
    50  
    51    fetch(url, {
    52      method: "post",
    53      body: JSON.stringify([{ verb: "incr", name: name, tags: tags }]),
    54    })
    55  }
    56  
    57  export const pathToTag = (path: string): AnalyticsType => {
    58    if (path.indexOf("/") === 0) {
    59      path = path.substring(1) // chop off the leading /
    60    }
    61    let parts = path.split("/")
    62    if (parts[0] === "") {
    63      return AnalyticsType.Grid
    64    }
    65    if (parts[0] === "overview") {
    66      return AnalyticsType.Grid
    67    }
    68  
    69    if (parts[0] === "r") {
    70      if (parts[2] === "overview") {
    71        return AnalyticsType.Detail
    72      }
    73    }
    74  
    75    return AnalyticsType.Unknown
    76  }
    77  
    78  export let navigationToTags = (
    79    location: Location,
    80    action: AnalyticsAction | Action
    81  ): Tags => {
    82    let tags: Tags = { type: pathToTag(location.pathname) }
    83  
    84    // If the location has a `state`, use the `action` property for the analytics event
    85    const locationAction: Action | undefined = location.state
    86      ? (location as Location<{ action?: Action }>).state?.action
    87      : undefined
    88    if (action === "PUSH" && locationAction) {
    89      tags.action = locationAction
    90    }
    91  
    92    let filterSet = filterSetFromLocation(location)
    93    if (filterSet.level != FilterLevel.all) {
    94      tags.level = filterSet.level
    95    }
    96    if (filterSet.source != FilterSource.all) {
    97      tags.source = filterSet.source
    98    }
    99    if (filterSet.term.state !== TermState.Empty) {
   100      const termType = isRegexp(filterSet.term.input) ? "regexp" : "text"
   101      tags.term = termType
   102    }
   103    return tags
   104  }