Adobe Articles / Blogs / Perficient https://blogs.perficient.com/tag/adobe/ Expert Digital Insights Thu, 19 Sep 2024 15:01:14 +0000 en-US hourly 1 https://blogs.perficient.com/files/favicon-194x194-1-150x150.png Adobe Articles / Blogs / Perficient https://blogs.perficient.com/tag/adobe/ 32 32 30508587 Create Content Fragment Variations in AEM With GenAI https://blogs.perficient.com/2024/09/24/create-content-fragment-variations-in-aem-with-genai/ https://blogs.perficient.com/2024/09/24/create-content-fragment-variations-in-aem-with-genai/#respond Tue, 24 Sep 2024 10:50:17 +0000 https://blogs.perficient.com/?p=369459

Earlier this year, Adobe introduced new generative AI capabilities in Adobe Experience Manager (AEM). As a Platinum partner of Adobe, Perficient has early adopter features provisioned for our environments. One of the more exciting and relevant features is the ability to use GenAI to generate variations within Content Fragments in AEM.

In this blog, we’ll talk about a sample use-case scenario, the steps involved with this new feature, and show how it can empower marketers and content authors who spend a lot of time in AEM and make their lives easier. 

The Scenario

In this sample use case, we have contributors who write content for a site called WKND Adventures. We’d like to create a contributor biography to enable an engaging experience for the end user. A biography will further enhance the user experience and increase the chance of content leading to a conversion, such as booking a vacation.  

How to Quickly Create a Content Fragment Variation 

1. Open a Content Fragment for Editing

After logging into AEM as a Cloud Service authoring environment, head over to a Content Fragment and open it up for editing.

Note: If you don’t see the new editor, try selecting the “Try New Editor” button to bring up the latest interface.

AEM as a Cloud Service Content Fragment Editing

As you can see, we still have the standard editing features such as associating images, making rich text edits, and publishing capabilities.

2. Generate Variations

Select the “Generate Variations” button on the top toolbar, and then a new window opens with the Generative Variations interface as seen in the image below.

AEM as a Cloud Service Generative Variations

What’s important to note here is that we are tied to the authoring environment in this interface. So, any variations that are generated will be brought back into our content fragment interface. Although a new prompt can be generated, we’ll start with the Cards option.

Note: There will be more prompt templates created after the writing of this blog.

3. Prompt Templates

The Cards option is pre-filled with some default helper text to provide guidance on a potential prompt and help fine-tune what’s being generated. Providing relevant and concise explanations to the user interaction will also improve the generated results. The interaction can also be explained. The generations can be further enhanced by providing Adobe Target, or a CSV file to further improve the generations. Providing a tone of voice also further defines the variations.

AEMaaCS Generative Variations Prompts

One of our favorite features is the ability to provide a URL for domain knowledge. In this case, we’re going to select a site from Rick Steves on winter escapes as seen in the image below.

AEMaaCS Generative Variations Prompt Url Domain Knowledge

After selecting the appropriate user interaction, tone, temperature intent, and number of variations, we select the “Generate” button.

4. Choose a Content Fragment Variation

Once the variations are created, we can review the results and then choose one to bring back into our Content Fragment editor.

AEMaaCS Generative Variations Selection

After selecting a variation and giving it a name, we can then export that variation. This will create a new variation of that content fragment in AEM.

AEM as a Cloud Service New Content Fragment

Although this is a simple example, many other prompt templates can be used to generate variations that can be used in AEM. Such as creating FAQs, a headline, hero banners, tiles, and more. Additional technical details can be found on Adobe’s GenAI page.

The Exciting Future of Content Creation

Having a direct integration to generate variations from an authoring environment will certainly speed up content creation and allow authors to create relevant and engaging content with the help of GenAI. We look forward to more features and improvements from Adobe in this exciting space, and helping customers adopt the technologies to effectively and safely create content to build exciting experiences.

]]>
https://blogs.perficient.com/2024/09/24/create-content-fragment-variations-in-aem-with-genai/feed/ 0 369459
A rabbit hole in web development https://blogs.perficient.com/2024/09/11/a-rabbit-hole-in-web-development/ https://blogs.perficient.com/2024/09/11/a-rabbit-hole-in-web-development/#respond Wed, 11 Sep 2024 16:15:35 +0000 https://blogs.perficient.com/?p=369021

A rabbit hole

Recently, I was learning about some new Adobe software, and came across the line of code import Theme from "@swc-react/theme". This quickly dropped me into the web development education rabbit hole…

  • A quick search shows me that "@swc-react/theme" is React Wrappers for Spectrum Web Components.

  • Another search shows that Spectrum Web Components is a particular implementation of Adobe Spectrum that uses Open Web Components‘s project generator.

  • What is Open Web Components? Well, whatever it is, it relies on something called Lit.

  • What is Lit? It’s a JavaScript library that relies on Web Components.

  • At the end of the rabbit hole, we learn that Web Components is a collection of modern HTML and JavaScript features that allow implementation of “components”, which are modular, HTML-parameterizable pieces of a webpage that have their own associated HTML, JavaScript, and CSS. Components are typically implemented by more heavyweight frameworks such as React or Angular.

Of course, few of the clarifying details I’ve added in the above bullet points were clear to me during my initial time in the rabbit hole.

The following is an article that presents the relevant content from the rabbit-hole in a more foundational, “bottom-up” approach.

Web components

Web Components is a suite of different technologies [standard to HTML and JavaScript] allowing you to create reusable custom elements – with their functionality encapsulated away from the rest of your code – and utilize them in your web apps.”

The “suite of different technologies” are the custom elements JavaScript API, the shadow DOM JavaScript API, and the <template> and <slot> HTML elements.

Custom elements (JavaScript API)

The custom elements JavaScript API allows

  • extension of built-in HTML elements, such as <p>, so that an extended HTML element can be used in HTML with code such as <p is="word-counter"> . (The argument to is specifies which extension of <p> is used.) These are called customized built-in elements.

  • creation of new HTML elements that have new tag names such as <custom-element>. These are called autonomous (HTML) elements.

A custom element is implemented as a class which extends either

  • an interface corresponding to an HTML element, in the case of extending an existing HTML element

    or

  • HTMLElement, in the case of creating a new HTML element

The class will need to implement several “lifecycle callback functions”. The class, say Cls, is then passed to window.customElementRegistry.define("my-custom-element", Cls).

Shadow DOM (JavaScript API)

The shadow DOM JavaScript API allows “hidden” DOM trees, called shadow trees, to be attached to elements in the regular DOM tree. Shadow trees are hidden in the sense that they are not selected by tools such as document.querySelectorAll(). They allow for encapsulation because none of the code inside a shadow tree can affect the portion of the overall DOM tree that is its parent.

Shadow trees are effected by using

  • <template shadowrootmode="open"> </template> in HTML

    or

  • const shadow = elem.attatchShadow({mode: "open"}) in JavaScript

<template>

The <template> HTML element is not actually rendered by the browser. Instead, when template is the JavaScript Element representing a <template> HTML element (e.g. const template = document.querySelectorAll("#some-template")), we are expected to manually render* template.content. This manual rendering is done by writing code such as document.body.appendChild(template.content).

But- still- what good is this? At this stage, all we know about <template> is that use of it requires manually rendering HTML. It seems useless!

*template.content is of type DocumentFragment, which is a data structure that represents template.innerHTML. You can read about a situation in which you would want to use DocumentFragment over innerHTML here. It’s not clear to me how using DocumentFragment is vastly superior to innerHTML in this scenario, but there is probably some small performance advantage.

Slotting

<template> does become quite useful when it’s paired with the <slot> element. The <slot> element allows us to define portions of the <template> inner HTML that are variable so that we can later “plug-in” custom HTML into those portions of the <template> inner HTML.

In order achieve this functionality of <slot>, we must actually use <slot> alongside custom element and shadow DOM concepts, as this was how <slot> was designed to be used.

Slotted custom elements

We now describe how <slot> is used with custom elements, the shadow DOM, and templates to implement a “slotted” custom element.

  1. Include code such as

<template id = "some-template">
    ...
    <slot name = "some-slot"> default text </slot>
    ...
</template>

in the HTML.

  1. In the class that defines a custom element, write a constructor that creates a shadow tree by including const shadowRoot = this.attachShadow({mode: "open"}) in the constructor.

  1. In same constructor, right after the creation of the shadow tree, set template.content to be the inner HTML of the shadow tree: shadowRoot.attachChild(template.content.cloneNode(true)).

(To see an example of this, inspect this webpage with your browser’s development tools.)

We see that the three concepts of custom elements, the shadow DOM, and templates are all involved. (1) and (3) are about templates, (2) is about the shadow DOM, and (2) and (3) occur in the custom element’s constructor!

But how does <slot> come into play? Well, suppose that a custom element called “some-element” is configured in the above way. Then then the HTML

<some-element> </some-element>

is interpreted by the browser to be the inner HTML of the template with the inner HTML of the template’s <slot> element replacing the template’s <slot> element. So, the browser will render the HTML

...
default text
...

Alternatively, the HTML

<some-element>
    <div slot = "some-slot"> replacement text </div>
</some-element>

is interpreted by the browser to be the inner HTML of the template with the inner HTML of the newly specified <slot> element replacing the template’s <slot> element. So, the browser will render the HTML

...
replacement text
...

Modern components

The type of custom element above implements the idea of a modern component, which is

  • easily reusable

  • encapsulated (in the sense that one component’s code is separate from other components and does not affect other components state or behavior)

  • allows for parameterization of HTML with <slot>

We’ve seen that writing the above type of custom element requires a lot of boilerplate. We could eliminate the boilerplate by writing a class that implements the modern component functionality. The class’s constructor would take the HTML that is to underlie the modern component as an argument*.

* If <slot> functionality is used, then the HTML that is to underlie the modern component would contain a the same kind of <slot> element that <template> did above.

Lit

Lit is a library that provides a class, LitElement, that implements this notion of modern component. As Lit’s documentation says, the advantage of this approach is that, since modern components rely on standard HTML and JavaScript APIs, they are supported by almost all web browsers (all web browser that support the required HTML and JavaScript APIs, that is), and do not require any frameworks such as Angular or React to run.

Open Web Components

Open Web Components is a website that “gives a set of recommendations and defaults” on how to write modern web components”. The “Getting Started” page recommends that to begin developing a web component, you should make use of their npm package by running npm init @open-wc, which generates an example Lit component.

Spectrum Web Components

Spectrum Web Components is the “frameworkless” or “as close to vanilla JS as possible” implementation of Adobe Spectrum. Spectrum Web Components are Lit components and thus extend LitElement.

React Wrappers for Spectrum Web Components

swc-react is a collection of React wrapper components for the Spectrum Web Components (SWC) library, enabling you to use SWC in your React applications with ease. It relies on the @lit/react package to provide seamless integration between React and the SWC library.”

Why not just use React Spectrum components?

swc-react and React components are two technologies that implement the idea of a component in some way. I would think that if we’re using React, wouldn’t it more natural to just use React components, and not import an extra library that make Lit components useable in React? Well, Adobe documentation says:

We recommend using swc-react over React Spectrum in your add-ons based on React, because it currently offers a more comprehensive set of components which provide built-in benefits as detailed above in the Spectrum Web Components section, and is more actively supported.

So I suppose that answers my question 🙂

]]>
https://blogs.perficient.com/2024/09/11/a-rabbit-hole-in-web-development/feed/ 0 369021
Edge Delivery Services Tips and Tricks for Developers https://blogs.perficient.com/2024/09/03/edge-delivery-services-tips-and-tricks-for-developers/ https://blogs.perficient.com/2024/09/03/edge-delivery-services-tips-and-tricks-for-developers/#respond Tue, 03 Sep 2024 11:27:58 +0000 https://blogs.perficient.com/?p=368351

Edge Delivery Services empowers developers and authors to create lightning-fast, high-performing digital experiences that score a perfect 100% on Google’s Lighthouse metrics. With Edge Delivery, you can choose from two flexible implementation options – document-based authoring and WYSIWYG (What You See Is What You Get) – to streamline your development workflow and accelerate content authoring. 

Edge Delivery Services Setup

This blog will focus on document-based authoring, also known as Project Franklin, Helix, or AEM (Adobe Experience Manager) Live. To unlock the full potential of Edge Delivery Services and get started with local development, please refer to Adobe’s comprehensive guide for setting up Edge Delivery Services locally.

With this foundation, we will discuss the developer’s insights on document-based authoring in the subsequent section. 

Tips and Tricks

Be a Lighthouse Keeper

The overarching goal is to maintain a perfect Lighthouse score throughout the development process. To achieve this, regularly monitor the score at key milestones, such as the completion of each feature or block. Referring to the diagnostics and addressing suggested areas of improvement will help you maximize your score.

For instance, look at the items listed in the image below. By keeping a close eye on Lighthouse performance, you will significantly reduce the number of issues to address, resulting in a much shorter list. Regular monitoring helps identify and resolve problems early on, streamlining your development process.

Adobe Edge Delivery Services Diagnostics

Example of Google’s Lighthouse Diagnostics for a website.

Additionally, by adopting a mobile-first development approach, you can minimize rework and ensure a seamless user experience across all devices. This proactive strategy will eventually save time and effort.

Best Practices for Accurate Lighthouse Score Testing

When testing Lighthouse scores during local development, it’s essential to minimize external factors that can impact your results. Only enable necessary browser extensions, as they can negatively affect your score. If you’re unable to disable extensions, consider using the command line interface instead. To get started, refer to the steps below.

  1. Install Lighthouse: Run the following command to install Lighthouse globally on your machine:
    npm install -g lighthouse
  2. Run Lighthouse: Check your score using the following command:
    lighthouse <url>
  3. Customize breakpoints (optional): To test specific breakpoints, pass options using the following command:
    lighthouse <url> --view --chrome-flags="--window-size=<windowWidth, windowHeight>"

    Replace <url> with the URL you want to test, and <windowWidth> and <windowHeight> with your desired dimensions.

Leveraging the Boilerplate Code for Enhanced Performance

Edge Delivery Services’ boilerplate code offers a range of functions designed to optimize code performance. To explore these functions and gain a deeper understanding of the code, review the scripts in aem.js and script.js. These scripts provide out-of-the-box (OOTB) functions that can significantly enhance your development workflow.

One of the noteworthy functions is the createOptimizedPicture(), which optimizes image delivery. Additionally, the buildAutoBlocks() function is a valuable tool for autoblocking, particularly on blog post pages or when creating common components for pages using the same template. This function can serve as an inspiration for your own custom solutions.

Naming Conventions for Blocks

To ensure seamless rendering, verify that the block name on the document matches the corresponding block folder and file names (CSS/JS) under the /blocks directory. For instance, if the block is named “social-media-links“, the folder structure should mirror this naming convention.

Edge Delivery Naming Conventions For Blocks

Example block folder structure.

On the document, the block can be referenced using the following variations, all of which will render the above-sown block successfully:

  • social media links
  • Social Media Links
  • social-media-links
  • Social-Media-Links
Edge Delivery Block Authored In A Table Example

Example block authored in a table.

Note that while the naming convention is case-insensitive, it is sensitive to camelCase. Therefore, using “socialMediaLinks” will not render the block correctly. Maintaining consistent naming conventions ensures efficient block rendering and avoids potential issues.

Checkout the OOTB Block collection

Before building a new block from scratch, take a moment to explore the out-of-the-box (OOTB) options available with Edge Delivery Services. The Edge Delivery Services offers a comprehensive array of block examples that can serve as a foundation for your project, saving you time and effort. Although the OOTB blocks may seem comparable to core components, they serve a distinct purpose. Unlike core components, the block collection from the boilerplate code cannot be extended, and no updates from Adobe should be expected. Developers are free to utilize or repurpose any block from the collection or those found in the boilerplate code. By leveraging the OOTB collection, you can accelerate your development process and avoid reinventing the wheel.

Overcome New Edge Delivery Services Obstacles

By incorporating these tips and tricks into your Edge Delivery Services-based development routine, you’ll be able to overcome common obstacles faced by a new Edge Delivery developer. Remember, the key to success lies in continuous learning, adaptability, and a willingness to explore new approaches.

Stay curious!

More Edge Delivery Services Content!

New From Adobe: Next-Gen Composability

Adobe Edge Delivery Services POC

]]>
https://blogs.perficient.com/2024/09/03/edge-delivery-services-tips-and-tricks-for-developers/feed/ 0 368351
4 Ways Perficient’s Adobe Practice is Forging the Future So Far in 2024 https://blogs.perficient.com/2024/08/21/4-ways-perficients-adobe-practice-is-forging-the-future-so-far-in-2024/ https://blogs.perficient.com/2024/08/21/4-ways-perficients-adobe-practice-is-forging-the-future-so-far-in-2024/#respond Wed, 21 Aug 2024 14:36:15 +0000 https://blogs.perficient.com/?p=364615

Perficient’s people are the key to our success and make our organization the unique, dynamic, and innovative workplace it is today. This is the first blog in our Business Unit Spotlight series where we will share colleagues’ perspectives on leading digital change, driving real results for our clients, and collaborating with the best and brightest across the globe.

Perficient’s Adobe practice is comprised of more than 700 dedicated Adobe-focused consultants, accompanied by more than 50 skilled Adobe architects. We have a powerhouse of certified talent across Perficient who are shattering boundaries and forging the future. Continue reading as our colleagues share their experience at Perficient and the amazing achievements accomplished so far this year.

1. Perficient is an Award-Winning, Highly Specialized Adobe Partner 

Perficient has been honored with a number of awards for our work on the Adobe platform, including the 2023 Adobe Digital Experience Emerging Partner of the Year, Americas. This year, we earned our seventh Adobe specialization! Our latest specialization in Customer Journey Analytics strengthens our position as a leading Adobe partner and demonstrates our expertise in empowering clients to make informed decisions that drive business growth. Perficient is recognized by Adobe and our clients for our ability to deliver incredible digital experiences.

Santhosh Nair

“We are proud to be recognized time and time again for our distinguished Adobe work,” said Santhosh Nair, senior vice president. “These recognitions are a testament to the deep expertise, growth, and commitment of our entire Adobe practice. We are focused on building and delivering Adobe-centric offerings that connect brands with their customers, and our team takes great pride in the value we provide for our clients.”

From strategy to implementation, Perficient’s team of experts are building exceptional experiences on the Adobe platform that are delighting our clients and their customers.

Grace Siwicki

“I think it’s great that Perficient has received these honors from Adobe as they reflect how well aligned we are with Adobe, ensuring we have the best possible solutions for our clients,” said Grace Siwicki, Adobe platform director. “It’s also indicative of our level of experience and competency within the Adobe ecosystem that enables us to be subject matter experts. I believe that Adobe will continue to be a leader in the industry, which positions Perficient well in our strong partnership and allows us to continue to grow our business and talent.”

2. Showcasing Digital Experience at Adobe Summit 2024 

Perficient had a significant presence at this year’s Adobe Summit conference, including hosting three industry focused events, two client success story presentations, and co-hosting the Women in Digital Breakfast. Our colleagues had the opportunity to connect with clients and other experts in the space to stay on the leading edge of technology. Robert Sumner Photo

“We had a great turnout for the automotive and manufacturing breakfast,” said Robert Sumner, principal. “I had the opportunity to speak alongside Adobe’s head of industry strategy about how to modernize, innovate, and win in an increasingly competitive automotive and mobility market.” 

Watch Now: Robert Sumner Discusses the Impact of GenAI on the Automotive and Manufacturing Industries 

The Women in Digital event at Adobe Summit has become an honored tradition for Perficient as it features a panel of influential women leaders facilitating conversations on professional growth, emerging industry trends, and other key topics. 

Meghan Frederick“The Women in Digital event is an opportunity for female leaders to connect, share advice, and learn from their peers all centered around women empowerment,” said Meghan Frederick, senior marketing manager. “Perficient has partnered with Adobe to host Women in Digital panel discussions since 2017, making it the longest running event at Adobe Summit.”

3. Perficient Included in Forrester’s Adobe Services Landscape, Q1 2024 Report 

Perficient was included in Forrester’s Adobe Services Landscape, Q1 2024 report as a medium-sized consultancy among many notable Adobe service vendors. In the report, Forrester identified top business scenarios that buyers most frequently seek and expect along with extended business scenarios to illustrate vendor differentiation. 

“It is with immense pride and joy that Perficient is included in Forrester’s Adobe Services Landscape report, a significant milestone that we have pursued for years,” said Robert. “This recognition stands as a testament to our dedication and expertise in the field. Personally, this achievement holds significance as it reflects the culmination of my own efforts and contributions to Perficient’s success. It is a moment of celebration not only for the company but also for each individual who has played a role in shaping our Adobe journey towards excellence.” 

Robert Presenting

Robert has been with Perficient for more than 20 years and is regarded as one of the founders of the Adobe practice at Perficient. 

“The practice began as a team of generalized web content management specialists,” said Robert. “Embracing global delivery has allowed us to be more competitive in the marketplace. We became renowned for the quality of work delivered by our onshore and offshore teams.” 

Learn More: Perficient’s Collaborative Culture 

4. Fun and Rewarding Team Building Opportunities 

There is no shortage of fun to be had within the Adobe business unit! From cooking competitions to golf tournaments and ping-pong tournaments, our Adobe team knows how to work hard and play hard. Here is what some of our colleagues had to say:

Raf Winterpacht“In our Adobe BU, we care about each other,” said Raf Winterpacht, director, based in our Chicago office. “We take the time not only to ask how we can support each other, but we actually take on tasks when we see that someone’s workload needs to be balanced. Even though we’re dispersed around the world, we greet each other regularly. That is so important because it provides a sense of human connection.”

Women In Digital Golf Clinic

Women in Digital golf clinic

“Outside of our day-to-day work, we also pride ourselves in participating in knowledge-sharing activities,” said Raf. “We believe in sharing our findings and viewpoints when it comes to new and upcoming technology. This makes for a more harmonious work dynamic amongst our team.”

“Our team of thought leaders contribute to the amazing culture we have here at Perficient,” said Meghan Frederick. “We have a great group of people across the world working together to achieve incredible things. There is much excitement around our Adobe practice at Perficient, and our colleagues are true difference makers.”

Matt Shields“I want to know everyone in this practice and understand what they’re good at, what they like to do, where they want to grow, and what makes them uncomfortable,” said Matt Shields, managing director. “All of this is helpful to know when ensuring that people are well aligned in their role. As a result, we’re helping our clients in the best ways we can.”

Read More: Making a Splash and Growing with Perficient: From Solution Director to Adobe Managing Director

Perficient’s Adobe Practice is #ProudlyPerficient 

Perficient prioritizes a people-centric work culture. Our colleagues work collaboratively to deliver solutions that excite and solve real world problems. We are helping the world’s biggest brands digitally transform while also fostering an inclusive, growth-oriented environment at Perficient that will challenge, champion, and celebrate our colleagues at every turn. 

Click to view slideshow.

 


READY TO GROW YOUR CAREER? 

It’s no secret our success is because of our people. No matter the technology or time zone, our colleagues are committed to delivering innovative, end-to-end digital solutions for the world’s biggest brands, and we bring a collaborative spirit to every interaction. We’re always seeking the best and brightest to work with us. Join our team and experience a culture that challenges, champions, and celebrates our people. 

Visit our Careers page to see career opportunities and more! 

Go inside Life at Perficient and connect with us on LinkedIn, YouTube, Twitter, Facebook, TikTok, and Instagram. 

]]>
https://blogs.perficient.com/2024/08/21/4-ways-perficients-adobe-practice-is-forging-the-future-so-far-in-2024/feed/ 0 364615
Create an RSS Feed using HTL https://blogs.perficient.com/2024/05/03/create-an-rss-feed-using-htl/ https://blogs.perficient.com/2024/05/03/create-an-rss-feed-using-htl/#comments Fri, 03 May 2024 17:15:39 +0000 https://blogs.perficient.com/?p=362326

Did you know you can create an RSS feed in AEM (Adobe Experience Manager) for external applications like Eloqua? While AEM provides out-of-the-box functionality for RSS feeds, customizing them may require additional steps. Below you’ll find several options for creating RSS feeds in AEM along with steps for creating one using HTL.  

3 Options to Create an RSS Feed in AEM  

  1. Override Default JSP Functionality (JSP Approach) 
    • Customize the JSP code to tailor the RSS feed according to your requirements 
    • This approach requires writing backend logic in Java and JSP
  2. Create a Servlet for RSS Feed
    • Implement the logic within the servlet to fetch and format the necessary data into RSS feed XML
    • Configure the servlet to respond to specific requests for the RSS feed endpoint
    • This approach allows more control and flexibility over the RSS feed generation process
  3. Use HTL with Sling Model (HTL Approach)
    • Write HTL templates combined with a Sling Model to generate the RSS feed
    • Leverage Sling Models to retrieve data from AEM and format it within the HTL template
    • This approach utilizes AEM’s modern templating language and component models
    • HTL is preferred for templating tasks due to its simplicity and readability

Expected RSS Feed 

Below is the feed response for an external source to integrate and send emails accordingly. Here the feed results can be filtered by category tag names (category) using query parameters in the feed URL. 

  • https://www.demoproject.com/products/aem.rss 
  • https://www.demoproject.com/products/aem.rss?category=web
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <atom:link rel="self" href="https://www.demoproject.com/products/aem" />
        <link>https://www.demoproject.com/products/aem</link>
        <title>AEM</title>
        <description />
        <pubDate>Fri, 29 Sep 2023 02:08:26 +0000</pubDate>
        <item>
            <guid>https://www.demoproject.com/products/aem/one.rss.xml</guid>
            <atom:link rel="self" href="https://www.demoproject.com/products/aem/sites" />
            <link>https://www.demoproject.com/products/aem/sites</link>
            <title>Aem Sites</title>
            <description><![CDATA[AEM Sites is the content management system within Adobe Experience Manager that gives you one place to create, manage and deliver remarkable digital experiences across websites, mobile sites and on-site screens.]]></description>
            <pubDate>Tue, 31 Oct 2023 02:23:04 +0000</pubDate>
        </item>
        <item>
            <guid>https://www.demoproject.com/products/aem/two.rss.xml</guid>
            <atom:link rel="self" href="https://www.demoproject.com/products/aem/assets" />
            <link>https://www.demoproject.com/products/aem/assets</link>
            <title>Aem Assets</title>
            <description><![CDATA[Adobe Experience Manager (AEM) Assets is a digital asset management system (DAM) that is built into AEM. It stores and delivers a variety of assets (including images, videos, and documents) with their connected metadata in one secure location.]]></description>
            <pubDate>Thu, 26 Oct 2023 02:21:19 +0000</pubDate>
            <category>pdf,doc,image,web</category>
        </item>
    </channel>
</rss>

Steps for Creating RSS Feed Using HTL 

  • Create a HTML file under the page component 
  • Create a PageFeed Sling Model that returns data for the RSS feed 
  • Add a rewrite rule in the dispatcher rewrite rules file 
  • Update the ignoreUrlParams for the required params 

Page Component – RSS html  

Create an HTML file with the name “rss.xml.html” under page component. Both ‘rss.html’ or ‘rss.xml.html’ work fine for this. Here, ‘rss.xml.html’ naming convention indicates that it is generating XML data. PageFeedModel provides the page JSON data for the expected feed.  

  • Category tag is rendered only when page properties are authored with tag values
  • CDATA (character data) is a section of element content to render as only character data instead of markup
<?xml version="1.0" encoding="UTF-8"?>
<sly data-sly-use.model="com.demoproject.aem.core.models.PageFeedModel" />
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <atom:link rel="self" href="${model.link}"/>
        ${model.linkTag @ context='unsafe'}
        <title>${model.title}</title>
        <description>${model.subTitle}</description>
        <pubDate>${model.publishedDate}</pubDate>
        <sly data-sly-list.childPage="${model.entries}">
            <item>
                <guid>${childPage.feedUrl}</guid>
                <atom:link rel="self" href="${childPage.link}"/>
                ${childPage.linkTag @ context='unsafe'}
                <title>${childPage.title}</title>
                <description><![CDATA[${childPage.description}]]></description>
                <pubDate>${childPage.publishedDate}</pubDate>
                <sly data-sly-test="${childPage.tags}">
                    <category>${childPage.tags}</category>
                </sly>
            </item>
        </sly>
    </channel>
</rss>  

Page Feed Model

This is a component model that takes the currentPage as the root and retrieves a list of its child pages. Subsequently, it dynamically constructs properties such as publish date and categories based on the page’s tag field. These properties enable filtering of results based on query parameters. Once implemented, you can seamlessly integrate this model into your component to render the RSS feed.

  • Using currentPage get the current page properties as a value map 
  • Retrieve title, description, pubDate, link for current page 
  • Retrieve title, description, pubDate, link, tags (categories) for child pages 
  • Filter the child pages list based on the query param value (category)
//PageFeedModel sample code 
package com.demoproject.aem.core.models;

import com.adobe.cq.export.json.ExporterConstants;
import com.day.cq.commons.Externalizer;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageFilter;
import com.demoproject.aem.core.utility.RssFeedUtils;
import lombok.Getter;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

@Model(adaptables = {
    Resource.class,
    SlingHttpServletRequest.class
}, resourceType = PageFeedModel.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class PageFeedModel {

    protected static final String RESOURCE_TYPE = "demoproject/components/page";
    private static final Logger logger = LoggerFactory.getLogger(PageFeedModel.class);
    @SlingObject
    ResourceResolver resourceResolver;
    @SlingObject
    SlingHttpServletRequest request;
    @Inject
    private Page currentPage;
    @Getter
    private String title;
    @Getter
    private String link;
    @Getter
    private String linkTag;
    @Getter
    private String description;
    @Getter
    private List < ChildPageModel > entries;
    @Inject
    private Externalizer externalizer;
    @Getter
    private String feedUrl;
    @Getter
    private String publishedDate;


    @PostConstruct
    protected void init() {
        try {
            ValueMap properties = currentPage.getContentResource().adaptTo(ValueMap.class);
            title = StringEscapeUtils.escapeXml(null != currentPage.getTitle() ? currentPage.getTitle() : properties.get(JcrConstants.JCR_TITLE, String.class));
            description = StringEscapeUtils.escapeXml(properties.get(JcrConstants.JCR_DESCRIPTION, String.class));

            link = RssFeedUtils.getExternaliseUrl(currentPage.getPath(), externalizer, resourceResolver);
            feedUrl = link + ".rss.xml";
            linkTag = RssFeedUtils.setLinkElements(link);

            String category = request.getParameter("category") != null ? request.getParameter("category").toLowerCase().replaceAll("\\s", "") : StringUtils.EMPTY;
            entries = new ArrayList < > ();
            Iterator < Page > childPages = currentPage.listChildren(new PageFilter(false, false));
            while (childPages.hasNext()) {
                Page childPage = childPages.next();
                ChildPageModel childPageModel = resourceResolver.getResource(childPage.getPath()).adaptTo(ChildPageModel.class);
                if (null != childPageModel) {
                    if (StringUtils.isBlank(category)) entries.add(childPageModel);
                    else {
                        String tags = childPageModel.getTags();
                        if (StringUtils.isNotBlank(tags)) {
                            tags = tags.toLowerCase().replaceAll("\\s", "");
                            List tagsList = Arrays.asList(tags.split(","));
                            String[] categoryList = category.split(",");
                            boolean flag = true;
                            for (String categoryStr: categoryList) {
                                if (tagsList.contains(StringEscapeUtils.escapeXml(categoryStr)) && flag) {
                                    entries.add(childPageModel);
                                    flag = false;
                                }
                            }
                        }
                    }
                }
            }
            publishedDate = RssFeedUtils.getPublishedDate(properties);

        } catch (SlingException e) {
            logger.error("Repository Exception {}", e);
        }
    }
}
//ChildPageModel 
package com.demoproject.aem.core.models;

import com.adobe.cq.export.json.ExporterConstants;
import com.day.cq.commons.Externalizer;
import com.day.cq.commons.jcr.JcrConstants;
import com.demoproject.aem.core.utility.RssFeedUtils;
import lombok.Getter;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

@Model(adaptables = {
    Resource.class
}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class ChildPageModel {
    private static final Logger logger = LoggerFactory.getLogger(ChildPageModel.class);

    @SlingObject
    Resource resource;

    @Getter
    private String title;

    @Getter
    private String link;

    @Getter
    private String linkTag;

    @Getter
    private String feedUrl;

    @Getter
    private String description;

    @Getter
    private String publishedDate;

    @Getter
    private String tags;

    @Inject
    private Externalizer externalizer;

    @PostConstruct
    protected void init() {
        try {
            if (null != resource) {
                String url = resource.getPath();

                ResourceResolver resourceResolver = resource.getResourceResolver();
                link = RssFeedUtils.getExternaliseUrl(url, externalizer, resourceResolver);
                feedUrl = link + ".rss.xml";
                linkTag = RssFeedUtils.setLinkElements(link);

                ValueMap properties = resource.getChild(JcrConstants.JCR_CONTENT).adaptTo(ValueMap.class);
                title = StringEscapeUtils.escapeXml(properties.get(JcrConstants.JCR_TITLE, String.class));
                description = StringEscapeUtils.escapeXml(properties.get(JcrConstants.JCR_DESCRIPTION, String.class));
                publishedDate = RssFeedUtils.getPublishedDate(properties);
                tags = StringEscapeUtils.escapeXml(RssFeedUtils.getPageTags(properties, resourceResolver));

            }
        } catch (SlingException e) {
            logger.error("Error: " + e.getMessage());
        }
    }
}
//RSS Feed Utils 

package com.demoproject.aem.core.utility;

import com.day.cq.commons.Externalizer;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.tagging.Tag;
import com.day.cq.tagging.TagManager;
import com.day.cq.wcm.api.NameConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/** 
 * @desc RSS Feed Utils 
 */
@Slf4j
public class RssFeedUtils {

    public static final String FORMAT_DATE = "E, dd MMM yyyy hh:mm:ss Z";
    public static final String CONTENT_PATH = "/content/demoproject/us/en";

    public static String getPublishedDate(ValueMap pageProperties) {
        String publishedDate = StringUtils.EMPTY;
        SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_DATE);
        Date updatedDateVal = pageProperties.get(JcrConstants.JCR_LASTMODIFIED, pageProperties.get(JcrConstants.JCR_CREATED, Date.class));
        if (null != updatedDateVal) {
            Date replicatedDate = pageProperties.get(NameConstants.PN_PAGE_LAST_REPLICATED, updatedDateVal);
            publishedDate = dateFormat.format(replicatedDate);
        }
        return publishedDate;
    }

    public static String getExternaliseUrl(String pagePath, Externalizer externalizer, ResourceResolver resourceResolver) {
        String url = StringUtils.EMPTY;
        if (StringUtils.isNotBlank(pagePath) && null != externalizer && null != resourceResolver)
            url = externalizer.publishLink(resourceResolver, resourceResolver.map(pagePath)).replace(CONTENT_PATH, "");

        return url;
    }

    public static String setLinkElements(String link) {
        String url = StringUtils.EMPTY;
        if (StringUtils.isNotBlank(link)) {
            url = "<link>" + link + "</link>";
        }
        return url;
    }

    public static String getPageTags(ValueMap properties, ResourceResolver resourceResolver) {
        String tags = StringUtils.EMPTY;
        String[] pageTags = properties.get(NameConstants.PN_TAGS, String[].class);
        if (pageTags != null) {
            List < String > tagList = new ArrayList < > ();
            TagManager tagManager = resourceResolver.adaptTo(TagManager.class);
            for (String tagStr: pageTags) {
                Tag tag = tagManager.resolve(tagStr);
                if (tag != null) {
                    tagList.add(tag.getName());
                }
            }
            if (!tagList.isEmpty()) tags = String.join(",", tagList);
        }
        return tags;
    }
}

Dispatcher Changes  

demoproject_rewrites.rules 

In the client project rewrites.rules (/src/conf.d/rewrites) file add a rewrite rule for .rss extension. This rewrite rule takes a URL ending with .rss and rewrites it to point to a corresponding rss.xml file in the page component, effectively changing the file extension from .rss to .rss.xml

#feed rewrite rule
RewriteRule ^/(.*).rss$ /content/demoproject/us/en/$1.rss.xml [PT,L]

100_demoproject_dispatcher_farm.any  

Set the URL parameters that should not be cached for the rss feed. It is recommended that you configure the ignoreUrlParams setting in an allowlist manner. As such, all query parameters are ignored and only known or expected query parameters are exempt (denied) from being ignored.

When a parameter is ignored for a page, the page is cached upon its initial request. As a result, the system subsequently serves requests for the page using the cached version, irrespective of the parameter’s value in the request. Here, we add URL parameters below to serve the content live as required by an external application.

/ignoreUrlParams {
    /0001 { /glob "*" /type "allow" }
    /0002 { /glob "category" /type "deny" }
    /0003 { /glob "pubdate_gt" /type "deny" }
    /0004 { /glob "pubdate_lt" /type "deny" }
}

 

Why is HTL Better?  

We can utilize this approach to produce any XML feed, extending beyond RSS feeds. We have the flexibility to add custom properties to tailor the feed to our specific needs. Plus, we can easily apply filters using query parameters.

 

Big thanks to my director, Grace Siwicki, for her invaluable assistance in brainstorming the implementation and completing this blog work.

]]>
https://blogs.perficient.com/2024/05/03/create-an-rss-feed-using-htl/feed/ 1 362326
Making a Splash and Growing with Perficient: From Solution Director to Adobe Managing Director https://blogs.perficient.com/2024/04/22/making-a-splash-and-growing-with-perficient-from-solution-director-to-adobe-managing-director/ https://blogs.perficient.com/2024/04/22/making-a-splash-and-growing-with-perficient-from-solution-director-to-adobe-managing-director/#respond Mon, 22 Apr 2024 20:25:23 +0000 https://blogs.perficient.com/?p=360219

Meet Matt Shields, Managing Director of Perficient’s Adobe Business Unit

Perficient’s Adobe business unit (BU) has grown organically over the years and is now one of Perficient’s largest partnerships. Starting with a single source contract, the Adobe practice at Perficient was built from the ground up.  When Matt Shields joined Perficient in 2015, the Adobe BU was on track for a promising growth trajectory and opportunity ahead. 

Matt's career journey timeline

As Managing Director, Matt supports the Adobe BU from an operational perspective, including everything from sales to delivery. He ensures the right leadership is in place to meet the growth goals and metrics of the Adobe BU and Perficient. Matt keeps a pulse on the business to continue laying the building blocks of success within Perficient’s Adobe practice. 

Matt’s Career Journey 

Matt’s professional journey at Perficient began in October 2015 when he joined the Adobe BU as a senior manager of delivery. He progressed to become the director of delivery and then moved into the practice director role. In July 2023, he stepped into his current role as managing director of the BU. 

Prior to joining the Perficient team, Matt’s career journey depicts how he acquired the ability to “sink or swim in any environment,” as he puts it. Upon earning his undergraduate degree in financial services and obtaining licensing, Matt became a financial advisor to mesh his skill with numbers and desire to interact with people. 

“I valued this time in my career tremendously; I learned so much, including how to have conversations with folks about difficult personal experiences. Unfortunately, this point in my career occurred during the market crash of 2008. It was very upsetting to talk with people who had lost their life savings and would have to change their way of life. This was a scenario that no one was able to prevent, and it caused me to take a long, hard look at what I was doing. I ultimately decided this was not what I wanted to do, so I went back to school to get an MBA.”  

Original Eb23bfd2 Ab6a 4575 9708 E6d2144de4ef[1]

In just nine months, Matt earned an MBA with a focus in project management. Within a week of graduating, he received a call from a small technology consultancy based in Dayton, Ohio. He was tasked to support a government contractor as a senior project manager onsite in Columbus, Ohio.

“I was the only person from my company supporting this customer. I had zero experience just coming out of school, and I was put in a role on a large initiative. I realized very quickly that this was a sink or swim scenario. The first six months was probably the most hectic and anxiety ridden of my career.” 

Having been thrown into the deep end, Matt had to learn quickly on the job. Despite having some self-doubt, his ability to focus on gaining a deep understanding of his role and the business allowed him to excel.  

“I look back on this experience now, and I view it as one of the most beneficial things that ever happened to me in my career. It forced me to dive in head-first and learn everything I could from the business side, to project management and delivery. I’m so grateful to have fallen into consulting and technology.”

Growth Built From the Ground Up

Given the Adobe BU’s history of impressive growth, Matt is no stranger to implementing a growth-oriented mindset. There were roughly 20 colleagues supporting the Adobe platform when Matt joined Perficient, which has since expanded to hundreds of colleagues worldwide.  

Read More: Perficient’s Adobe Thought Leadership

Original 2adfe951 5c6c 4f3b A462 C6cd158c2e84[1]

Joining Perficient’s Adobe practice in the earlier days allowed Matt to gain a greater understanding of how Perficient operates and how the Adobe BU supports opportunities at an enterprise level. This helped instill Matt’s growth mindset by seeing how opportunity within Adobe can benefit and spread across the entire organization. 

“All of the work the Adobe BU has done to collaborate across Perficient and with teams around the world has put us in a very good position to drive growth within our global organization. We are very proud of our organic growth and the company-wide effect it has made to increase overall growth.” 

One of the ways Matt has propelled growth is by building strong relationships. He can identify where individuals will be best positioned within the practice by getting to know them and understanding their skill sets and career goals. 

“I want to know everyone in this practice and understand what they’re good at, what they like to do, where they want to grow, and what makes them uncomfortable. All of this is helpful to know when ensuring that people are well aligned in their role. As a result, we’re helping our clients in the best ways we can.” 

Group eating together at table

Developing high-performing teams with dedicated and skilled colleagues is one of the ways Perficient closes new business deals as well as retaining existing clients. This is a driving motivator for Matt to understand the people who enable the business’ success.

“I’ve always focused on our people. Our people are the reason we’re able to grow within Perficient. Growth in our capabilities, our careers, and our communities are what makes it all worth it. Our people are why we have so many multi-year relationships with Perficient’s clients and such a strong foundation for repeat business.”

Read More: Perficient Puts Colleagues in the Driver’s Seat of their Careers

Key Takeaways Three men smiling for the camera

A growth mentality is woven into the fabric of the Adobe BU’s foundation, and Matt is a strong proponent of continuing this momentum. His focus on people, both his colleagues and clients, lays the groundwork for further opportunity and growth. 

Perficient’s culture and success are defined by our colleagues. The Growth for Everyone initiative aims to build a culture that celebrates our colleagues’ unique accomplishments and supports them in reaching their goals. Growth, both personal and professional, is encouraged at Perficient, and we are building a workplace where achieving career growth goals is well within reach. 


MORE ON GROWTH FOR EVERYONE 

Perficient continually looks for ways to champion and challenge our workforce, encourage personal and professional growth, and celebrate the unique culture created by the ambitious, brilliant, people-oriented team we have cultivated. These are their stories. 

Learn more about what it’s like to work at Perficient on our Careers page. Connect with us on LinkedIn here. 

]]>
https://blogs.perficient.com/2024/04/22/making-a-splash-and-growing-with-perficient-from-solution-director-to-adobe-managing-director/feed/ 0 360219
Fusing His Passions for World Travel and Adobe Digital Marketing, Jay Jackson Expedites Growth https://blogs.perficient.com/2024/03/21/fusing-his-passions-for-world-travel-and-adobe-digital-marketing-jay-jackson-expedites-growth/ https://blogs.perficient.com/2024/03/21/fusing-his-passions-for-world-travel-and-adobe-digital-marketing-jay-jackson-expedites-growth/#respond Thu, 21 Mar 2024 13:30:12 +0000 https://blogs.perficient.com/?p=359502

Utilizing unique personal and professional experiences, Atlanta-based Adobe marketing expert, Jay Jackson, excels in his role as the Director of Perficient’s Adobe Digital Marketing practice. Before Perficient, Jay held various customer marketing leadership roles. With over 20 years of experience aiding Fortune 500 companies to enhance customer satisfaction, drive organizational efficiencies and boost revenue, he understands what truly matters to customers.  

Img 20180813 161543 Edited

In addition to his professional credentials, Jay is a passionate world traveler having visited over 107 countries, most recently Thailand. As Jay was interviewing to join Perficient five years ago, he was on a year-and-a-half sabbatical and had his initial interviews with Perficient in Ukraine and Prague. This personal sabbatical and all his traveling experiences allowed him to immerse himself in diverse cultures, languages and perspectives. His experiences have shaped him into a well-rounded leader who can sensitively and objectively adapt to the varying needs of a global workforce.  

Like running with the bulls in Spain, or going on a safari in South Africa, Jay understands that every customer is unique, just like the unique experiences of each country he’s visited. Continue reading to learn how Jay leverages his experiences to grow the practice globally while viewing the implementation of Adobe products as a means to help customers achieve their goals.  

Describe your role. What does a day in the life look like?  

My role as director of the Adobe Digital Marketing practice is twofold. Half of my responsibilities surround sales support to exponentially grow the business. This involves anything from helping prospective customers understand the “Art of the Possible” from an Adobe solution standpoint to building long-lasting “Trusted Advisor” relationships. The other half is delivering value. It’s one thing to simply sell a solution, but it’s another to deliver it well.  This includes project delivery management, solution expertise, sophisticated staffing models, resource hiring/enablement, continuous evaluation/client feedback loops, and ultimately consistent measurement of client objectives to ensure the return on their investment with Perficient. 

What makes you passionate about digital marketing with Adobe?  

Jay Jackson in Thailand

I have a background as a marketer, and I’m passionate about helping our customers make money. I’m not shy about that, it’s why we’re here. It excites me to help customers realize the value of their investments, but it goes beyond that. A lot goes into each client interaction, and each client has different needs and overall goals. Many of our customers are large, multi-national companies with shareholders who want to see a return on their investment, and strategizing how to successfully execute is another main driving factor behind my passion.

Share some insights about your upcoming speaking session at Adobe Summit, “Done in 60 Days: Driving B2B Personalization with Adobe Experience Platform.

The days of customer experience being the sole domain of B2C experiences are gone. Relevant, personalized, and real-time experiences are required to drive B2B digital marketing objectives. I believe this session gives us a platform to showcase our expertise alongside a global leader in wireless technology as we discuss how we drove end-to-end implementation and bidirectional integration of the Adobe Experience Platform to achieve personalized experiences at scale.  

The work we do and the impact we make, I believe, is why we were selected to present at Adobe’s conference. I look forward to showing the value Perficient brings, in a way that members of the audience recognize our extensive capabilities and expertise.  

Register for the Exclusive Fireside Chat with Perficient and Morgan Stanley 

 

In addition to the speaking sessions, what are you looking forward to at this year’s Adobe Summit?  

I always look forward to interacting and connecting with existing and prospective customers. Adobe Summit also presents an exciting opportunity to learn new things. There are always announcements of new products and capabilities at Summit, and as head of the delivery arm, it’s important that I’m in the know with the latest information to better inform our roadmaps. Beyond the announcements, the labs at the conference also allow me to understand the technology and remain technically competent from a hands-on perspective, ensuring I’m properly hiring, managing and mentoring team members.  

What does it mean to you that we’re seeing more opportunities specific to Adobe in analyst relations?  

Jetpack

I believe the increasing opportunities specific to Adobe in analyst relations first and foremost signify enhanced brand recognition. As our brand becomes more prominent in the market, our inclusion in reports from reputable third parties like Forrester, Gartner, or IDC amplifies our brand awareness. In turn, potential customers are becoming more familiar with who we are.  

It’s crucial to not only help people understand our brand but also to demonstrate our expertise through these unbiased report inclusions. While advertising is one approach to increasing our brand recognition, having our capabilities objectively outlined by organizations with no stake in Perficient’s or Adobe’s success is another level of credibility altogether. It not only enhances our credibility but, in my opinion, also significantly boosts our brand recognition and exemplifies our Adobe capabilities.  

LEARN MORE: Perficient Included in Forrester’s Adobe Services Landscape, Q1 2024 Report 

How are you making a difference at Perficient?  

I’ve been driving growth and I feel it has several impacts; one simply being that we’re obtaining more business, which impacts Perficient’s overall goals and revenue. In turn, this has an effect on how we hire and retain resources. As we intentionally instill our culture throughout the organization, that could be tied to Perficient regularly being named a Best Place to Work, stemming directly from employee insights. If our colleagues are happy, we’re more likely to make our customers happy, and we’ve seen this create opportunities for future projects.  

What made you choose Perficient, and what keeps you here?  

Cabo Dune Buggy

The true differentiator was the ability to work with numerous customers within multiple verticals and industries with a vast array of challenges to be solved with individualized Adobe solutions.  

As I went through the interview process, it was clear from my new boss that the ultimate goal was to construct a new Adobe Digital Marking practice.  Initially starting as Adobe Digital Marketing “Employee #1,” throughout the past five years, I’m proud to say we’ve grown to a team of more than 30 direct colleagues worldwide supporting every solution within the Adobe Experience Cloud portfolio (with hundreds more indirectly supporting data services, QA, project management, etc.). We continue building and expanding our global resources, and our unique growth trajectory year over year allows us to see continued success.  

What are your proudest accomplishments?  

There have been a lot of great moments at Perficient. Some are very timely like being selected by Qualcomm, Morgan Stanley, and Adobe to showcase our expertise at Adobe Summit in two speaking sessions. In a broader scope, I’m proud of Adobe’s perspective of Perficient, and our recognition as a trusted partnerAlso, being named an Adobe Partner of the Year for the Americas last year at Summit was a testament to our outstanding Adobe business unit at Perficient. Most importantly, however, is helping our clients succeed – it’s what contributes to our repeat business rate of more than 94%.

READ MORE: Perficient Named 2023 Adobe Digital Experience Emerging Partner of the Year, Americas 

Why are you Proudly Perficient?  

Wp 20160702 14 24 50 Pro

I’m proud to be a part of Perficient because of the flexibility and autonomy of my role. There are plenty of companies that do Adobe work, but being at Perficient gives me the autonomy to drive results derived from my experience and do what’s right for our customers and Perficient. Building the practice from the ground up allowed me to create the rules as I went along. There’s a level of trust that’s bestowed upon me to drive results, and I think those results have spoken for themselves. Nonetheless, I couldn’t have gotten here without the autonomy and trust in the first place.  


SEE MORE PEOPLE OF PERFICIENT   

It’s no secret our success is because of our people. No matter the technology or time zone, our colleagues are committed to delivering innovative, end-to-end digital solutions for the world’s biggest brands, and we bring a collaborative spirit to every interaction. We’re always seeking the best and brightest to work with us. Join our team and experience a culture that challenges, champions, and celebrates our people.   

Visit our Careers page to see career opportunities and more!   

Go inside Life at Perficient and connect with us on LinkedIn, YouTube, Twitter, Facebook, TikTok, and Instagram. 

]]>
https://blogs.perficient.com/2024/03/21/fusing-his-passions-for-world-travel-and-adobe-digital-marketing-jay-jackson-expedites-growth/feed/ 0 359502
Secure and Personalized Commerce for Healthcare and Life Sciences https://blogs.perficient.com/2024/03/14/hipaa-ready-and-personalized-commerce/ https://blogs.perficient.com/2024/03/14/hipaa-ready-and-personalized-commerce/#respond Thu, 14 Mar 2024 12:31:16 +0000 https://blogs.perficient.com/?p=357986

The ability to offer healthcare products and services digitally is more important than ever. In fact, the global healthcare eCommerce market is projected to reach $994.2 billion by 2030. But a complex regulatory landscape and data privacy and security concerns are formidable obstacles. Additionally, consumer demand for proactive, personalized experiences is at an all-time high.

So how can healthcare and life sciences organizations capitalize on this opportunity?

HIPAA-Ready and Personalized Commerce Lunch at Adobe Summit

Perficient and Adobe are partnering at Adobe Summit 2024 to share insights on industry trends and discuss how Adobe is revolutionizing healthcare commerce with Adobe Commerce’s ability to deliver HIPAA-ready and personalized commerce experiences. Join us during our HIPAA-Ready and Personalized Commerce lunch on Wednesday, March 27 at 11:30 A.M. in The Grand Lux Café in The Palazzo.

Attendees will have the opportunity to grab lunch (and skip long lines), connect with industry peers, and hear insights from Justin Racine, a unified commerce strategy principal at Perficient, and Tom Swanson, Adobe’s head of industry strategy and marketing for health and life sciences,  before heading to the Adobe Summit afternoon sessions.

Perficient and Adobe host HIPAA-Ready and Personalized Commerce lunch session at Adobe Summit 2024

What to Expect

  • 11:30 A.M. | Lunch Orders: Complimentary lunch orders will be taken until 12:00
  • 12:00 P.M. | Discussion: Enjoy an informative review of HIPAA regulation’s relevance to healthcare commerce, how to enhance the patient experience, and a demonstration of Adobe Commerce.
  • 12:30 P.M. | Lunch and Networking: Dine and connect with healthcare and life sciences industry peers who share your passion for digital excellence before heading off for afternoon sessions at Adobe Summit.

This event will emphasize the significance of data protection for covered entities and privacy-conscious brands and share how introducing next-gen commerce capabilities can empower seamless end-to-end experiences for your consumers, driving impact for your business.

Register Today

Join us for this exclusive lunch session on the second day of Adobe Summit. You must register to attend. Secure your spot today!

HIPAA-Ready and Personalized Commerce Lunch

Wednesday, March 27th | 11:30 A.M. – 1:00 P.M. PST

The Grand Lux Cafe in The Palazzo

REGISTER!

Learn More About HIPAA-Ready and Personalized Healthcare

We’ve helped Adobe build its new HIPAA and PHI-ready commerce solution to help reduce risks and improve experiences. Check out our blog series that discusses different use cases for HIPAA-Ready Adobe Commerce.

3 Ways Adobe Commerce Enhances Patient-Provider Relationships

How Adobe Commerce Can Impact Payor Strategies

Adobe Commerce, Medical Device & Life Sciences, and … Golf?

3 Ways Adobe Commerce Elevates Pharmacy Services

]]>
https://blogs.perficient.com/2024/03/14/hipaa-ready-and-personalized-commerce/feed/ 0 357986
Automotive and Manufacturing: How to Modernize, Innovate, and Win in 2024 https://blogs.perficient.com/2024/03/04/automotive-and-manufacturing-how-to-modernize-innovate-and-win/ https://blogs.perficient.com/2024/03/04/automotive-and-manufacturing-how-to-modernize-innovate-and-win/#respond Mon, 04 Mar 2024 18:07:07 +0000 https://blogs.perficient.com/?p=357960

The automotive and manufacturing industry continues to be heavily impacted by digital disruption while customer experiences and business models are being reimagined.

So how do you modernize, innovate, and win in this increasingly competitive market?

Exclusive Automotive and Manufacturing Breakfast at Adobe Summit 2024

Perficient and Adobe are partnering at Adobe Summit 2024 to share insights on industry trends and discuss how to put your entire plant-to-dealer operations on the right track during our Automotive and Manufacturing Breakfast on Wednesday, March 27 at 8:00 A.M. in The Grand Lux Café in The Palazzo.

Attendees will have the opportunity to grab breakfast (and skip long lines), connect with industry peers, and hear insights from Robert Sumner, a principal Adobe consultant at Perficient, and Neerav Bhansali, Adobe’s head of industry strategy, automotive, and mobility before heading to the Adobe Summit keynote.

Adobe Summit 2024 Automotive And Manufacturing Breakfast With Perficient

What to Expect

  • 8:00 A.M. | Breakfast: Complimentary breakfast will be available until 9:00
  • 9:00 A.M. | Discussion: Learn how to shift your automotive and mobility transformation into high gear.
  • 9:30 A.M. | Networking: Connect with automotive and manufacturing industry peers who share your passion for digital excellence before heading off for to the Adobe Summit keynote session.

You’ll leave this session with practical strategies and knowledge that can be applied to drive success in the automotive and mobility sector.

Register Today

Come kickstart the second day of Adobe Summit with us. You must register to attend. Secure your spot now!

Your Adobe Partner

Learn more about supercharging the customer journey and delivering exceptional digital experiences by checking out our Adobe blogs.

]]>
https://blogs.perficient.com/2024/03/04/automotive-and-manufacturing-how-to-modernize-innovate-and-win/feed/ 0 357960
Morgan Stanley Supercharged Its Customer Journey. Learn How at Adobe Summit 2024! https://blogs.perficient.com/2024/02/28/how-morgan-stanley-supercharged-its-customer-journey/ https://blogs.perficient.com/2024/02/28/how-morgan-stanley-supercharged-its-customer-journey/#respond Wed, 28 Feb 2024 17:01:23 +0000 https://blogs.perficient.com/?p=357503

Adobe Summit 2024 is right around the corner, and we’re excited to sit down with the executive director and head of marketing applications at Morgan Stanley Dorothy Joseph on March 27 at 11:30 A.M PST at The Grand Lux Café in The Palazzo.

Perficient’s Jay Jackson, director of Adobe Digital Marketing and CDP, will host a fireside chat with Joseph about the global financial services leader’s successful journey to consolidate and optimize the Adobe Experience Platform.

The audience will hear about the transformation that enabled Morgan Stanley to upgrade to Adobe Customer Journey Analytics, Target, and Customer Data Platform.

Adobe Summit Fireside Chat with Morgan Stanley and Perficient

Register for the Exclusive Fireside Chat With Morgan Stanley

If you’re attending Adobe Summit 2024, make sure to include this lunch session on your agenda.

You must register to attend. Secure your spot now!

What to Expect

  • Complimentary lunch
  • Hear how Morgan Stanley supercharged its customer journey
  • An opportunity to connect with peers who share your passion for digital excellence in the financial services industry before heading off for afternoon sessions at Adobe Summit

Your Adobe Partner

Learn more about supercharging the customer journey and delivering exceptional digital experiences by checking out our Adobe blogs.

]]>
https://blogs.perficient.com/2024/02/28/how-morgan-stanley-supercharged-its-customer-journey/feed/ 0 357503
Workflow Model in AEM https://blogs.perficient.com/2024/02/21/workflow-model-in-aem/ https://blogs.perficient.com/2024/02/21/workflow-model-in-aem/#respond Wed, 21 Feb 2024 08:04:22 +0000 https://blogs.perficient.com/?p=353830

Workflow Model

A Workflow Model represents a definition (model) of a workflow. It is made of Workflow Nodes and Workflow Transitions.

Workflow models in Adobe Experience Manager (AEM) are used to define the series of steps executed when a user starts a workflow, and it is used for the automatic processing of content as well as facilitating governance and processes requiring human decision-making. Workflows enable you to automate processes for managing resources and publishing content in your AEM environment.

AEM Workflow provides a way to collaborate, manage, and process content in AEM.

We can create a workflow model to define the steps executed when a user starts the workflow.

The workflow component could specify process arguments to the code; it always has a start and end node.

AEM Workflow Model Editor

The AEM Workflow Model Editor is a tool that allows you to create and edit workflow models.

Workflows implement business processes in AEM, and the workflow model is defined as a task. It is divided into two main categories.

  1. Scheduled Workflow – This uses AEM content.
  2. Manual Workflow – This retrieves content from a business process (e.g., content review workflow).

Steps to Create a Workflow

  1. The steps, Flow Start and Flow End. These represent the beginning and end of the workflow. These steps are required and cannot be edited/removed.
  2. An example Participant step is named Step 1. This step is configured to assign a work item to the workflow initiator. Edit or delete this step, and add steps as required.
Workflowm1

Fig: New Workflow Creation

Steps to Create a Workflow with the Editor

  1. Open the Workflow Models console; via Tools, Workflow, Models, for example, https://localhost:4502/aem/workflow

    Workflowm2

    Fig: AEM Tools

  2.  Select Create, then Create Model.

    Workflowm3

    Fig: AEM Workflow Models Console

  3. The Add Workflow Model dialog appears. Enter the Title and Name (optional) before selecting Done.

    Workflowm4

    Fig: Workflow model Author component

  4.  The new model is listed in the Workflow Models console.

    Workflowm5

    Fig: AEM Workflow Models Console

How to Edit/Update the Workflow Model

  1. Select a workflow and click Edit.
  2. Check the workflow steps that represent work from the workflow model.
  3. Validate Content – Used to validate a workflow payload.
  4. Publish Content – Copies content to an AEM publication for immediate publishing.

    Validateandpublish

    Fig: Workflow model author page

  5. Edit the workflow model that has settings for the workflow model and its entities.

    Wfconfig

    Fig: Workflow model page property

  6. Start and run the workflow model and synchronize and publish the workflow model.

    Createwf

    Fig: Publish Workflow model

We can apply more than one workflow to a page.

  1. We can implement any workflow (that you have access to as defined by your AEM administrator).
  2. Optionally, a title that helps identify the workflow instance in a user’s Inbox.
  3. Workflow payload, it can be one or more pages.

Apply Workflow to a Page

  1. Navigate and select the desired page.
  2. You can now select a workflow from the Create option in the toolbar.

    Create

    Fig: AEM author page

  3. Select the created workflow model, add a workflow title, and click the Next button.

    Details

    Fig: Create workflow

  4. Add content and click the Create button.    Addcontent
  5. We can also start the workflow from author mode. Go to Author Page > Select Work to start workflow; Add details and click Start Workflow. It will start directly from the AEM Site Editor.

    Start

    Fig: Start Workflow

  6. Click on complete and complete the workflow.

    Complete

    Fig: Complete Workflow

Conclusion

By understanding workflows, we can create a new workflow model. This gives you the flexibility and control to create custom workflows that meet the specific needs and scenarios of your business.

Workflows are a way to organize and automate tasks to achieve a specific goal. This helps you ensure content quality and consistency.

This gives you the flexibility and control to create custom workflows that fit the specific needs and scenarios of your business.

The workflow template editor allows us to define steps, activate the workflow, and update the workflow according to specific needs.

 

 

]]>
https://blogs.perficient.com/2024/02/21/workflow-model-in-aem/feed/ 0 353830
Adobe Target Recommendations Designs: Iterating Over $entityN.variable https://blogs.perficient.com/2024/02/01/adobe-target-recommendations-designs-iterating-over-entityn-variable/ https://blogs.perficient.com/2024/02/01/adobe-target-recommendations-designs-iterating-over-entityn-variable/#comments Fri, 02 Feb 2024 00:34:28 +0000 https://blogs.perficient.com/?p=352263

Adobe Target Recommendations uses the open-source Apache Velocity Engine – with an emphasis on velocity – to retrieve recommendations data. A Recommendations Design is a specialized Target offer populated at runtime with the entities, i.e., products or items, to be displayed. This is done by incorporating Velocity Template Language (VTL) identifiers to denote entity attributes using the following syntax: $entityN.variable.  

Recommmendations HTML Design exampleWriting $entityN.variable N times ignores the third concept of structured programming: iteration.

Up to 99 entities can be referenced in a design and for each attribute $entityN.variable is written N times. This is the case in HTML designs (shown above) and non-HTML JSON responses fetched, for example, via “rawbox” (raw mbox or ubox) calls: 

Recommendations Design JSON example

Declaring an identical object repeatedly ignores the third concept of structured programming: iteration (the first two being sequence and selection), and soon becomes tedious. As one Adobe Target forum participant asked: 

“Is there a way to make HTML dynamic? I have a requirement to display 50 contents based on Recommendations. But instead of writing it 50 times, is there a way like ‘loop’ to iterate on all recommended content?”

So, Can You Iterate Over Entities?

The short answer probably has to do with Adobe’s decision to strike the right balance between accessibility and complexity. As powerful and flexible a solution as Recommendations is, the ability to implement it effectively means not asking marketers to dabble in VTL. Viewed this way, verboseness in the templates is an acceptable trade-off.  

The longer answer is, yes, it’s doable and Adobe’s Customize a design using Velocity page is instructive. The overview states that “any type of attribute can be sent; however, Target does not pass attributes of type ‘multi-value’ as an array over which a template can iterate (for example entityN.categoriesList). These values are referenced with the following syntax: $entityN.variable.” Further, “The following attributes are available as Velocity arrays. As such, they can be iterated over or referenced via index: entities and entityN.categoriesList.”  

The last example, Customizing the template size and checking for blank values, shows this usage:

Adobe Customize Design Using Velocity

Leveraging the $entities Array

In a sense, we have the solution that solves the problem. Yet the Separation of Concerns principle as it pertains to data and display is not observed and the code can be difficult to manage. A Recommendations Design necessarily contains the presentation layer and the data access layer, but the two are not treated discretely. What if we want an array of entities with a specified set of attributes, as in the JSON above – without having to spell out the entire object beforehand? This can be done using the iterable $entities array: 

Iterating over $entities array

Ten entities with six built-in attributes and three custom attributes (application, industry, resourceType) are returned. Notable is the handling of zero-based (index) and one-based (count) indexing, and the dynamic evaluation of variables at render time. The result is an object that can be sanitized, filtered, and otherwise manipulated to satisfy business and display requirements. 

Entities object

Finally, iterating directly over $entityN.variable is similarly possible, producing the same result:

Iterating over $entityN.variable

#set ( $items = [0..9] )
#set ( $attributes = [
    'categoriesList', 'id', 'message', 
    'name', 'pageUrl', 'thumbnailUrl', 
    'application', 'industry', 'resourceType'
] )

<script type="text/javascript">
    const entities = Array.from({ length: '$items.size()' }, () => ({}));
</script>

#set ( $d = '$' )
#foreach ( $attr in $attributes )
    #foreach ( $i in $items )
        #set( $count = $i + 1 )
        #set ( $varName = "${d}entity${count}.${attr}" )
        <script type="text/javascript">
                entities['$i']['$attr'] = '#evaluate($varName)';
        </script>
    #end
#end

 

Streamlining Adobe Target Recommendations

Hopefully, the information provided in this tutorial will give you and your team a better understanding of how to streamline Target Recommendations Designs.  

Check out some of our other Adobe blogs to find out other ways to get the most out of Adobe Target. 

Your Adobe Target Partner 

We are an Adobe Platinum Partner with a specialization in Adobe Target (along with five more specializations in AEM Sites, AEM Run & Operate, Adobe Analytics, Adobe Commerce, Marketo Engage). And we were named the Adobe Digital Experience Emerging Partner of the Year Americas this year.   

Learn more about our Adobe experts, services, and capabilities here. 

]]>
https://blogs.perficient.com/2024/02/01/adobe-target-recommendations-designs-iterating-over-entityn-variable/feed/ 1 352263