[META] Support alternative renderings of prop data added for the 'full' view mode such as for search indexing or newsletters

Created on 18 July 2024, 5 months ago
Updated 12 September 2024, 3 months ago

Overview

Extracting this from #3440578-80: JSON-based data storage proposal for component-based page building because that's a long issue with a lot of different discussions, and it probably needs its own issue.

Both core search module and search_api module rely on view modes so that site builders can decide how content gets rendered into the search index. For core search module it hard codes the 'search' view mode, for search_api, you can configure which view mode to use.

The search view mode almost always wants to have all of the field content that the default view mode does (body field especially), but without elements that would 'pollute' the search results like field labels, related content blocks, CTAs, social widgets etc. so that if I search for "newsletter" or "Facebook" I don't get every article on the site back in the results, but only the ones with content actually mentioning newsletters or Facebook.

This means the search view mode is 99.9% of the time going to want to render both the 'fixed' and 'loose' content that is entered for the default view mode.

There is a very similar problem if you wanted to show for example the 'full' content of the entity in a newsletter subscription via an e-mail view mode - simplenews does this I think. When rendering content for a newsletter, you would probably want to remove a newsletter sign-up element, but probably different things to what you'd remove for search indexing otherwise.

Proposed resolution

I can see how we could do this if all prop content is in entity fields (such as the 'field union JSON' model from #3440578-80: JSON-based data storage proposal for component-based page building ), because we already have a model for configuring how those are displayed in different view modes. Although it would still need some work specific to 'field union JSON' fields because each delta could be a different union, and hence use a different component/formatter - but the data would be equally available regardless of which view mode you're in.

I have no idea how it would work with the current XB data model, because the 'static prop' data is all in a single field value (JSON blob), and that single field value holds content that is specific to a view mode. We would need to provide a way for experience builder to configure rendering that data in a different way - but it's arbitrary what data is in there.

User interface changes

🌱 Plan
Status

Active

Component

Data model

Created by

🇬🇧United Kingdom catch

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @catch
  • 🇬🇧United Kingdom catch
  • 🇬🇧United Kingdom catch
  • Assigned to effulgentsia
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Thank you for opening this hyper-critical issue!

    Since JSON-based data storage proposal for component-based page building Active was proposed by @effulgentsia, I think it'd be helpful to read even just a high-level take on how @effulgentsia imagined this would work 😇🙏

  • 🇬🇧United Kingdom catch
  • 🇬🇧United Kingdom catch

    Replying to @lauriii from 📌 Refactor the XB field type to be multi-valued, to de-jsonify the tree, and to reference the field_union type of the prop values Active .

    I believe there should be an easier way for managing the challenges related to the search indexing.

    Do you have any concrete proposals for this? The use cases have been identified for several months now, and I do not believe any alternative way to do it has been proposed. Neither for Experience Builder itself, nor examples from other content builders - other than ones that have no concept of this whatsoever and require custom templates to be written for each alternative rendering.

    In the meantime, more and more cases continue to be identified, which all currently rely on very similar concepts.

    So far:

    1. Optional fields that later need to be incorporated into other view modes.

    2. Custom teaser text. that doesn't appear in the main content.

    3. Search indexing - both core search module and search_api. Search API has over 120,000 installs.

    4. Newsletters via simplenews - simplenews has over 20,000 modern Drupal installs.

    5. Alex Pott's German content audit module

    In Barcelona I brought up the case of wanting the show the first four (or however many) components of an article in a newsletter with a link to read more. iirc the alternative solution to this was for the site builder to create two content slots, one for content that would appear in the newsletter teaser, one for content that wouldn't. This requires the site builder to know in advance of building their entire site that they will need to do this. It also prevents them from being able to increase or decrease the amount of teaser content later because it would be baked into the content model itself.

  • 🇺🇸United States effulgentsia

    I'd like to understand the email newsletter use case more.

    I brought up the case of wanting the show the first four (or however many) components of an article in a newsletter with a link to read more

    Is this a common thing to do? I agree we should support it if it is, but I was under the (perhaps incorrect) impression that HTML emails generally required very different considerations from web pages, such that people would generally want to create an entirely different node for the newsletter rather than trying to derive it dynamically from the "for the website" article node.

  • 🇬🇧United Kingdom catch

    @effulgentsia I haven't used simplenews for years, but a couple of ways:

    https://www.drupal.org/docs/8/modules/simplenews/how-to-create-a-newslet...

    e.g. a 'newsletter' content type, that in turn references other articles on the site, in this case in 'teaser' mode. So the newsletter content type would contain the email specific content but it would also carry teasers for content on the site.

    There's also the reverse case, where content is primarily created for email, but the website has an archive. This British financial advice site does that https://www.moneysavingexpert.com/tips/

    I don't subscribe to any substacks so don't get emails from them, but I would assume a post like this goes out as an e-mail (and it has the signup widget in the middle of it which presumably doesn't) - and then is also readable on the site like a normal blog post.

    https://substack.com/@mehdirhasan/p-147950395

  • 🇬🇧United Kingdom catch

    At the meeting in Barcelona, @lauriii briefly mentioned 'conditional display' as a possible alternative way to do this, although we didn't get into any real details. I tried to think through what an alternative more XB-centred way to achieve similar things might look like, and possibly have one. Note this is not a proposal, I just think it would be useful (for me, but hopefully for everyone) to have something to compare against for pros and cons, and doing so might bring up other possibilities or rule other ones out.

    For this I am assuming that component availability in XB is configured per-entity-type-and-bundle per discussions in 🌱 [META] Configuration management: define needed config entity types Active even if things aren't exposed in this way by default.

    Also thinking through the use-cases more above, I think they can be boiled down to three types. Each one assumes we are rendering a search index or newsletter or 'long teaser' view mode.

    1. Show everything in XB slots from the full view mode, except component type X

    2. Show the first x deltas of specific component types from the XB slots on the full view mode. x deltas of x components. (testimonial, image gallery)

    3. Show a few deltas of any component type, limited to a certain amount (long teaser).

    The idea of using field union JSON is that on these other view modes because the content exists independently of the full view mode in fields, that we can access and render it separately (either via XB or field formatters).

    The alternative could maybe look something like this;

    For each component that's enabled for a bundle, in the component configuration (or an additional config entity type), have a list of view modes with a boolean show vs. not. To support showing specific deltas, it would also need a delta + offset in there.

    This would mean on a newsletter view mode, you could set only the newsletter sign-up component to not show, but render everything else exactly the same way.

    On the 'course teaser + testimonial' view mode, you could set all components except the testimonial to not render, and only show one delta from the testimonial.

    This wouldn't cover the 'long teaser' use case by itself, there would need to be some kind of XB or display mode-level setting to show 'x items of any type' still. Something like essentially a field formatter setting on each XB slot could accomplish that (I know that's not how it'll work but similar concept).

    If the bundle level is not granular enough, it would be possible to have per-component-instance overrides stored in the XB field data.

  • 🇫🇮Finland lauriii Finland

    The conditional display of components is a capability where we allow the components to react to context. For example, the context could be "search_index = true" or "user_roles = [anonymous]" which could be used to determine whether a component should be displayed or not. This is not tied specifically to display modes, this could be done within a display mode. We could also allow the component author to specify this for the component itself. This way a component author could say that for example the labels within the component should not be displayed if the context is search index.

    Custom teaser text. that doesn't appear in the main content.

    A custom teaser text seems like it would be a field, just like we are using the summary field today. It seems that this is the approach that's used by https://www.moneysavingexpert.com/tips/ for example.

    Search indexing - both core search module and search_api. Search API has over 120,000 installs.

    We are planning to enable conditional display components. We could add "search index" as a condition. We could also add additional tools, to allow specific components, or parts of components to be excluded from the search index so that they wouldn't have to be specified in the context of placing a component, but could be defined by the component author.

    What's worth noting is that customizing the search index too much from the actual full page display isn't necessarily a best practice. The search index starts losing meaning if the content is wildly different from what's actually on the page.

    Newsletters via simplenews - simplenews has over 20,000 modern Drupal installs.

    This is already not working with Layout Builder today pretty much at all because AFAIK you can't even access the Layout Builder overrides in the simplenews view mode. See: 🌱 simplenews render flow from layout builder Active . It seems that this would be solved by allowing rendering the XB slots as a whole in a different display mode. This could be enhanced with the conditional display of components to disallow displaying specific components in a newsletter.

    It seems that what would be best for the https://substack.com/@mehdirhasan/p-147950395 example, is that it would be possible to configure as the subscribe component author that it should not be displayed if the context is a newsletter.

    Alex Pott's German content audit module

    I tried to understand what the module does. It does seem like it's taking the content, and enhancing the content some additional information to be sent to an API. It seems that this also would be solved by allowing rendering the XB slots as a whole in a different display mode, or potentially by simply allowing a conditional display of components for this specific context. I would need more information to describe with confidence how this would work with Experience Builder.

    Optional fields that later need to be incorporated into other view modes.

    This is a nice to have capability, but I don't see why we would design the whole system to accommodate this. I'm also questioning if this is actually really solved by the field union approach. It's definitely closer to solving this, but not to an extent where it seems useful.

    We should keep the search index, teaser, and newsletter use cases in mind as we continue working on Experience Builder. I believe the use cases mentioned here are covered by some combination of data modeling, conditional display of components, and potentially being able to create additional display modes that use slot contents from the full content display mode.

    I can't see how any of these use cases would be better solved by being able to place components in an arbitrary order in a different display mode. Because there would be too much risk that the display isn't what's actually expected, the search index example seems like the only use case where that's even a viable option (given the search index itself is not being accessed humans).

  • 🇬🇧United Kingdom catch

    potentially being able to create additional display modes that use slot contents from the full content display mode.

    For me this has been my central concern, that the full content display mode would be 'locked in' to the full display mode and there would not be any (not horrible) way to access it from other contexts. The exact details of how the other display modes show that content is less important to me as long as it's robust, which is why I think sorting out the use cases is so important here since it gives us something to validate against.

    What you've described with conditional display sounds potentially viable, but brings up additional questions too:

    The conditional display of components is a capability where we allow the components to react to context. For example, the context could be "search_index = true" or "user_roles = [anonymous]" which could be used to determine whether a component should be displayed or not. This is not tied specifically to display modes, this could be done within a display mode.

    How will the list of available contexts be determined, and how will contexts be set when rendering content?

    For example, for component authors to be able to conditionally hide labels (or their entire component) on search indexing, there would need to be one, reliably used, 'search_index = true' context - likely provided by core and used by all search contrib modules.

    Conversely, say I'm a site builder/custom module developer and I want to create a custom context. How would I then set conditional display on a component based on that context - I guess the answer to that might just be 'implement an alter hook' or 'update the configuration for each component to set it'.

    The two examples you gave of search index and roles, to me at least feel like they might be too different for one API.

    e.g.

      public function view(EntityInterface $entity, $view_mode = 'full', $langcode  = NULL) {
    

    There is no API to send different contexts at that level so it could only work for the full view mode at least without some entity API refactoring.

    However:

    "user_roles = [anonymous]" 
    

    This is request level context which we can retrieve when rendering, so unlike view mode doesn't need to be passed in explicitly - in terms of the cache API it would be a cache context whereas view mode would be part of the cache key.

    But determining display by roles feels much closer to the field access API than something for component authors to determine - I could absolutely see a 'component access API' though, that does a similar thing to what field access does now.

  • 🇬🇧United Kingdom catch

    This is already not working with Layout Builder today pretty much at all because AFAIK you can't even access the Layout Builder overrides in the simplenews view mode. See: #3393390: simplenews render flow from layout builder.

    It wouldn't work with layout builder, but it will be possible with paragraphs. Disclaimer that I've never actually used paragraphs.

    The paragraphs field references paragraphs entities. The paragraphs formatter renders the paragraphs entities in a specified view mode.

  • 🇬🇧United Kingdom catch

    Cross-linking Allow content created in Experience Builder to be used in meta tags and schema.org vocabularies Active which is about meta tags / schema.org markup. It's slightly different from the 'access from different view modes' use case but probably anything we do here would help there and vice-versa.

Production build 0.71.5 2024