[MGNLPN-474] Get (stateless) personalized content from the Delivery endpoint Created: 22/Nov/17  Updated: 17/Dec/21  Resolved: 15/Jun/21

Status: Closed
Project: Magnolia Personalization
Component/s: None
Affects Version/s: 1.8
Fix Version/s: 2.1

Type: New Feature Priority: Major
Reporter: Viet Nguyen Assignee: Jaroslav Simak
Resolution: Fixed Votes: 4
Labels: VN-Testing
Remaining Estimate: 0d
Time Spent: 3d 1h 31m
Original Estimate: Not Specified

Attachments: File rest-p13n.json    
Issue Links:
Cloners
is cloned by MGNLPN-542 Get (stateful) personalized content f... Closed
Relates
relates to MGNLREST-229 Jersey REST dispatcher impl only regi... Closed
relates to MGNLPN-66 As an editor I can edit all variants ... Closed
relates to MGNLPN-545 DOC: Cookie trait with multiple values Closed
causality
dependency
depends upon MGNLPN-544 Wrappers are not applied to a variant... Closed
depends upon MGNLREST-308 Expose JcrDeliveryEndpointDefinition ... Closed
is depended upon by PAGES-239 Personalization features in SPA Editor Closed
is depended upon by MGNLFE-95 Update SPA samples to fetch and displ... Closed
relation
is related to PAGES-1153 Component Inheritance with Visual SPA... Closed
Template:
Acceptance criteria:
Empty
Release notes required:
Yes
Documentation update required:
Yes
Date of First Response:
Epic Link: Headless p13n
Sprint: HL & LD 28, HL & LD 29, HL & LD 30, HL & LD 31
Story Points: 8

 Description   

User story:

As a SPA developer, I want to get personalized content from the website workspace statelessly, so I can deliver personalized experiences in my SPA.

Notes:

Personalization is one of the enterprise features that pure headless CMS do not have, now that we know many customers want to use the pages editor and personalization to populate headless frontends we should provide this.

Acceptance criteria:

  • The REST call specifys which traits or segments should be used in the resolution (rather then using the info in the user session) - at least by querystring as well as possibly other approaches.
    • This gives more flexibility. Gives better caching possibilities. 
    • Important for middleware / SSR / SSG
  • By default,  a delivery endpoint delivers the same non-personalized format that it delivers now, including all of the variants. (This can still be useful if a developer wants to implement personalization in the frontend itself.)
  • This is only expected to work on any workspaces that are saved to by a "pages app", but there should be no limitations as other app types may eventually also support variant nodes.


 Comments   
Comment by Viet Nguyen [ 22/Nov/17 ]

Example use case from customer:
We are trying to get personalized content through rest call from website repository.
http://localhost:8080/author/.rest/

{customendpoint}

/v1/

{component/page path}

?previewCountry=br
We want to do this through custom Java REST endpoint. Can you give examples or pointers for Personalization integration with REST by passing traits as query parameter?

Comment by Marcel Koch [ 28/Jan/19 ]

I'm bumping up this ticket.

Was there any further progress regarding that idea? We would like to do the same.
Furthermore, it would be interesting to know how we could access the personalization feature / the variants with the JCR-API in pure Java.

Thanks for any hint.

Comment by Travis Munroe [ 02/Jul/19 ]

I am also looking for examples of how to leverage Magnolia's personalization feature through a REST endpoint.  The documentation says it's possible through a custom Java endpoint (https://documentation.magnolia-cms.com/display/DOCS57/How+to+get+content+as+JSON+-+an+overview#HowtogetcontentasJSON-anoverview-CustomJavaendpoints).  Where can I find documentation and/or examples of how to leverage the personalization feature in a custom Java endpoint?

Comment by Viet Nguyen [ 02/Jul/19 ]

Thanks for responding and interesting in our new feature, please let me inform our development team for product development priority arrangement.

Comment by Christopher Zimmermann [ 07/Oct/19 ]

Workaround from professional services department, not supported:

Here is the source for the delivery endpoint v2 modified to return a personalized response (forked from master on September 19th)(Repository only available to enterprise partners): https://git.magnolia-cms.com/projects/SERVICES/repos/rest/browse

You can see the change to support p13n in this diff: 
https://git.magnolia-cms.com/projects/SERVICES/repos/rest/commits/94e1822cdba709c04ba1d95b18770b1230a56c2d

 

 

Comment by Christopher Zimmermann [ 07/Oct/19 ]

An alternative workaround is to use a standard v2 delivery endpoint to return all the variants and then perform the actual personalization logic in the frontend.

In order to get the "variants" via the rest endpoint from the "website" workspace, you need to configure the appropriate child nodes. 

For example:

# Example delivery endpoint v2 configuration:

class: info.magnolia.rest.delivery.jcr.v2.JcrDeliveryEndpointDefinition
workspace: website
rootPath: /travel
depth: 6
nodeTypes:
- mgnl:page
childNodeTypes:
- mgnl:area
- mgnl:component
- mgnl:variants   #THESE ARE NECESSARY TO GET THE VARIANTS.
- mgnl:page.      #THESE ARE NECESSARY TO GET THE VARIANTS.
limit: 100

# Then get content with something like: https://demopublic.magnolia-cms.com/.rest/delivery/pagesWithComponents/v1/contact
Comment by Mikaël Geljić [ 13/Feb/20 ]

Initial implementation working, with a proper ContainerResponseFilter; two related issues though:

  1. The variant's real path, as well as its mixin type and properties are exposed in the delivery response (see rest-p13n.json). We might have to revert MGNLPN-66's NodeWrapper changes (and introduce a separate-wrapper for editing purposes) cc rkovarik.
  2. Bypassing workspace ACLs in delivery config isn't sufficient to resolve the variant node: ResponseFilter processing happens outside the system-context operation, done by the endpoint impl itself.
Comment by Roman Kovařík [ 14/Feb/20 ]
  1. The variant's real path, as well as its mixin type and properties are exposed in the delivery response (see rest-p13n.json).

All of these should be solvable by extending ComponentPersonalizationNodeWrapper.

We might have to revert MGNLPN-66's NodeWrapper changes (and introduce a separate-wrapper for editing purposes) cc rkovarik.

Since then probably bunch of other things depends on this behaviour (it's the only way to distinguish between original and variant node without unwrapping). A custom wrapper mentioned above for your use case would solve this issue.

Simple traits probably work without any problems. What about e.g. a cookie trait, are page request cookies usually passed/copied to rest requests?

Not sure if I am looking at the up to date code (not sure what's ContainerResponseFilter mentioned above):

// Apply personalization
        if (this.traitCollector != null) {
            node = new PersonalizationNodeWrapper(node, Components.newInstance(PersonalizationContentDecorator.class),
                    Components.getComponent(VariantMapping.class), Components.getComponent(VariantResolver.class),
                    this.traitCollector, Components.getComponent(WebContext.class));
        }

can be written as follows

// Apply personalization
personalizationContentDecorator.wrapNode(node); //this properly returns {{ComponentPersonalizationNodeWrapper}} whereas the code above somehow combines {{ComponentPersonalizationContentDecorator}} and {{PersonalizationNodeWrapper}}

And the last question, do we cache by default / do we want to support it?

Comment by Christopher Zimmermann [ 14/Feb/20 ]

We want to support caching. But im sure there's complexity around not overcaching / stale content. 
In one "mode" the devloper provides the traits/segments as parameters in the rest call - then caching is safe I guess. In another mode we want to serve personalization based on our other info about the user (session linked to a cookie?? Not sure how that works now tbh) - here's where caching would be great - but not sure if that is doable. Could the cache system use this session state info (traits, segments) as part of the cache key?

Comment by Roman Kovařík [ 14/Feb/20 ]

In one "mode" the devloper provides the traits/segments as parameters in the rest call - then caching is safe I guess

Is this already implemented as well (I haven't noticed this in the repo linked above)?

In another mode we want to serve personalization based on our other info about the user (session linked to a cookie?? Not sure how that works now tbh) - here's where caching would be great - but not sure if that is doable. Could the cache system use this session state info (traits, segments) as part of the cache key?

Thinking about it again, it should be pretty quick as here is no rendering involved. Not sure how much would cache help.

Comment by Christopher Zimmermann [ 14/Feb/20 ]

"Not sure how much would cache help."
Ha - good point! I'm not sure.

But with all the integrations going on and external content sources - I see a usecase of Magnolia serving content that is a mix of native and remote content (product information from PIM for example) In that case, seems like caching could be a benefit.

Also - is there maybe some efficiencies around resolving the actual content that should be served based on the traits? I guess not at first since we talking about just serving the variants directlyu - without templates or template models.

Comment by Roman Kovařík [ 14/Feb/20 ]

> Also - is there maybe some efficiencies around resolving the actual content that should be served based on the traits? I guess not at first since we talking about just serving the variants directlyu - without templates or template models

Our caching of pages/components variants needs resolving even if items are already cached but it's pretty fast.

Comment by Christopher Zimmermann [ 14/Feb/20 ]

OK. I guess my main input is simply that it should be performant. If its performant without caching then that's great. 

Comment by Christopher Zimmermann [ 31/Mar/20 ]

Question from a user in the documentation: "Are there any examples of how I could use delivery API to get component level content matching a certain Personalization Trait value? Looking to see if I could query by a trait value and get back a page's content with the matching component variations only and not all of the variations."
https://documentation.magnolia-cms.com/display/DOCS61/Delivery+endpoint+API+v2?focusedCommentId=215328200#comment-215328200

Generated at Mon Feb 12 06:37:59 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.