# Feed ## General Concepts ### Client vs. Server A feed response can include a combination of client-driven and server-driven modules. The idea behind providing client-driven modules is to let product/marketing/etc. control things like the ordering of the modules while still letting the client control the content. As such, much (if not all) of the content for the client-driven modules will come from the clients. Server-driven modules will include all the content necessary for the display and any actions that can be taken on the module. Modules will all share a `type` and `data` key at the root level. This is intended to enable expectations for the content of a module based on the type. This lets clients determine whether or not they are capable of parsing/handling a given module. ### Discover Shop The feed service gets lists of shops by hitting the Search Service's `discover/shops` endpoint. As such, the shop model will be the exact same as directly hitting `discover/shops`. Example posted for convenience: ``` { "city": "Little Falls", "cuisines": [ { "name": "brick oven pizza", "seo_representation": "brick-oven-pizza" }, { "name": "grandma pizza", "seo_representation": "grandma-pizza" }, { "name": "healthy pizza", "seo_representation": "healthy-pizza" }, { "name": "veggie pizza", "seo_representation": "veggie-pizza" } ], "delivery_info": { "fee_range": { "max": 0.0, "min": 0.0, "type": "flat" }, "minimum_order_range": { "max": 0.0, "min": 0.0 } }, "distance_to_user": 3.431427278485589, "id": "7c3b92a8-356c-4f6c-9f16-afd0ab711518", "is_acquired": false, "location": { "latitude": 40.8855087, "longitude": -74.2401942 }, "name": "381 Main Bar & Grill", "ovr": 0.0, "rating_info": { "count": null, "display": null, "should_display": null, "value": null }, "shop_id": 20561, "state": "NJ", "zip_code": "07424" } ``` The above example is the `DiscoverShop` currently returned by Search Service if the user provides the `user_context`. There is in progress work to update the `delivery_info` object to return different info based on whether or not a shop delivers at all / to a user specifically. That work can be tracked [here](https://app.clubhouse.io/slicelife/story/59793/search-service-return-user-specific-delivery-info), but should be expected to be completed before anyone needs to integrate with the feed service. Given the large size of a `DiscoverShop` object, we will use `((DiscoverShop))` as a shorthand for referring to this type of object. ## Feed Structure ### Feed Response Client and server driven modules are returned as part of a feed: ``` { "key": "my-slice-delivery-default", "content": [ { "type": // String identifying type of module (e.g: horizontala shop collection) "key": // String identifying the instance of a type of module (e.g.: recommended delivery nearby) "data": { // Data specific to this type of module } }, { "type": // String identifying type of module (e.g: horizontala shop collection) "key": // String identifying the instance of a type of module (e.g.: recommended delivery nearby) "data": { // Data specific to this type of module } } ] } ``` The `key` will be a unique value on Contentful that can be used to track what kind of feed we to shown to the user. As will be discussed in the following sections, the number of modules returned in the `content` key of a feed may differ from the number of modules defined on the feed in contentful. ### Client-driven #### Reorder This indicates a reorder capability simliar to the current reorder in the apps. Example module: ``` { "type": "recent-reorder", "key": "default-reorder", "data": {} } ``` **Contentful Links:** Content Type: [Client: Reorder](https://app.contentful.com/spaces/rjqzadbl7gw8/content_types/clientReorder/fields) Example: [`default-reorder`](https://app.contentful.com/spaces/rjqzadbl7gw8/entries/3FA2AJy7YeBRcWDIYbnXFY) ### Server-driven #### Horizontal Shop Collection Behavior of this collection will be driven by contentful as well as the response from the server. Strictly speaking, clients do not need to be aware of all the contentful part of the collection, but it's being included for context on why a collection would/would not be included in the response to clients. ##### Contentful The fields in contentful drive the behavior of the module: - `key`: A unique value that identifies the module/collection (e.g.: "delivery-near-user") - `type`: `shop-collection-horizontal` - `title`: Title of the module that cannot be empty - `subtitle`: Subtitle of the module that may be empty - `query`: A template query JSON, that has placeholders for the user's lat/long and after substituting can be exectued against `discover/shops` - `min_shops_for_inclusion`: The minimum number of shops that must come back from the `query` in order for module to be included in an overall feed response - `shops_to_show_in_collection`: How many shops the client should show in the collection, vs. on a separate "View All" screen. The server will reduce this value (before sending to the client) if necessary to ensure it does not exceed the number of shops returned from the `query` to Discover. **Contentful Links:** Content Type: [Server: Horizontal Shop Collection](https://app.contentful.com/spaces/rjqzadbl7gw8/content_types/serverHorizontalShopCollection/fields) Examples: - [`delivery-recommended-near-you`](https://app.contentful.com/spaces/rjqzadbl7gw8/entries/1yw4uU1se2OqPeom14crWN) - [`pickup-near-you`](https://app.contentful.com/spaces/rjqzadbl7gw8/entries/433yhxy8cgxMiPRWiflnkc) ##### Response As mentioned in the `Contentful` section above, a collection may be excluded from a feed response based on definitions in the Contentful model. However, all the horizontal shop collections returned from the feed will look like: ``` { "type": "shop-collection-horizontal", "key": "delivery-near-user", "data": { "title": "Recommended Near You", "subtitle": "", "shops": [ ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)) ], "shops_to_show_in_feed": 5 } } ``` The `subtitle` key will always be included and will be an empty string if undefined/empty on Contentful. The `shops_to_show_in_collection` key represents how many shops the client should show in the collection, vs. on a separate "View All" screen. This integer should always be less than or equal to the total number of shops returned from the `shops` key. #### Vertical Shop Collection Behavior of this collection will be driven by contentful as well as the response from the server. Strictly speaking, clients do not need to be aware of all the contentful part of the collection, but it's being included for context on why a collection would/would not be included in the response to clients. ##### Contentful The fields in contentful drive the behavior of the module: - `key`: A unique value that identifies the module/collection (e.g.: "staff-pics") - `type`: `shop-collection-vertical` - `title`: Title of the module that cannot be empty - `subtitle`: Subtitle of the module that may be empty - `query`: A template query JSON, that has placeholders for the user's lat/long and after substituting can be exectued against `discover/shops` - `min_shops_for_inclusion`: The minimum number of shops that must come back from the `query` in order for module to be included in an overall feed response - `shops_to_show_in_feed`: How many shops the client should show in the collection, vs. on a separate "View All" screen. The server will reduce this value (before sending to the client) if necessary to ensure it does not exceed the number of shops returned from the `query` to Discover. **Contentful Links:** Content Type: [Server: Vertical Shop Collection](https://app.contentful.com/spaces/rjqzadbl7gw8/content_types/serverVerticalShopCollection/fields) Example: [`staff-picks`](https://app.contentful.com/spaces/rjqzadbl7gw8/entries/6g7z9Q2GkORxl6gQPqofPO) ##### Response As mentioned in the `Contentful` section above, a collection may be excluded from a feed response based on definitions in the Contentful model. However, all the vertical shop collections returned from the feed will look like: ``` { "type": "shop-collection-vertical", "key": "staff-picks", "data": { "title": "Staff Picks", "subtitle": "Something Clever", "shops": [ ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)) ], "shops_to_show_in_feed": 2 } } ``` The `subtitle` key will always be included and will be an empty string if undefined/empty on Contentful. The `shops_to_show_in_feed` key represents how many shops the client should show in the collection, vs. on a separate "View All" screen. This integer should always be less than or equal to the total number of shops returned from the `shops` key. ## My Slice Feed ### Contentful Content Type: [Feed: My Slice](https://app.contentful.com/spaces/rjqzadbl7gw8/content_types/mySliceFeed/fields) Examples: - [`my-slice-pickup-default`](https://app.contentful.com/spaces/rjqzadbl7gw8/entries/Fu4OIXdXvoYw9Y6Ec3uSj) - [`my-slice-delivery-default`](https://app.contentful.com/spaces/rjqzadbl7gw8/entries/WuJICrINQqjxBu8Q2A3ys) ### Request Send the `latitude` and `longitude` to the `mySlice` endpoint on the feed service, e.g.: `GET` request to `https://[TBD path]/api/v1/my-slice?latitude=[latitude]&longitude=[longitude] ### Response ``` { "key": "my-slice-default", // Unique identifier on Contentful "content": [ { "type": "recent-reorder", "key": "default-reorder", "data": {} }, { "type": "shop-collection-horizontal", "key": "delivery-near-user", "data": { "title": "Recommended Near You", "subtitle": "", "shops": [ ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)) ], "shops_to_show_in_feed": 5 } }, { "type": "shop-collection-vertical", "key": "staff-picks", "data": { "title": "Staff Picks", "subtitle": "Something Clever", "shops": [ ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)), ((DiscoverShop)) ], "shops_to_show_in_feed": 2 } } ] } ```