Directory Management| Hitchhikers Platform

The Directory Manager (DM) helps you create a directory website by generating and grouping Knowledge Graph entities into a tree of parent-child relationships. Conceptually, the Knowledge Graph for a U.S.-based location directory could look something like this:

dm-conceptual-diagram.png

Once you have a directory tree set up in your Knowledge Graph, it’s really easy to develop a Pages site!

light bulb
Tip
If you want to get started building a directory site, check out this module.


Directory Manager Terminology

Before we dive in, here is a list of common Directory Manager terms used throughout the documentation:

Term Definition
Directory A website for which pages are organized in a hierarchical structure.
Example: locations.tacobell.com
Directory Tree A tree of entities in the Knowledge Graph, from which a directory website is built from.
Directory Manager (DM) The application responsible for creating and maintaining a directory tree in the Knowledge Graph.
Directory Entities The set of entities programmatically created by the DM.
Example: for a location directory, directory entities would be the cities, states/regions, countries, and the root entity.
Base Entities The set of entities from which the directory entities are derived. You can think of this set as the “base” for your directory; the DM does not create these entities, it uses them in order to create entities. These are also known as “leaf” entities.
Example: for a location directory, the base entities are the locations. The directory entities are generated based on address information from the base entities.
Root The single entity that sits at the top of your tree. All other entities in your directory are related this entity, hence it is known as the “root”.
Directory Saved Filter A saved filter generated by the DM to represent the set of entities generated for a particular level of a directory. Each saved filter only includes entities that have Directory Children. There is always one saved filter per level of a directory tree.
Example: given a directory with cities, states, and a root, the DM will create three saved filters.
Directory Parents For a given node, parents refers to the full set of entity ancestry above it in the directory tree.
Example: given a directory with cities, states, countries, and a root, the parents for a New York (city) entity would be New York (state), United States, and root.
Directory Children For a given entity, children refers to the set of entities related one-level below it in the directory tree.
Example: given a location directory, the children for New York (state) would be New York (city) and Brooklyn.
Directory Children Count For a given entity, this count refers to the total number of base entities related to it in a directory tree.
Example: assume there are five locations based in Manhattan and five based in Brooklyn. The children count would be 10 entities for New York (state): five entities for Manhattan and five entities for Brooklyn.


Directory Manager Schema

The Directory Manager is powered by a JSON configuration file. Here is the full list of available properties that can be configured in your file:

Property Type Details Validation
$id string Configuration identifier. Unique within account. Required
name string Display name for the Directory Manager. Required
baseEntities object The set of base entities from which the directory will be derived. Required
baseEntities.savedFilterIds array Array of saved filter IDs that comprise your base entities. One of
baseEntities.EntityTypes array Array of entity type IDs that comprise your base entities. One of
localization object Configures the language profiles that are in scope for your directory. If not provided, defaults to the primary language profile for each base entity. Optional
localization.locales array Array of locale code strings (e.g. “en”, “es”, “fr”) Required (if localization is present)
root object Used to configure the “root” entity for your directory tree. When included, all entities in your tree are related to this entity. Optional
root.entityType string The ID of the entity type used for the root entity. This Must already exist. Required (if root is present)
root.slug string Configures the slug value for the entity. Optional
root.entityTemplateId string Specifies an entity template ID to apply to this entity upon creation. Optional
root.localeOverrides object Configures field overrides to be used when creating alternate language profiles. Optional
root.localeOverrides.[localeCode] object Object that specifies the localeCode to configure overrides for. Any localeCode specified here must be listed in localization.locales, or else the overrides will be ignored.
root.localeOverrides.[localeCode].slug string Configures the slug value for the root entity.
root.localeOverrides.[localeCode].entityTemplateId string Specifies an entity template ID to apply to this entity language profile upon creation.
levels array An array of objects. Each object represents a level in the directory. The last element in the array configures the level that points to the base entities. Required. Min 1, Max 3.
levels.entityType string The ID of the entity type used for each level. Must already exist. Required
levels.field string The field ID from the base entity used to generate entities at this level. Required
levels.slug string Configures the slug value for the entity. Optional
levels.entityTemplateId string Specifies an entity template ID to apply to this entity upon creation. Optional
levels.fieldMappings object Allows you to map fields from the base entity to fields on the directory entity. Also supports display name translations for address.region and address.countryCode abbreviations (example: NY → New York, US → United States). Optional
levels.fieldsToCopyFromBase array Array of fields from the base entity to copy over to directory entities. Optional
levels.localeOverrides object Configures field overrides to be used when creating alternate language profiles. Optional
levels.localeOverrides.[localeCode] object Object that specifies the localeCode to configure overrides for. Any localeCode specified here must be listed in the localization.locales, or else the overrides will be ignored.
root.localeOverrides.[localeCode].slug string Configures the slug value for the entity on the relevant language profile.
root.localeOverrides.[localeCode].entityTemplateId string Specifies an entity template ID to apply to entities generated at this level on the relevant language profile.
root.localeOverrides.[localeCode].fieldMappings object Defines mappings for fields on a base entity to fields on a directory entity. Supports display name translations for region and country abbreviations.


Updating a Directory Manager Configuration

After reading our advanced use cases section, you may have decided you want to add a new feature to your existing directory. Don’t worry, upgrading your DM configuration is easy!

Follow the steps below to upgrade your configuration:

  1. Go to your Yext account, and open up Admin Console.
    • You can find this in the Developer section of your left-nav bar, or by using Quick Find.
  2. On the left-side of your page, open up pages > directory-manager, and click on your desired DM configuration file.
  3. Update your file with the desired configuration updates.
  4. Click the “Apply” button in the top-right corner of your window and follow the prompts to apply the resources.
  5. Open up your terminal and enter the following command:

    yext init
  6. Enter the following command to run your updated DM configuration:

    yext dm run --cacId="[REPLACE_ME]"
  7. Navigate back to your Knowledge Graph. You should see the updated configuration changes reflected in your data!


Directory Manager Execution Process

Once the Directory Manager has been executed, there’s a lot that happens under the hood. Specifically, the Directory Manager:

  1. Adds the following custom fields to the entity types in your Yext account:
    • Directory Parents (dm_directoryParents)
    • Directory Children (dm_directoryChildren)
    • Directory Children Count (dm_directoryChildrenCount)
    • Directory Manager ID (dm_directoryManagerId)
  2. Generates your directory entities.
  3. Creates a saved filter for each level of your directory.

Saved Filters

The Directory Manager creates a saved filter for each level of your tree, which includes all entities that were created at that level. These filters are generated automatically to help you configure Streams for Pages development.

Importantly, part of the criteria for these filters is to only include entities that have directory children.

Field Updates

Critically, the Directory Manager is also responsible for creating directory-specific fields and adding them to your entities. It will also populate the built-in slug field for each level of your tree. These include:

  • Slug (slug)
  • Directory Parents (list of entities related to an entity one-level up the directory tree)
  • Directory Children (list of entities related to an entity one-level down the directory tree)
  • Directory Children count (the count of base entities related to an entity)
  • Directory Manager ID (the DM resource ID associated with the creation of an entity)


Ongoing Directory Maintenance

The Directory Manager’s work isn’t finished after initialization. The DM will remain active in your account and actively listen for ongoing CRUD operations involving the set of base entities.

Entity Creation

For example, imagine your business has expanded to a new location - Chicago, Illinois - so you add a new location entity to your graph. You don’t need to re-run the Directory Manager in order to update your directory; the new entities are generated automatically!

In the example below:

  • The user adds location 5 - based in Chicago, IL, a city and state that aren’t in the directory yet.
  • As such, the DM creates all of the following:
    • Chicago city entity
    • Illinois state entity
    • Relationships pointing to and from them
  • The directory children count for the root entity changes from four to five. It is set to one for both the Illinois state entity and the Chicago city entity.

directory-before-after-new-location.png

Entity Updates

The same is true for updates to existing entities as well.

In the example below:

  • The user moves location 2 from New York, NY to Brooklyn, NY.
  • As such, the DM creates a new Brooklyn city entity and relates it to the NY state entity.
  • The DM changes the related city entity for location 2 from New York (city) to Brooklyn.
  • The directory children count is still two for NY state is still two, changes from two to one for New York (city), and it is set to one for Brooklyn.

dm-ongoing-update.png

Entity Deletions

The same is true for entity deletions. For example, if you were to delete a location from your directory, the DM will ensure any relevant directory entities are no longer related to it. Observe the example below:

In the example below:

  • The user deletes location 1 in Brooklyn, NY.
  • After deletion, the Brooklyn city entity no longer has any related children entities.
  • Because Brooklyn has no children, the DM removes it as a child of NY state.
  • The directory children count changes for NY state from three to two and changes for the root entity from four to three.

directory-before-after-deletion.png


Advanced Configuration Use Cases

Entity Templates

An entity template is a Knowledge Graph tool that allows you to define a “template” of field values and apply it to a set of entities. Templates are extremely useful for applying standardized content at scale, and can save you a ton of time (refer to our module to learn more).

The Directory Manager extends this functionality by allowing you to apply specific templates any time a directory entity is generated! To accomplish this, use the entityTemplateId property.

Let’s look at a concrete use case to see why this is useful:

Example DM Configuration

Per the configuration below, there are two entity templates in use by the DM:

  1. stateTemplate (applied to each state entity)
  2. cityTemplate (applied to each city entity)

    {
      "$id": "us-directory",
      "$schema": "https://schema.yext.com/config/pages/directory-manager/v1",
      "name": "US Directory",
      "scope": {
        "savedFilterIds": ["685381454"]
      },
      "root": {
        "entityType": "ce_root",
        "slug": "index.html"
      },
      "levels": [
        {
          "entityType": "ce_state",
          "field": "address.region",
          "slug": "{{address.region}}",
          "entityTemplateId": "stateTemplate",
          "fieldMappings": {
            "c_addressRegionDisplayName": "{{#regionDisplayName}}",
            "c_addressCountryDisplayName": "{{#countryDisplayName}}"
          }
        },
        {
          "entityType": "ce_city",
          "field": "address.city",
          "slug": "{{address.region}}/{{address.city}}",
          "entityTemplateId": "cityTemplate",
          "fieldMappings": {
            "c_addressRegionDisplayName": "{{#regionDisplayName}}"
          }
        }
      ]
    }

Templates

Now, let’s look at what each entity template does:

  1. stateTemplate - Sets the description field to “Welcome to [[name]], located in the great nation of [[c_addressCountryDisplayName]]!”

    state-template.png

  2. cityTemplate - Sets the description field is set to “Welcome to [[name]], located in the great state of [[c_addressRegionDisplayName]]!”

    city-template.png

light bulb
Tip
These examples leverage embedded fields to make the descriptions dynamic per entity. Learn more about how embedded fields work in this module.

Tying it All Together

Once the Directory Manager runs, it will apply the relevant template to each entity that it generates. As a result, you can observe how the description field is automatically populated for both the New York (state) and New York (city) entities below:

state-city-entities.png

Putting this all together, these dynamic description fields can then easily power your Pages frontend!

dm-description-fields.png


Multi-Language Directories

For each base entity, the DM will generate equivalent language profiles for each entity in its parent ancestry. Refer to the screenshot below:

multi-language-dm.png

Location 1, based in New York, NY, has language profiles defined for [“en”, “es”]. This language profile cardinality is respected across its parent ancestry - meaning the DM creates an “en” and “es” profile for the New York city, New York state, and root entities.

By contrast, Location 3 does not have an “es” profile, meaning its ancestry only has “en” profiles generated for it. Furthermore, when it comes to entity relationships, Streams respects language profile cardinality - meaning that the “es” language profile for the root entity will not have “California” as a child entity (because it does not exist).

Advanced Configuration Example

Tying all the above use cases together, here is an example configuration file that uses all possible features:

{
  "$id": "us-directory",
  "$schema": "https://schema.yext.com/config/pages/directory-manager/v1",
  "name": "US Diretory",
  "scope": {
    "entityTypes": [
      "location"
    ]
  },
  "localization": {
    "locales": ["en", "es", "fr"]
  },
  "root": {
    "entityType": "ce_root",
    "slug": "index.html",
    "entityTemplateId": "rootTemplate",
    "localeOverrides": {
      "es": {
        "entityTemplateId": "rootTemplate-spanish",
        "slug": "index/{{localeCode}}"
      },
      "fr": {
        "entityTemplateId": "rootTemplate-french",
        "slug": "index/{{localeCode}}"
      }
    }
  },
  "levels": [
    {
      "entityType": "ce_state",
      "field": "address.region",
      "slug": "{{address.region}}",
      "entityTemplateId": "stateTemplate",
      "fieldMappings": {
        "c_addressRegionName": "{{#regionDisplayName}}",
        "c_addressCountryDisplayName": "{{#countryDisplayName}}"
      },
      "fieldsToCopyFromBase": [
        "email",
        "instagram",
        "labels",
      ],
      "localeOverrides": {
        "es": {
          "entityTemplateId": "stateTemplate-spanish",
          "slug": "{{localeCode}}/{{address.region}}",
          "c_addressRegionName": "{{#regionDisplayName}}",
          "c_addressCountryDisplayName": "{{#countryDisplayName}}"
        },
        "fr": {
          "entityTemplateId": "stateTemplate-french",
          "slug": "{{localeCode}}/{{address.region}}",
          "c_addressRegionName": "{{#regionDisplayName}}",
          "c_addressCountryDisplayName": "{{#countryDisplayName}}"
        }
      }
    },
    {
      "entityType": "ce_city",
      "field": "address.city",
      "slug": "{{address.region}}/{{address.city}}",
      "entityTemplateId": "cityTemplate",
      "fieldMappings": {
        "c_addressRegionName": "{{#regionDisplayName}}"
      },
      "fieldsToCopyFromBase": [
        "email",
        "instagram",
        "labels",
      ],
      "localeOverrides": {
        "es": {
          "entityTemplateId": "cityTemplate-spanish",
          "slug": "{{localeCode}}/{{address.region}}/{{address.city}}",
          "fieldMappings": {
            "c_addressRegionName": "{{#regionDisplayName}}"
          }
        },
        "fr": {
          "entityTemplateId": "cityTemplate-french",
          "slug": "{{localeCode}}/{{address.region}}/{{address.city}}",
          "fieldMappings": {
            "c_addressRegionName": "{{#regionDisplayName}}"
          }
        }
      }
    }
  ]
}
Feedback