OER-WEB-TEAM / design-system--drupal-theme

1 stars 0 forks source link

Design System Stats - Create a way for components to self report usage statistics #40

Closed AlexVanK closed 3 months ago

AlexVanK commented 5 months ago

The idea is to have websites that use the design system to report to it, the usage of the components used within. This can be automatized!

Stay tuned :)

AlexVanK commented 5 months ago

First step is to add a design-system ID to each component... Something like a data attribute to the container element data-ds-id. Separately we need a dictionary where every ID is mapped to a friendly name. The ID works like a point, it's meaningless and will never change, whereas the friendly name can. E.g: dict = { "2G03CK" : "Card" }

Other attributes could be needed to provide meta information. This could be useful for statistic purpose.

emsaiz commented 5 months ago

Love this idea! I feel like this is the main ID that might help us figure out how often a component is/isn't used right? That's the only big success metric I can think of atm.

I did come across a design system that used metrics to determine usage (& it looks like they linked their github): https://segment.com/blog/driving-adoption-of-a-design-system/#how-it-works

I have NO IDEA if this is applicable, it just seemed kinda interesting at a glance and I thought I'd send it your way.


These were some other (non-ID) success metrics that might be important. Let me know if you have disagree or have other metrics in mind! I can keep a list somewhere for the future.

AlexVanK commented 4 months ago

proposed data structure. This will allow filtering by category, and usage source. Total count is calculated at each fetch, based on the number of page URLS.


[
    {
        "id": "wfHJxBKb",
        "component_name": "accordion",
        "component_categoy": "component",
        "usage_source": [
            {
                "id": "grants.nih.gov",
                "pages": [
                    "grants.nih.gov/page1",
                    "grants.nih.gov/page2"
                ]
            },
            {
                "id": "sharing.nih.gov",
                "pages": [
                    "sharing.nih.gov/page1",
                    "sharing.nih.gov/page2",
                    "sharing.nih.gov/page3"
                ]
            }
        ]
    },
    {
        "id": "DiYpvKCx",
        "component_name": "paginator",
        "component_categoy": "drupal_component",
        "usage_source": [
            {
                "id": "grants.nih.gov",
                "pages": [
                    "grants.nih.gov/page1",
                    "grants.nih.gov/page2"
                ]
            },
            {
                "id": "sharing.nih.gov",
                "pages": [
                    "sharing.nih.gov/page1",
                    "sharing.nih.gov/page2",
                    "sharing.nih.gov/page3"
                ]
            }
        ]
    }
]
AlexVanK commented 4 months ago

On another thought, data needs to be serialized into a list of object that have no relationship information. Also, list needs to be flat: repetitions are allowed (E.g.: 2 alerts on the same page).

This structure will allow several benefits:

Re-proposed structure:


[
    {
        "id": "wfHJxBKb",
        "component_name": "accordion",
        "component_categoy": "component",
        "usage_source_domain": "grants.nih.gov",
        "usage_source_url": "grants.nih.gov/node/123",
        "detected_on": "",
        "removed_on": ""
    },
    {
        "id": "wfHJxBKb",
        "component_name": "paginator",
        "component_categoy": "drupal_component",
        "usage_source_domain": "sharing.nih.gov",
        "usage_source_url": "grants.nih.gov/node/456",
        "detected_on": "",
        "removed_on": ""
    }
]
AlexVanK commented 4 months ago

In this third revision of the data structure focuses on minimizing the HTML footprint. Other than the component DesignSystem (DS) ID, no other information needs to be stored on the HTML element. Instead the information can be mapped to a dictionary. This bring two important benefits:

Here are the two emerging objects:

Information sent along with the component stats

[
    {
        "_id": "wfHJxBKb",
        "usage_source_hostname": "grants.nih.gov",
        "usage_source_pathname": "grants.nih.gov/node/123",
        "date_detected": "",
        "date_removed": ""
    },
    {
        "_id": "wfHJxBKb",
        "usage_source_hostname": "sharing.nih.gov",
        "usage_source_pathname": "grants.nih.gov/node/456",
        "date_detected": "",
        "date_removed": ""
    }
]

Information to be stored in component dictionary (can be updated manually when updating the DS

[
    {
        "id": "i2jqw7hh",
        "short_name": "Accordion",
        "long_name": "",
        "category": "components"
    },
    {
        "id": "j2tmke3n",
        "short_name": "Alert",
        "long_name": "",
        "category": "components"
    },
]
AlexVanK commented 4 months ago

Some components wont be tracked as there's no need for doing so

@emsaiz, suggestions on how to handle the following?

Some other components need to be tracked, but only counted once. Those are the components that are loaded in the header or footer of the website thus they are displayed on every page. Multi-count is not relevant for them, or maybe we shouldn't track them at all?

Perhaps a logical compromise is not to track anything that comes packaged with the theme, because it means it's already there, and won't contribute to usage statistics.

The nature of the design-system is prescriptive, that is, it educates the users on how to use the technology. But it doesn't not enforce any practice. For the components above, if one deviates from the suggested procedures, we will encounter unexpected behavior and un-informative statistics. Perhaps we should force those components only to be used in a certain way? One perfect example is the USWDS banner HAS-TO stay on the top, and that comes hardcoded with the theme. But the banner should ALSO be placed only at the top of the page, yet it cannot come hardcoded with the theme because its content may vary.

To make things more complicated, components like the modal exhibit a hybrid behavior depending on how they are implemented on the website. For example a website administrator could decide to use a modal site-wide (for example the Qualtrics survey) Should we track it then? But we won't be able to anticipate that, and the modal is mapped to one ID only, we cannot differentiate depending on the intended use...

AlexVanK commented 4 months ago

After a lot of thinking, all the above has been dropped in favor of CSV data file.

The system works as follows:

  1. Each component has a component ID needed for tracking, expressed through the attribute data-ds-id. This value is a complete random combination of 8 lowercase + digit characters. image
  2. Granularity of the component ID reaches component variations. But does not extend further: the system won't track "spin-offs" created by a web-dev.
  3. A data dictionary maps component IDs to some of its attributes. This file is located under \__extra\stats_reporter\dict.php. image
  4. A BATCH file (.bat) will be run through a cron/schedule task at the end of every month to collect the usage statics of each component on a given website.
  5. The batch file will run PHP script that parses the content of a list of pages and REGEX search for every instance of a component ID.
  6. The list of pages will be retrieved from a JSON sitemap, provided as a REST resource by the target website itself. E.g.: https://styleguide.od.nih.gov/sitemap.json

Steps to expose a sitemap (by a website on which we want to track components usage)

  1. Install core module RESTful Web Services
  2. Install contributed module REST UI (not really needed as REST resources can be configured through .yml, but it facilitates dev a lot, and benefits other devs)
  3. Open REST UI config page : /admin/config/services/rest and enable CONTENT endpoint with the following params: image
  4. Create a view (page view) that exposes all the nodes and other content types. Find the required configuration in the file below. view-sitemaps-config.txt Import this through the Drupal UI /admin/config/development/configuration/single/import (this will take care of creating and configuring the view appropriately)