Add Analytics Nav Item for X

Adds an Analytics nav item below Premium in the X.com sidebar

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Add Analytics Nav Item for X
// @namespace    https://github.com/Johnson1602/tampermonkey-scripts
// @version      0.0.2
// @description  Adds an Analytics nav item below Premium in the X.com sidebar
// @author       Weiyi Xu
// @license      MIT
// @match        https://x.com/*
// @match        https://twitter.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=x.com
// @grant        none
// ==/UserScript==

;(function () {
  'use strict'

  const ANALYTICS_URL = '/i/account_analytics'
  const ANALYTICS_LABEL = 'Analytics'

  // Analytics chart icon SVG path
  const ANALYTICS_ICON_PATH =
    'M8.75 21V3h2v18h-2zM18 21V8.5h2V21h-2zM4 21l.004-10h2L6 21H4zm9.248 0v-7h2v7h-2z'

  let analyticsTextContainer = null

  function createAnalyticsNavItem(referenceItem) {
    const analyticsItem = document.createElement('a')
    analyticsItem.href = ANALYTICS_URL
    analyticsItem.setAttribute('aria-label', ANALYTICS_LABEL)
    analyticsItem.setAttribute('role', 'link')
    analyticsItem.className = referenceItem.className
    analyticsItem.setAttribute('data-testid', 'AppTabBar_Analytics_Link')

    // Clone the inner structure from reference item
    const innerDiv = referenceItem.querySelector('div')
    if (innerDiv) {
      const clonedDiv = innerDiv.cloneNode(true)

      // Update the SVG icon
      const svg = clonedDiv.querySelector('svg')
      if (svg) {
        svg.innerHTML = `<g><path d="${ANALYTICS_ICON_PATH}"></path></g>`
      }

      // Update the text and store reference to text container
      const textSpans = clonedDiv.querySelectorAll('span')
      if (textSpans.length > 0) {
        textSpans[0].textContent = ANALYTICS_LABEL
        // The text container is the parent div of the spans
        analyticsTextContainer = textSpans[0].parentElement
      }

      // Add hover state handlers using inline styles
      analyticsItem.addEventListener('mouseenter', () => {
        const isDarkMode = document.documentElement.dataset.theme === 'dark'
        clonedDiv.style.backgroundColor = isDarkMode
          ? 'rgba(231, 233, 234, 0.1)'
          : 'rgba(15, 20, 25, 0.1)'
      })
      analyticsItem.addEventListener('mouseleave', () => {
        clonedDiv.style.backgroundColor = ''
      })

      analyticsItem.appendChild(clonedDiv)
    }

    return analyticsItem
  }

  function syncTextVisibility(referenceItem) {
    if (!analyticsTextContainer) return

    // Check if the reference item has visible text (has span elements)
    const refTextSpan = referenceItem.querySelector('span')
    const hasText = refTextSpan !== null

    if (hasText) {
      analyticsTextContainer.style.display = ''
    } else {
      analyticsTextContainer.style.display = 'none'
    }
  }

  function addAnalyticsNavItem() {
    // Find the Premium nav item, fallback to Home
    const premiumItem = document.querySelector(
      '[data-testid="premium-hub-tab"]'
    )
    const homeItem = document.querySelector(
      '[data-testid="AppTabBar_Home_Link"]'
    )
    const referenceItem = premiumItem || homeItem

    if (!referenceItem) {
      return
    }

    // Check if already added
    const existingItem = document.querySelector(
      '[data-testid="AppTabBar_Analytics_Link"]'
    )
    if (existingItem) {
      const refHasText = referenceItem.querySelector('span') !== null

      // If reference now has text but we don't have a text container, recreate the item
      if (refHasText && !analyticsTextContainer) {
        existingItem.remove()
        analyticsTextContainer = null
      } else {
        // Sync text visibility with reference item
        syncTextVisibility(referenceItem)
        return
      }
    }

    // Create and insert the Analytics nav item
    const analyticsItem = createAnalyticsNavItem(referenceItem)
    referenceItem.insertAdjacentElement('afterend', analyticsItem)
  }

  // Use MutationObserver to handle SPA navigation and responsive changes
  const observer = new MutationObserver(() => {
    addAnalyticsNavItem()
  })

  // Start observing
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  })

  // Initial attempt
  addAnalyticsNavItem()
})()