|
2 | 2 |
|
3 | 3 | Version>=0.10.9
|
4 | 4 |
|
5 |
| -# Background |
| 5 | +# Problem |
6 | 6 |
|
7 |
| -At Arc, we typically talk about newsrooms being organized by website, but many newsrooms have desks within them that are organized around particular markets or subject matter. |
| 7 | +Editors need to be able to author alternate versions of a single story without blocking each other. There is no way to render alternate versions of a single story for specific websites. |
8 | 8 |
|
9 |
| -The hub-and-spoke relationship between a national content desk and multiple local market desks is being enhanced for stories. The hub editor (national content desk) will create a story. A spoke editor (local market desk) will be able to create a variant of the main story that contains unique content which shows on their local websites. |
| 9 | +# Proposal |
10 | 10 |
|
11 |
| -To facilitate this, the hub editor will be able to place a new content item on their story to designate where a spoke editor can add their unique local content. A spoke editor will create unique content that appears in place of the new content items for this local variant of the story. All editors can all work on their version of the story without locking each other. |
| 11 | +This document proposes changes to support conditional content in a story. When a story is request in Content API, the content will render differently depending on editor defined conditions. The the content of the story variations can be edited in parallel by multiple editors without locking each other out. |
| 12 | + |
| 13 | +* A new `variant` object defining conditional content data for a story. |
| 14 | + * [/ans/0.10.9/utils/variant.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/utils/variant.json) |
| 15 | +* A new `content_zone` story element representing a location for `variant` content within a story. |
| 16 | + * [/ans/0.10.9/story_elements/content_zone.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/story_elements/content_zone.json) |
| 17 | +* A new `variations` field on the story object that contains references to the associated `variant` data. |
| 18 | + * [/ans/0.10.9/traits/trait_variations.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/traits/trait_variations.json) |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | +**Limitations** |
| 23 | +* Only websites are supported as a condition. Future conditions would need additional changes to the ANS spec. |
| 24 | +* Revisions of conditional content are not supported. This will likely require future changes to the ANS spec. |
| 25 | + |
| 26 | +# Details |
| 27 | + |
| 28 | +## Modified/Added Schema |
| 29 | + |
| 30 | +* [/ans/0.10.9/content_operation.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/content_operation.json) |
| 31 | +* [/ans/0.10.9/story.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/story.json) |
| 32 | +* [/ans/0.10.9/story_elements/content_zone.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/story_elements/content_zone.json) |
| 33 | +* [/ans/0.10.9/traits/trait_variations.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/traits/trait_variations.json) |
| 34 | +* [/ans/0.10.9/utils/variant.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/utils/variant.json) |
| 35 | + |
| 36 | +## Variant object |
| 37 | + |
| 38 | +[/ans/0.10.9/utils/variant.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/utils/variant.json) |
| 39 | + |
| 40 | +A `variant` defines a condition and content combination associated with a story. The condition of a `variant` is defined by the "websites" field. The content of a `variant` is defined as a story object in the "content" field. A story may have 0 or many `variant`s. |
| 41 | + |
| 42 | +```javascript |
| 43 | +variant = { |
| 44 | + // Condition of the variant is a list of one or more websites |
| 45 | + "websites": [ |
| 46 | + "TheGazette", |
| 47 | + "TheDaily" |
| 48 | + ], |
| 49 | + |
| 50 | + // Content of the variant is an ANS Story object |
| 51 | + "content": { |
| 52 | + "type": "story", |
| 53 | + "version": "0.10.9", |
| 54 | + "content_elements": [ |
| 55 | + { |
| 56 | + "_id": "AAAAAA111111AAAAAA111111", |
| 57 | + "type": "element_group", |
| 58 | + "content_elements": [ |
| 59 | + { |
| 60 | + "content": "Some data for content_zone AAAAAA111111AAAAAA111111", |
| 61 | + "type": "text" |
| 62 | + } |
| 63 | + ] |
| 64 | + } |
| 65 | + ] |
| 66 | + }, |
| 67 | + |
| 68 | + // User fields |
| 69 | + "name": "My Variant 1", |
| 70 | + "published": false, |
| 71 | + |
| 72 | + // Read-only meta-data |
| 73 | + "type": "variant", |
| 74 | + "publish_date": "2022-10-09T07:20:50.00Z", |
| 75 | + "created_date": "2022-10-08T08:18:50.00Z", |
| 76 | + "last_updated_date": "2022-10-09T07:20:50.00Z" |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +## Content Zone story element |
| 81 | + |
| 82 | +[/ans/0.10.9/story_elements/content_zone.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/story_elements/content_zone.json) |
| 83 | + |
| 84 | +To enable editors to place `variant` content into the main story content, we are introducing a new `content_zone` story element. |
| 85 | + |
| 86 | +A `content_zone` can be used as a story content element to define where `variant` content will be added to the story. A `variant` may contain an `element_group` which references a `content_zone` in the main story content. When the main story is requested in Content API, the `content_zone` element of the story will be replaced with the `element_group` content. |
| 87 | + |
| 88 | +Below is an example ANS object of a story with a `content_zone` content element. The `content_zone` references the `element_group` of the `variant` defined in the previous section. |
| 89 | + |
| 90 | +```javascript |
| 91 | + story = { |
| 92 | + "type": "story", |
| 93 | + "version": "0.10.9", |
| 94 | + "canonical_website": "TheGazette", |
| 95 | + "content_elements": [ |
| 96 | + { |
| 97 | + "_id": "AAAAAA111111AAAAAA111111", |
| 98 | + "type": "content_zone", |
| 99 | + "additional_properties": { |
| 100 | + "comments": [ |
| 101 | + "This content_zone may be replaced by an element_group from a variant" |
| 102 | + } |
| 103 | + } |
| 104 | + ] |
| 105 | + } |
| 106 | +``` |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | +## Variations story element |
| 111 | + |
| 112 | +[/ans/0.10.9/traits/trait_variations.json](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/traits/trait_variations.json) |
| 113 | + |
| 114 | +To get the associated `variant`s of a story, we are introducing a new read-only `variations` field on the story object. |
| 115 | + |
| 116 | +The `variations` field contains the relationships between a story and its list of `variant`s. It also contains a list of all `content_zone`s within the story content. This information is added to the story object as a convenience and optimization for ANS consumers using conditional content. It is a read-only field on the story object. Data included in the `variations` field will be ignored for updates to a story object. In order to maintain ANS document size limitations, `variant` data in a story `variations` field does *not* include its "content" field. |
| 117 | + |
| 118 | +```javascript |
| 119 | + revision = { |
| 120 | + "type": "story", |
| 121 | + "version": "0.10.9", |
| 122 | + "canonical_website": "TheGazette", |
| 123 | + "content_elements": [ |
| 124 | + { |
| 125 | + "_id": "AAAAAA111111AAAAAA111111", |
| 126 | + "type": "content_zone" |
| 127 | + } |
| 128 | + ], |
| 129 | + |
| 130 | + // Read only list of references to variants and content_zones |
| 131 | + "variations": { |
| 132 | + "variants": [ |
| 133 | + { |
| 134 | + "_id": "Q523SZMO6NHORGJJJR6USCS2O4", |
| 135 | + "created_date": "2023-01-09T03:50:38.318Z", |
| 136 | + "last_updated_date": "2023-01-09T03:50:38.318Z", |
| 137 | + "name": "test variant", |
| 138 | + "published": false, |
| 139 | + "type": "variant", |
| 140 | + "websites": [ |
| 141 | + "TheGazette" |
| 142 | + ] |
| 143 | + // Note the "content" field is not returned for variants |
| 144 | + } |
| 145 | + ], |
| 146 | + "content_zone_ids": [ |
| 147 | + "AAAAAAAAAAAAAAAAAAAAAAAAAA" |
| 148 | + ] |
| 149 | + } |
| 150 | + } |
| 151 | +``` |
| 152 | + |
| 153 | +# Content Replacement Scheme |
| 154 | + |
| 155 | +In general, the particulars of how variant content replaces content in the |
| 156 | +original story is a matter of the content authoring and rendering tools' |
| 157 | +implementations. |
| 158 | + |
| 159 | +However, the initial planned support within the Arc system is specified below. |
| 160 | +Any custom implementation of Conditional Content should follow the guidelines to |
| 161 | +ensure compatibility. Only the fields delineated below will be initially |
| 162 | +supported. |
12 | 163 |
|
13 | 164 | ## Content Elements
|
14 | 165 |
|
15 |
| -https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/story_elements/content_zone.json |
| 166 | +The [Content Zone story element](#content-zone-story-element) section above |
| 167 | +outlines the `content_zone` element, which can be placed within the |
| 168 | +`content_elements` array of the original story. These elements must have |
| 169 | +their `_id` field filled with a value. This value must be unique within the |
| 170 | +context of this story's `content_elements`. |
| 171 | + |
| 172 | +The [variant data](#variant-object)'s `content` field holds a minimal story |
| 173 | +with its `content_elements` populated only with the replacement content. For |
| 174 | +each `content_zone` in the original story, the variant `content_elements` |
| 175 | +may optionally contain an element with its `_id` filled with the same value |
| 176 | +from a corresponding `content_zone` element. Though the replacement element |
| 177 | +may technically be any schema-compliant element, the `element_group` is the |
| 178 | +expected element type in the initial implementation. |
| 179 | + |
| 180 | +If a `content_zone` does not have a corresponding value in the variant |
| 181 | +content, it will be removed in the final rendering of the original story. The |
| 182 | +order of the `content_zone`'s `_id` values will match the ordering in the |
| 183 | +variant's replacement data. |
| 184 | + |
| 185 | +## Featured Media |
| 186 | + |
| 187 | +The original story's `promo_items.basic` field can be replaced by simply |
| 188 | +populating the variant's `content.promo_items.basic` field with an image |
| 189 | +[reference](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/utils/reference.json). |
| 190 | +The `basic` field is the only one within the `promo_items` object that is |
| 191 | +currently supported for replacement. |
| 192 | + |
| 193 | +## Tags |
| 194 | + |
| 195 | +The `taxonomy.tags` field in the original story is not replaced by the |
| 196 | +variant's values, but instead supplemented. These auxiliary tags will be |
| 197 | +populated in the variant's `content.taxonomy.tags` field. |
| 198 | + |
| 199 | +While there will be an effort to eliminate duplicate tags between the original |
| 200 | +story and the variant content in the rendering tier, it is not likely to be |
| 201 | +perfect. This is due to the |
| 202 | +[tag schema](https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/utils/tag.json) |
| 203 | +itself. The `_id` field would be the ideal basis to determine uniqueness, but |
| 204 | +the only `text` field is required. Ultimately, the authoring system is the |
| 205 | +best sentinel of uniqueness. |
| 206 | + |
| 207 | +The additional tags will render after the original story's tags. |
| 208 | + |
| 209 | +# Concerns |
| 210 | + |
| 211 | +## What considerations have been made for backwards and forwards compatibility. |
| 212 | + |
| 213 | +All changes are additive to ANS. Previous versions of all ANS objects will be compatible with these changes. |
| 214 | + |
| 215 | +For future compatibility, variations may define fields for new conditions beyond websites. We expect revisions for Variants in the future. |
| 216 | + |
| 217 | +## Why make the variations field read-only? |
| 218 | + |
| 219 | +To help improve collaborative editing, `variant`s are designed for editing independent of the main story. However, to support ANS consumers it helps to include variant data on the story object. To maintain collaborative editing while also supporting publishing API consumers, the `variations` field was designed as read-only. Variants will have an update API endpoint separate from the story object. |
| 220 | + |
| 221 | +## Why not maintain story variant data in the story? |
| 222 | + |
| 223 | +As noted, tightly coupling the story and variant content makes collaborative editing more complicated for users. The intent of this feature is to be used in parallel by multiple editors. There are also concerns about ANS document size limits if all content from all `variant`s are included in the story object. |
| 224 | + |
| 225 | +## What are limits of new features? |
| 226 | + |
| 227 | +A story may have up to 30 `variant`s and up to 10 `content_zones`. |
| 228 | + |
| 229 | +# Alternatives considered |
16 | 230 |
|
17 |
| -A new ANS content element will be defined to represent a `content zone` in the `content_elements` array of a Story document. It can be added to a hub story’s content_elements. It cannot be added to the content of a variant. This element will be replaced with content from a variant when applicable. |
| 231 | +## "Smart Clone" story variations instead of "content_zones" |
18 | 232 |
|
19 |
| -## Story Variants |
| 233 | +In this solution, a story would be "cloned" but maintain "smart" references back to the content of the original story. Changes between the two stories would be synchronized. This was ultimately ruled out because of increased complexity and not as strong of a product fit for ARC. |
20 | 234 |
|
21 |
| -https://github.com/washingtonpost/ans-schema/blob/master/src/main/resources/schema/ans/0.10.9/utils/variant.json |
| 235 | +# Implementation |
22 | 236 |
|
23 |
| -A `variant` is a new ANS element which represents conditional content for a Story document. A variant relates to a single story. Multiple variants may related to the same story. Each variant contains a list of websites (the condition). If the Story is requested from a website set on a variant, then the data defined on the variant will be used in place of the main story data. |
| 237 | +Publishing Platform team will implement authoring support in Draft API and rendering support in Content API for this feature. |
0 commit comments