How to craft Personalized Digital Experiences using Acquia Lift?

A few decades ago, companies were involved in the mass production of products and services with very limited options for customers to choose from. In the following years, increased competition and technological advancements resulted in the entire process being redefined with Customer Centricity as the core value.

In the digital world, websites and platforms have a huge amount of content and options available for users. The essence of Personalization is to provide the right content, at the right time, to the right person. Businesses like Amazon, Netflix, NewYork Times, etc have successfully used Personalization to create successful customer experience examples.

Acquia Lift

Acquia introduced a marketing solution named Lift in the year 2014. And the Drupal community has helped in fine-tuning it to its latest offering, version-4. Lift uses data to improve the experience for the user and it will result in increased engagement and loyalty. It is a user-friendly tool built for drupal which has the capability to do adaptive targeting. The capabilities and features that make Lift an effective Personalization tool is given below.

a) Profiling and Segmentation - Important User data like location, device type, content preference, etc are captured and analyzed. It helps to create different segments that can be targeted separately using different strategies. For Eg, users from various locations will be viewing different Hero banners that are most relevant for them.

b) Campaigns - Marketing runs on Campaigns and it is easy to create and execute campaigns using Acquia Lift. First, we need to set the objectives and goals for the campaign. A form of the campaign like A/B type, Recommendations or a combination is selected after that. Then the right segments are selected for targeting.


c) Advanced Features

  • Point and Click - To make personalization easier, Lift has introduced a new form without code. So, technical knowledge is not a prerequisite for users to optimize the content.
  • Scheduling- Creating a campaign and scheduling it for a future date or specific event is a feature of Lift that is very helpful when you need to create and run multiple campaigns
  • Live data - Live User data is analyzed to fine-tune personalization and provide the most relevant content.
  • Review - We can view all the active campaigns together and check how each campaign is performing in terms of click-through rate and conversion rate. It is presented in a visual format using graphs.

This video will help you in understanding how we can use Lift effectively for marketing initiatives. 

In today’s business world, there is no discussion on ‘whether to personalize or not?’. Personalization is not a luxury anymore. It is a necessity that businesses need for growth or even survival. Tools like Lift make sure that your content management system and the users blend in perfectly and thus adding value in the process.

It helps your business stay ahead of the curve and provide an omnichannel customer journey to create personalized digital experiences, building a pool of loyal customers. Do get in touch with us to know more about how Acquia Lift can help your business.

How Drupal can help in creating amazing Digital Experiences?

Traditionally, companies used to focus primarily on product designs and features. The underlying assumption was that the best product will automatically bring in the best results. Recently, businesses started developing a holistic view of the customer journey and decision-making process. So, detailed attention is given to Customer experience and how it can be enhanced at each stage. 

In today’s technology-driven world, there are too many entities vying for the customer's attention. Hence, to succeed in the digital world, you should understand the digital customer journey, and design each and every interaction with the customer in a way that results in the best overall digital experience for him.  Let’s examine how Drupal stacks up against the essential attributes of successful digital customer experience for your business. 

Performance Matters 

Nowadays, Customers have very high expectations about performance aspects like loading time, installation time, etc. 

They say it takes a village to raise a child. Similarly, it takes a vibrant community to grow an open-source technology. Drupal benefits from the contributions from the developers and enthusiasts across the globe who always look for ways to optimize the performance. It gives Drupal the capacity to work efficiently even when there is heavy traffic of users. 

Implementation of many performance tools like Redis, Varnish, Memcache or Bigpipe helps in smart caching and it ensures consistent page loading. A plethora of off the shelf CDN services integration options enables the availability of relevant assets based on the geographic location of the user. So, acclaimed companies like Tesla use Drupal for their website.

Feeling of Safety 

In the digital world, businesses gather a lot of data about the Users, directly and indirectly, including very private information, financial information, and proprietary information. And then, there is the constant issue of security threats in the form of phishing, cyber attacks, data leaks, etc. To succeed in gaining the trust of users, companies need to convince them that their privacy is protected with the utmost care.

The strength of a chain is its weakest link. 

Drupal has a dedicated security team of experts from different parts of the globe that focuses on resolving issues. Information about vulnerabilities and solutions are also made available to the community periodically.
Drupal’s security measures meet International standards like OWASP (The Open Web Application Security Project) and that is the reason why numerous Governmental websites like https://www.nasa.gov/ and   https://www.australia.gov.au/ trust Drupal.

Personalization

‘One size fits all’ doesn't work in today’s world where customers expect tailor-made solutions for their challenges. Personalization started initially with a few categories based on color, size, price, etc. Now, it has grown to a level where even minute preferences and concerns of customers are considered and a solution is designed specifically to meet those. Drupal has a robust framework that can manage the varying requirements of different websites and applications.

Acquia offers a new product named Acquia Lift, which is a fast and effective personalization tool. It has a no-code version which makes it easier to use, even for users with no technical background. Besides that, the vibrant Drupal Community has created thousands of contributed modules that help with very specific requirements. For eg, a Smart Content module can be used to deliver segmented content based on options like industry or your target user persona.

Ease of Use

An intuitive UI is needed for customers so that they are not affected by the heavy underlying processes. This requires a flexible system matching the demanding needs of new-age users. Headless Drupal with APIs allows you to work with any modern front end framework like AngularJS, ReactJS, VuJS, NextJS or even other Drupal websites.

Omnichannel

Customers interact with the system through various touchpoints in multiple channels. It is imperative that all the different channels like website, mobile, App, Kiosk, etc should provide consistent information, providing a smooth and enriching digital journey. 

This is especially important for companies engaged in e-commerce as the customer will be accessing information about the products and going through the purchase process through different channels. Drupal can act as the single source of Content which can be managed by various content managers and directed through various channels and touchpoints.  

A closer look makes it evident how the features of Drupal can help in improving the ROI, Customer Acquisition and Retention while being an Open-source platform. Get in touch with us to know more about how Drupal can help your business create spectacular digital experiences for customers.

Creating email templates using custom config entities in Drupal 8

In projects, there are multiple trigger points where emails have to be sent. In Drupal 7, we had the option where we could define a template and set up rules to trigger emails based on defined action.

But the rules module is still under active migration from D7 to D8, and we were short of time to complete the project.

So, we decided to create custom config entities for creating email templates. There was a need to have a configuration page where admin can add new templates having the subject field as well as text body. To help the admin user,  we had to list out all variables available on the same config page. In our case, since the list of trigger actions was pre-defined, we added them programmatically. These actions are available during the email template creation page.

The following steps show how we have implemented it.

Step 1 - Created a custom config entity ‘email_templates’ for the custom module ‘projectname_email_templates’ using the drupal console.

Steps to Generate a custom module using the drupal console:

drupal generate:module
// Welcome to the Drupal module generator
Enter the new module name:
> projectname_email_templates
Enter the module machine name [projectname_email_templates]:
>
Enter the module Path [modules/custom]:
>
Enter module description [My Awesome Module]:
> Module  for email templates
Enter package name [Custom]:
>
Enter Drupal Core version [8.x]:
>
Do you want to generate a .module file? (yes/no) [yes]:
> yes
Define module as feature (yes/no) [no]:
> no
Do you want to add a composer.json file to your module? (yes/no) [yes]:
> yes
Would you like to add module dependencies? (yes/no) [no]:
> no
Do you want to generate a unit test class? (yes/no) [yes]:
>
Do you want to generate a themeable template? (yes/no) [yes]:
> yes
Do you want proceed with the operation? (yes/no) [yes]:
> yes
// generate:composer
Generated or updated files
Generation path: /var/www/html/Drupal_proj/my_proj/web
1 - /modules/custom/projectname_email_templates/projectname_email_templates.info.yml
2 - /modules/custom/projectname_email_templates/projectname_email_templates.module
3 - /modules/custom/projectname_email_templates/tests/src/Functional/LoadTest.php
4 - /modules/custom/projectname_email_templates/projectname_email_templates.module
5 - /modules/custom/projectname_email_templates/templates/projectname-email-templates.html.twig
6 - modules/custom/projectname_email_templates/composer.json
Generated lines: 100

Steps to Generate custom config entity using the drupal console:

drupal generate:entity:config
// Welcome to the Drupal Config Entity generator
Enter the module name [address]:
> projectname_email_templates
Enter the class of your new config entity [DefaultEntity]:
> EmailTemplates
Enter the name of your new config entity [email_templates]:
>
Enter the label of your new config entity [Email templates]:
>
Enter the base-path for the config entity routes [/admin/structure]:
>
Generated or updated files
Generation path: /var/www/html/VB/horse-auction/web
1 - modules/custom/projectname_email_templates/config/schema/email_templates.schema.yml
2 - modules/custom/projectname_email_templates/projectname_email_templates.links.menu.yml
3 - modules/custom/projectname_email_templates/projectname_email_templates.links.action.yml
4 - modules/custom/projectname_email_templates/src/Entity/EmailTemplatesInterface.php
5 - modules/custom/projectname_email_templates/src/Entity/EmailTemplates.php
6 - modules/custom/projectname_email_templates/src/EmailTemplatesHtmlRouteProvider.php
7 - modules/custom/projectname_email_templates/src/Form/EmailTemplatesForm.php
8 - modules/custom/projectname_email_templates/src/Form/EmailTemplatesDeleteForm.php
9 - modules/custom/projectname_email_templates/src/EmailTemplatesListBuilder.php
Generated lines: 269

 

Step 2 - In email_templates.schema.yml (projectname_email_templates/config/schema): Define the variable and its type.

Step 3 - In EmailTemplates.php (projectname_email_templates/sec/Entity) : Define the template entities like entity_keys, config_prefix, admin_permission, links and email templates variables.

Step 4: In EmailTemplatesForm.php projectname_email_templates/src/Form/) we will be creating the required form elements.

Step 5: In the custom module file ‘projectname_email_templates.module’ define a hook_mail() to handle the various trigger points

Step 6: To send emails based on the trigger point, we are using plugin.manager.mail service.
 

Step 7: Drupal views do not support displaying custom config entities. So, In order to list all the email templates created, We are using a drupal custom page with a custom HTML table.


We have created a custom page by creating a route in projectname.routing.yml and creating a controller function 'emailTemplateList' in the AdminPagesController.php

Note: If you want to give access to other than Admin users, we need  Add, Edit, delete and view config entity. we need to give the permission -Administer site configuration (admin/people/permissions)

Get in touch with us to know more about how Drupal can help your in achieving your unique business requirements.

How to create Content type specific Publishing Workflow

We have been working on The Employee Experience Centre project which needed different publishing workflows for a content type used by various departments.

By default, Two modules -Workflow and Content Moderation- are available in Drupal Core which give you one workflow per content type.

In our case, We had another situation. Given the large size of the company, there are multiple departments. And the head of each department wanted to change the content publishing workflow. There would be content in a specific state of workflow. And suddenly, there would be a new directive to create a new workflow. But they wanted to keep following the earlier workflow for content which was already in process.

For this scenario, we had no option but to create a custom module.

  • Default workflow module provides us the moderation state. We created specific state & transition based on the client requirement.
  • Client agreed to define multiple workflows along with states. These were mostly fixed which could be utilized by different departments across the company. So, we created each one using custom code.
  • Then we created a page to enable selection of workflow based on content type. On this page, we created a configuration form to list down all content types and departments. 
  • After selecting a department, we listed down all content types with existing workflows.
  • Workflow can be changed for specific content. This permission was given to very specific roles only.

Routing for configuration form

Workflow configuration form

  • Then in hook_node_presave or in hook_node_update,  we can first check for existing workflow type for content type and department from configuration form. Then, we can set the value of moderation state in node.

// queryCheckExistingWorkflowTypeName service will fetch the workflow type by passing department_name and node type.

We managed to create this work around since project team agreed to have predefined workflow. 

This story is not over yet. Actual requirement was to enable even admin users to create these workflows using configuration page. We are out of ideas on this. Would like to hear your suggestions.

How to Set up Android React Native?

React Native is an open-source JavaScript framework created by Facebook for writing real, natively rendering mobile applications for iOS and Android. It’s based on React and uses Facebook’s JavaScript library for building UI.

Web Developers can write mobile applications that look and feel truly ‘native’, all from the JavaScript library. Just code once and React Native apps are available for iOS and Android.

Why React Native is used
The developer has to write one set of code that is JavaScript code to enjoy the performance of the React Native mobile applications and it will work for both of the platforms, such as iOS and Android. We can reuse React Native components for building both Android and iOS apps. React Native is a great platform for those developers who have expertise in JavaScript as there is no need to learn Android specific Java or iOS-specific Swift. React Native is rapid and UI focused, so it helps to load the app quickly and gives a smooth feel. 

Follow these steps to setup React Native in Ubuntu for Android platform:

1.   Install JDK8 or later versions

sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default

2. Download and Install Android Studio into your system.

    Download android studio package using the following link:
      https://developer.android.com/sdk/index.html?source=post_page

 To launch Android Studio, open a terminal, navigate to the android-studio/bin/ directory and execute studio.sh.

launch Android Studio
  2(a. Check if you have a .bash_profile file in your root directory:

         Type ls -a in your terminal and check for the .bash_profile file.

     If you don’t have a .bash_profile in your root directory :

        Type touch .bash_profile

        Open your bash_profile:

        Type nano / .bash_profile

     And add your SDK path:

    if you have a .bash_profile file in your root directory add your SDK path

   Then ctrl + o to write out, hit Enter and then ctrl + x to close the editor.

3. Install Node.js

Sudo apt -get install -y nodejs

4. Install React Native CLI:

npm i -g react-native-cli

5. Create a new React Native project called ‘MyFirstProject’

expo init MyFirstProject
cd MyFirstProject

 6. Start npm server

react-native start

7. Run your project

-  react-native run-android


This is your first screen and your first project in React Native is complete .

react project      

Creating Secure API using Node.js, Express Js and Passport-JWT

Node.js is a server-side platform built on Google Chrome's JavaScript Engine (V8 Engine). It is an open-source, cross-platform runtime environment for executing Javascript code outside of the browser. Node.js is used for developing server-side and networking applications.

  1. Steps for the Installation of Node.js  
    1. For Windows Users 
      1. Go to https://nodejs.org/en/download/
      2. Click on windows-installer.
      3. Now click on “continue” for all the popup screens.
      4. Check the node version by running the command
        node -v
        Check the node version by running the command: node -v
    2. For ubuntu/mac users
      1. The first step is to check node version using the below-mentioned commands

        $ node -v
        Output:
        $ v5.0.0
      2. The next step is to check npm version using the below-mentioned commands

        $ npm -v
        Output: 
        $ 4.0.0
      3. If ‘YES’, then go to the next step; and if ‘NOT’, then Remove node by -
        $ sudo apt-get remove --purge nodejs
      4. Now, Install again using
        $ sudo apt-get install curl
      5. Download node package

        $ curl -sL https://deb.nodesource.com/setup_10.x | sudo bash -
        Note: You can use any version instead of 10.x such as 8.x, 6.x
      6. Lets install NodeJS package
        $ sudo apt-get install -y nodejs
        Check node and npm version using the above commands and make sure it is greater than or equal to the given value.
  2. Create your first simple Node.js project

    1. Create the folder “node-project”

    2. Create file “app.js” in that and add the below code.

    3. Run command “node app.js”
      Run command “node app.js”

    4. It will print “Hello! World” in the command line.

3. Creating Secure API using Node.js, Express Js and Passport-JWT

Express Js: Express js is a web application framework for Node.js. It is a third-party library, used for routing. 

Passport-JWT: This module lets you authenticate API endpoints using a JSON web tokens. It is used to secure RESTful endpoints without sessions.

Npm: It is a ‘Node Package Manager’, basically a command-line tool, as well as a registry for third party library, which can add our node applications.

Steps For Creating Secure Node Api  

 1. Create folder ‘ Node-project ‘ and inside the folder run command

 npm init

it will create the package.json file. This file will contain the details about the project like name, author, version, dependencies and GitHub related items etc.
create the package.json file containing the details about the project like name, author, version, dependencies and GitHub related items etc

 

2. Then, Run the command inside of the root folder.

npm install --save express passport passport-local passport-jwt jsonwebtoken 

Then, check the package.json. It will contain all the above modules.

3. Create file “app.js” and include the installed modules in app.js file using require keyword.

4. Create one more folder called “API” inside the root folder and create a file called user.js and add the following code as shown below:

Creation and Storage of JWT : 

Const token = jwt.sign({ userName: response.userName, userId: response.userId }, "secretekey");
  1. When user logins, first we check wheather user exists in our database or not.
  2. If user exists, then create the token (which will be the combination of the user object and secret key). It is JWT(JSON Web Token).
  3.  It will be stored in the client-side (typically local storage).
  4.  Whenever a user requests to access API, we will pass the token to our middleware function to verify the token is valid or not. If it is valid, only then we will allow accessing our API endpoints.

 

5. Now add the lines to our “app.js”

app.get('/login', user.login);

6. Now create one more folder called middleware, and inside middleware folder create file passport.js. In passport.js add the following code.

Here, I am using the passport-jwt strategy. Once the token is stored in the client-end while accessing our API, we call this function and decrypt the token using the “secret key” and again we check whether user exists in our database or not. If it exists, it will return the user object as a response and then it will call our API endpoint. If the user does not exist, then it will show the error “Unauthorised”.

7.  Then include this file to our app.js . i.e

require('./api/middleware/passport')(passport);

8. Create one function and fetch all user data in user.js. Add the below-mentioned code.

9. Then add our middleware passport-jwt in app.js.

passport.authenticate('jwt', {session: false})

10. While accessing our api /userData,it will call the middleware. If the token is valid, only then, it will allow accessing the getAllUsers function in user.js or else it will show the error as “Unauthorised”

Adding Custom field in search results for Decoupled Drupal Architecture

Nowadays, most of the sites we are working on are built on decoupled Drupal approach. A decoupled website opens up multiple opportunities. Along with new opportunities, we also get our fair share of challenges. One was where I was tasked to create the module, which can take input (string & filetype) from the front end framework and result the dataset along with metadata e.g. image, date, content type and  File Type.

Before we move on with how we implemented this, we need to understand how search function operates in Drupal site. It has three main parts - Source, Index and Results.

Source refers to any kind of content we have on the website. We parse the content and store the metadata in the index. And we display the result in the front-end.

In our case, the front end was built using AngularJS.

First, we had to Identify the schema in which all of our source data was stored. 

The required search page had a basic set of features like title, description, taxonomy, link and some extra metadata like image, date, type and file type. Since we search across multiple sites, we also needed information about the source from where the item comes from.

I created a custom module to create API which can be used for content search like a REST resource using _controller POST method. 

Below is a basic module to explain how we can create Search API to be consumed by the external applications.

We would need to create files as per the below structure.

customapi_search/

├── customapi_search.info.yml

├── customapi_search.routing.yml

└── src

    └── Controller

        └── SearchAPIController.php


Step 1.  Create module.info.yml file to define the metadata of the module.

Step 2. Create search routing file customapi_search.routing.yml

Additionally, create a customapi_search.routing.yml file in which we can define our path (endpoint), controller and methods.

Step 3. Create a SearchAPIController.php Controller file in which we can define custom _controller with [POST] resources.

In our case, we have used the controller method as rest API using POST method, which extends ControllerBase class and EntityQuery used for fetch data precept to the POST method param value.

Endpoint of Custom search api: /api/content-search

Json query parameters like:

{"q": "test", "firstResult": 0, "numberOfResults": 1000, "filters": {"type": ["page","pdf",”docx”]}, "sortBy": "latest"}

The above module will provide endpoint

Endpoint response output:

Changing of Cloned Reference values while Cloning the Entity in Drupal 8

Recently, I came across a unique situation in Employee experience portal project that I was working on.

As in any enterprise, there were multiple departments in the company generating content for specific departments with varying levels of access as well as security.

To increase synergy as well as collaboration between departments, they had decided to allow authors to clone content from different departments. This was also to enable them to reutilize the design layout as well as content created by others.
 

We realized that this is not an option available within the Drupal ecosystem. We do have an  Entity Clone module available. But it was not solving our issue. The challenge was that we needed to clone an entity which was having existing references and these values should be changed in cloned entity based on certain conditions e.g. security groups assigned to a specific department.

These references were paragraphs, widgets as well as other custom entity types. If we clone the node using create duplicate function, it creates a duplicate node. But then, we have to attach all the field definition from the original node manually.

Challenge was in the entity clone process

  • Base field definitions are already available from the original content. Original content is referencing to existing entities.
  • While creating the duplicate, we have an ID (of an entity) only which is not saved yet and we are trying to attach that definition to newly created duplicated content.

Because of this, the content was not being saved with the new modified value.

We found a workaround by reviewing the entity clone module process further.

During the Entity clone process, it saves the duplicate node twice

  • At first, it creates an exact duplicate of the original content and saves it. On saving, ID gets created and then, attach all the reference fields.
  • And it saves the 2nd time with all the references of original content.

We have modified the references of cloned content while saving it the 2nd time. And we have implemented necessary business logic to modify the references.

The following snippet will help in understanding the solution.

 

To perform any alter operation, we have to implement hook_presave

$entity gives you clone entity during entity clone process.

$original_content gives you the values from parent content from where we are initiating the clone of the new content.

Now, you can implement your business logic inside hook_presave to modify the cloned node reference field value.

With the above code, we can change the clone reference values while cloning the entity. I would love to learn from others if there are any other ways to implement the same.

How to create Custom Menu based on Specific Roles and Groups in Drupal

I was working on a project recently where we came across a very unique situation.

The Project required menu to be shown based on roles.These roles were tied with groups created earlier by previous developer team. Each department wanted to have complete access of the Drupal menu to configure (add/ edit/delete) along with drag & drop option within the department. This was to be accomplished without giving them admin access of project.

Menu creation needed to have a workflow where once menu has been added, it should be draft stage and must be reviewed & published by the head of the department to make it live. There was a need for adding additional fields (text & image) along with each menu item. This was to highlight the content of certain pages in menu drop-down itself.Addition & updation of menu was expected to happen in Drupal dialog (popup).

Challenges

  1. By default, there is no option in Drupal to create menu as per role. There is a contributed module available Menu per Role, but this can be configured only for roles whereas our need was to make it work with groups too.
  2. Since this is configuration entity (schema file) and not a content entity, no option was available to add extra fields in menu items
  3. By default, Drupal modal dialog opens the custom form in a pop-up and on submission of the form, you have to mention close dialog command to close the popup and submit the form. But requirement was to create new form (while adding up new menu item) without closing the modal.

Because of the above three scenarios, we created a custom module to enable the following functionalities.

    • Department-wise Menu Creation Configuration
    • Option to publish menu in Draft state

How we enabled role & group specific menu configuration

  1. Enable Roles & Groups

We created a custom page to list all the menu items:

  • Create a routing file

  • Fetch roles of current user

  • Fetch groups based on the role of that current user and give access to user based on specific role & groups

  1. How we added extra fields in menu item\

  • Created custom entity

  • Created a custom table to link custom entity ID with menu ID:

Create a schema file for creating custom table in drupal 8

  • On creation of promo, add drupal insert query to add in custom table
     

3) How to create a new form without closing the modal

I added following custom ajax command to achieve this

  • Add UpdateMenuCommand.php file under module_name/src/Ajax folder

  • Then in js file, add like this:

Drupal.AjaxCommands.prototype.updateMenu key name mentioned in UpdateMenuCommand.php file.

Use the same in js file.

By following this procedure, we were able to create role based menu which worked with groups related permission. This can also be used when you need an extra field in the menu.

Feel Free to Contact Us for Your Enterprises

Sajari Search Custom Implementation with Drupal for Better Performance

Google discontinued its Site Search as a Service from April 1, 2017. For one of our clients who was using Google CSE, the team decided to implement the Sajari search which is a high-performance custom search for enterprises.

There is a contributed module already available to use Sajari on Drupal websites. But we know that each additional contributed module adds overhead to Drupal, impacting the performance.

In our case, the client was very keen to have minimal impact on performance. So, we decided to build a lightweight custom module for Sajari integration ensuring appropriate custom search matches.

Sajari team gave us the javascript code snippet for the functionality. They also provided the unique key for our website. Based on our research and the documentation provided, we completed the implementation in the following steps.
 

  • Created the search box using the html and added the class that was mentioned by sajari
  • Our objective was to display the result in a specific page. For this, we added a routing page url in the javascript.
  • Now the target URL will accept the query parameter and will display the result on the page.
  • Sajari provides the option to display results in categorized tabs. This would enable these tabs. 

Note: When we moved our site from http to https, only data from http sites was being displayed. So, again we re-crawled the sajari search. Kudos to Sajari team, we have not seen any downtime so far. We were able to display the content in https too.

Feel free to Contact Us for your Enterprises

Download the Drupal Guide
Enter your email address to receive the guide.
get in touch