Directory Management | Yext Hitchhikers Platform
The Directory Manager (DM) helps you create a directory website by generating and grouping Content entities into a tree of parent-child relationships. Conceptually, the Content for a U.S.-based location directory could look something like this:
Once you have a directory tree set up in your Content, it’s really easy to develop a Pages site!
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 Content, from which a directory website is built from. |
Directory Manager (DM) | The application responsible for creating and maintaining a directory tree in the Content. |
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 Entity Types | The set of entity types that comprise your base entities. This controls what types of entities are allowed to be processed by the Directory Manager. |
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. You must provide a value for entityTypes and can use one or more savedFilterIds in conjunction. |
Required |
baseEntities.EntityTypes |
array | Array of entity type IDs that comprise your base entities. | Required |
baseEntities.savedFilterIds |
array | Array of saved filter IDs that comprise your base entities. | Optional |
localization |
object | Configures the language profiles that are in scope for your directory. | Required |
localization.locales |
array | Array of locale codes (e.g. “en”, “es”, “fr”). For each locale specified, the Directory Manager will create a language profile of that locale for relevant directory entities. Refer to the “Multi-Language Directories” section below for more information. | Required |
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.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:
- 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.
- On the left-side of your page, open up
pages
>directory-manager
, and click on your desired DM configuration file. - Update your file with the desired configuration updates.
- Click the “Apply” button in the top-right corner of your window and follow the prompts to apply the resources.
Open up your terminal and enter the following command:
yext init
Enter the following command to run your updated DM configuration:
yext dm run --cacId="[REPLACE_ME]"
Navigate back to your Content. 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:
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
) - Child Entity IDs (
dm_childEntityIds
)
- Directory Parents (
Generates your directory entities.
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)
- Child Entity IDs (a list used by the Directory Manager to help power the Directory Children Count)
- 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.
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.
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.
Advanced Configuration Use Cases
Entity Templates
An entity template is a Content 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:
stateTemplate
(applied to each state entity)cityTemplate
(applied to each city entity){ "$id": "us-directory", "$schema": "https://schema.yext.com/config/pages/directory-manager/v1", "name": "US Directory", "baseEntities": { "entityTypes": ["location"], "savedFilterIds": ["685381454"] }, "root": { "entityType": "ce_root", "slug": "index.html" }, "localization": { "locales": ["en"] }, "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:
stateTemplate - Sets the
description
field to “Welcome to[[name]]
, located in the great nation of[[c_addressCountryDisplayName]]
!”cityTemplate - Sets the
description
field is set to “Welcome to[[name]]
, located in the great state of[[c_addressRegionDisplayName]]
!”
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:
Putting this all together, these dynamic description fields can then easily power your Pages frontend!
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:
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",
"baseEntities": {
"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}}"
}
}
}
}
]
}