>> KYLE EINECKER: All right. Welcome. This is Drupal as the head in headless commerce.
And let's see. There we go.
I am Kyle Einecker, also known as ctrlAdel, but not on Twitter.
I am the Drupal lead at a company called Avionos. When I'm not doing Drupal programming things, I like to spend time outdoors doing backpacking and, like, long distance backpacking. I've done a couple of trips, 200 miles or so, a couple of weeks in the wilderness. It's nice to disconnect.
If you haven't heard of Avionos before, we're an agency that does enterprise‑level experience management and commerce. Mostly B2B commerce, but any commerce implementation, as well as ‑‑ [indistinct] ‑‑ really, we just ‑‑ we make on challenging projects, and we try to make a difference for our clients, and drive their business forward, increase the revenues, just help them run their business better. We've been in the Drupal space for a couple of years. We've got a couple of nomination for ‑‑ Acquia words. We have a couple of positions available. We're hiring.
The topic. Drupal as the head. Really, I'm going to start by addressing elephant in the room. And that is there's this tall Belgian dude. You might have recognized him. So he's been talking for a while, as well as Matt who spoke yesterday. They've been talking for a while, both of them, about using Drupal headlessly, and decoupled, that raises the question, if we use headlessly, why would we use it as the head for the commerce system?
And the answer is there's a lot of commerce systems out there. Right? There's Centarre, Commercetools, and stuff like elasticpath, Magento, there's a lot of commerce systems out there.
And not all of them support, you know, headless operation as well as Drupal. Not all as forward‑thinking. Some of them think that you should use what they provide, and use them as your front end. And in that situation, Drupal actually makes a lot of sense as the head.
And honestly, even though we technically in this room are biased towards Drupal, the technology that a business is going to choose will come down to a lot of practical considerations. Right?
For integrations, things like payment gateways, shipping providers ‑‑ [indistinct] ‑‑ PIMs, taxes, marketing automation, these are all things like for mature e‑commerce business, they already have answers to all of these, they have systems in place. If they're doing a new commerce site or if they're replatforming, they're not going to want to replatform their entire business.
So these often that way are technical biases in choosing what commerce system we're going to use. And there's also back end functionality.
Like how their businesses with customer service, invoices, user management, account management and promotions. All these are consideration that a business will take into ‑‑ take into account when they're choosing what commerce system they're going to use, even if they wanted to do a headless system, it has to work for their business or else they won't get what they want .
And that's why Drupal, the first ‑‑ [indistinct] ‑‑ Drupal commerce is not our commerce platform. Because life would be too easy if that's the case.
The use case is a business that's decided to do commerce, and they're not going to use Drupal commerce.
But they want to do it headlessly.
They've chosen one that supports headless use as our next assumption.
And even though they're happy with the commerce functionality, our business is not happy with the CMS compatibilities of their commerce platform. They want to have a rich customer experience. They want to have all the marketing material. They want to have the ability for their content authors to really promote their products and get their customers engaged.
And whatever commerce platform they've chosen, they've decided it's insufficient for the use case. We have the platform chosen. We know what we want. And now the business is looking for a CMS. So why Drupal?
And the answer to that ‑‑ there's plenty of talks and blog posts and reasons for why Drupal as a CMS. Drupal is a fully featured, future CMS. There's not reason not to use it.
But in this situation, I think Drupal is in a unique position, a unique value proposition. Because Drupal has Drupal commerce.
Which is a commerce system with a flexible data model that's really been built ‑‑ has been built in such a way that it can be used as an integration point for another commerce system.
And in the commerce systems I've worked with, the handful of them, I've never seen another commerce system like Drupal commerce. I've never seen one that's really built in such a flexible way that the data model would support being the front end for another commerce system.
And that's really unique. And I think Centarre and Drupal has done a good job of maintaining the data flexibility that allows this case of, we have a commerce platform chosen and now we need to get commerce into our CMS. Just plop Drupal commerce in the middle.
I think that's a very unique value proposition when it comes to Drupal, Drupal as the head in headless commerce. Especially against other CMSs. With that in mind, we're going to say our business has chosen Drupal as the CMS. So those are kind of assumptions for our use case.
And now we're onto our architecture considerations. We have two systems, how are they going to talk to each other? What does the data flow look like? What functionality lives where, that kind of stuff.
So the first real consideration you have to make is authentication.
And I'm not talking about authentication of the user. I'm talking about APL authentication. Does the platform that's chosen recommend using an integration user or does it support customer authentication? This is a really, really big one. If the commerce platform only supports integration user, then your customers cannot interact directly with the commerce API. You have to have something in the middle, otherwise you're exposing them, essentially a superuser for the API to all your customers, and that's not secure.
Whereas if the commerce platform has customer authentication, then a customer can directly use the commerce API and your integration will look significantly different because they can talk directly to the commerce system without having to have the middle layer. That's the first consideration. Authentication for your commerce API.
The next one is disconnected behavior. Another way of looking ‑‑ or saying this is, what parts of the site or how functional should the site be if the two systems aren't connected together? If Drupal cannot talk to the commerce platform, how functional should the Drupal side be? There are a couple. User authentication and checkout. If the customer is the identity provider for user authentication, if they're not connected, the user can't log in.
Drupal as the head doesn't have a say in checkout. So, like, it can't say whether an order ‑‑ or a cart with transition from a cart to an order. You can't do that without the integration in place. But then there's gray areas. Yes, you should still be able to browse a product detail page even if the system isn't connected to Drupal. Should you still be able to search? Yes. The business might have another answer. Should catalog and product listing pages still work? I think they should. I think that a user in this system where Drupal is the head and there's a commerce back end, the user shouldn't know if it's not connected until they try to take an action.
So product detail pages should be available. Search and product listing pages should be available. That's my opinion. Businesses might have different requirements.
And then there's two very gray areas in the carting and pricing.
If you're not connected, should you be able to cart something?
Well, you could say no. You shouldn't be, because what if the commerce system has rules that say you shouldn't be able to cart this together or a user can't purchase this for whatever reason.
And if you have specific or complicated carting logic, the answer is no. A user should not be able to cart thing if they're disconnected. But if you have a fairly simple business model, if you're selling online products, you know they're always going to be in stock. You don't have all that many access checks or all that much logic around adding to cart, sure. Let them cart it, and let Drupal and the commerce system figure it out once they reconnect.
And the same goes for pricing. If you have a simple pricing model that doesn't change that much, if you don't have that many B2B pricing rules for different accounts and users ‑‑ [cough] ‑‑ then import your base price, your list price, and show that, and then let Drupal and the commerce system handle it after they reconnect.
Now, obviously a user is going to hit a point where they can't continue in this process. Even if they can cart and they are seeing a price, if the systems aren't connected, check ‑‑ they can't enter checkout.
But that ‑‑ that's expected.
These two systems, in ideal world, are always connected together. In a worst‑case scenario, there's an unexpected outage on your platform, you want your site to still be usable but not totally functional.
And there's the middle case of, every once in a while, our API drops out. Like, you know, once an hour for a second or something. In that case, you want your site to still with usable. You want your user experience to be impacted, and you still want a use ‑‑ you want the two systems to be able to recover from that, you know, one‑second outage every hour and continue on through checkout without the user being aware of it. So that's really ‑‑ this is ‑‑ even though this is an edge case, it's an edge case that really has to be thought through and planned for.
And this brings me to my first implementation tip. So as we go through these slides I'm going to kind of call out some tips that I've learned through implementing how these systems, and hopefully they save you a lot of pain and time. Because all of these have been learned through blood, sweat, and tears.
So implementation tip #1 is write a health checker and notification checker, or notification for your connection between Drupal and your commerce system.
And for dev and stage, make the notification that you get a banner on every page.
Because you don't want to do a deployment and then have a user ‑‑ have a tester go into dev and say nothing works.
And then find out, once they open 40 ticket, that nothing worked because the two systems weren't connected together. Make sure everybody who's doing testing on dev and stage know the state of the system, and know to report it's not connected if they're expecting it to be connected. And it also goes for production. You don't want to do a full‑page banner display. But at an end point, and be able to monitor it through new relic or some other monitoring service to know when your systems are not connected and if you need to take any action to correct that.
So that is the first implementation tip.
Going to the next architecture consideration. The commerce API itself and the usage and flexibility of it. Is it fully featured for headless use? What are the API usage limits? Does it support querying? Will the business logic fit within existing endpoints? I've never built a commerce site that didn't have custom business logic that had to be Exposed in one way or another to a customer. So just make sure that the customizations you know, you need to write, fit within the end points.
Or the next one, you can write custom end points.
And for this commerce platform, there a PHP SDK or library available? Will you be writing your own API? Good things to know. Are there web hooks or will you be polling for updates? General considerations. Because everything between the two systems will be done through the API. You need to know the limitations and what to architect around before you really start getting into your integration.
And the next consideration is data ownership. This is something that should be established before any code is ever written. Figuring out what system owns what data.
So generally users are owned by the commerce system. It's the identity provider for users, unless the business already has another identity provider in place.
Like some type of ‑‑ I don't know ‑‑ user portal or user, online user access system that does the identity provider for their current e‑commerce solution. Something like that. And then, you know, orders, carts, products, product attributes, all of that data is also owned by commerce. As well as inventory.
You don't want to be modifying or customizing that in Drupal. But things like content and catalog structure, content is definitely owned by Drupal. And what's content versus what's data ‑‑ or what's content versus what's commerce data is also an interesting discussion for product. Because there can be a lot of overlap there.
And sometimes, like, products have metadata, but they lack a rich content data, and it can be added into Drupal to a product. And catalog structure, if it has a catalog, use it. If not, maybe that's something you have to add in Drupal to really get what you want.
And implementation tip #2.
Respect the decisions you make here, and respect them always. Do not make any exceptions.
And I really view this as when you do your integration, you can manipulate data from the commerce system. You can manipulate it to make it fit within Drupal, but never customize it.
And by that, I mean never ‑‑ never significantly change the data that comes through. Right?
If something comes in as red, and really the business wanted to display it as burgundy on the front end, that's a commerce data issue. Even though 30 second to write an if statement in Drupal, don't customize your data.
Always ‑‑ always correct it in the right system, in the system that owns it.
And that brings us to the next step. Make friends with all the teams. Because you have two systems, it's likely that you will have two architects at least, if not more.
And just make sure you're friendly with everybody. You have the communication channels. And you have that working relationship where if something needs to be corrected, you can get it corrected in the place it needs to be corrected, instead of doing a work‑around or doing a customization on Drupal.
Because that's just going to create more technical debt and make the integration more complicated, versus correct it go at the source.
So just be friendly with people, you know. Make sure that if you have a small ask, you can ask them, you know the process, and you have the procedures in place to correct everything.
Next ‑‑ oh. All right. That's the last architecture consideration. Now we will get into the possible architectures, after we've taken all these considerations into place.
The first one is doing a fully headless implementation. This is Drupal, Drupal serves a page. And then say this is a product detail page.
Where you have your header, and on the top right you have your cart.
And then you have some product content, and then you have your ‑‑ this other ‑‑ this bigger green box is your add to cart, your pricing, your variation selection, and your ‑‑ [indistinct] ‑‑ content or whatever with Drupal! So fully headless, and this is fully headless commerce, not fully headless Drupal. And fully headless commerce, Drupal doesn't know anything about the commerce system at all. And really, you're just using JavaScript to render different parts of the commerces ‑‑ commerce platform on a Drupal page.
This is ... this is possible if your commerce platform has a strong headless offering, and if it has customer authentication for the API.
If you have an integration user, you can't do this architecture.
Because it would ‑‑ it requires exposing the commerce API directly to the customer.
So that's fully headless. Obviously we're not going to talk about this because it's not the topic of the session. The next one is partially headless.
So this is similar to last one. But we've decided that the product details we really want those to live in Drupal. We want to be able to search with them through solar. We want to be able to reference the products as products and not content. We want to build a paragraph that has a grid of three products.
So we need to import those products into Drupal, and Drupal will handle displaying those products.
But our cart and our checkout are still going to be headless.
And that ‑‑ that's also going to be driven by commerce platform.
Once again, you need a strong ‑‑ you need a commerce platform with a strong headless offers offering, as well as customer authentication.
And then ...
Really, the cart and the checkout for this ‑‑ for this architecture will be driven by the commerce platform. And the content ‑‑ and products will be viewed as content that's imported from the commerce system into Drupal and displayed by Drupal.
The next possible architecture is what I'm going to call a full commerce integration. In this one you have your commerce platform, and then you have Drupal commerce, Centarre, and you have Drupal that's responsible for displaying all of it.
So in this one you're taking data out of your commerce platform, shoving it into Drupal commerce, and then just using Drupal commerce's functionality and display methods and cart and checkout to allow you ‑‑ the user to, you know, do the e‑commerce, add to cart, product search, all that good stuff! So this one is great, because if your commerce platform does not have a strong API or headless offering or recommended using as integration user instead of customer authentication, then there's a lot more flexibility in your PHP back end to work around API limitations.
Around getting data into Drupal.
And then letting Drupal ‑‑ letting Drupal commerce really handle exposing that data to the user, regardless of the limitations you actually have with your commerce platform API.
And the next one, this is ‑‑ this is more of a thought experiment. But I can see as Drupal commerce expands its commerce API functionality, I could see a really strong argument to be made for taking ‑‑ a commerce platform doesn't necessarily have a great API.
Moving the data into Drupal commerce, and, you know, doing content in Drupal, and then doing a fully headless Drupal site. Right?
So, like, a Drupal site that has ‑‑ a Drupal ‑‑ a headless site using reactor node that is using ‑‑ or leveraging Drupal commerce's APIs, all the data and all the business logic is still being driven by that back end commerce platform that is now two layers deep instead of one layer.
I think this is really interesting use case for the future, and I think it's only going to get better as Drupal commerce gets more API‑friendly. Those are the four architectures for headless commerce and Drupal as the head in headless commerce. We're going with #3, the full commerce integration. It leverages Drupal commerce's unique data model.
It really supports even the most underwhelming commerce platform API. That's what we're going to look at. We've got our architecture. We're going to do a full commerce integration. And now we're looking into integration considerations ‑‑ integration considerations and approaches for individual parts of the site.
Like, how do you build a robust integration for the cart or pricing or products?
And what do you want to do and what do you want to consider there?
The main ‑‑ this comes down to data. How often does data change? Why do you need the data? When do you need the data? And who owns the data?
So the answers to these questions are really going to determine how often you need to fetch the data, how important is it that it's accurate, and what areas you actually need it in. Once you answer all these questions, it will be obvious what integration approach to use to really keep your integration logical and performance and secure.
The first integration approach is import, or one way sync. This is going to be really the slowest and the most ‑‑ it's going to be the slowest and for data that is mostly static. For an import, all the ‑‑ you're bringing data out of the commerce platform, and you're importing it into the Drupal data model.
So you're bringing products in as products. You're bringing product attributes. For accounts ‑‑ I'm not talking about users but business or company accounts.
Really, more of a B2B feature. But this is stuff that's not going to change that often. But it's also stuff that Drupal is going to use all the time.
And it's going to show up a lot, and you're going to be querying for it a lot, and you don't want to take the performance of going out to the commerce platform every time you need the information.
And it's ‑‑ just not that important for it to be fetched on demand, because it's not going to change.
Things like product you aren't going to change randomly. Don't do a call for that every time. Just import it once.
And so implement this, I highly, highly, highly recommend doing a message queue system where either the commerce platform pushes messages to Drupal through an end point, or Drupal pulls the product data or the data out of the commerce platform, and then schedules individual jobs for individual pieces of data, like the individual products.
This is the most scaleable solution in the long‑term, because you're processing each product as an individual job, instead of, you know, writing some custom class that does a query out and imports 500 product at once. That's not very scaleable. You will run into issues eventually.
And they also allow, like, it allows you to have a job fail and to continue processing additional jobs. It's just ‑‑ it's an all‑around flexible system, and I highly advise doing this kind of approach through, like, ultimate‑kron (phonetic) in Drupal, instead of doing a one big method of God‑class to handle it. And I've been experimenting with using Migrate to use this. I would say, use it at your own caution.
Because commerce data is complicated, and there's a lot of relations. And unless you're a migrate wizard, and the team that's going to be maintaining your site are migrate wizards, the migration gets complicated really fast and it's not as straightforward. It's reading PHP data, this ‑‑ [indistinct] ‑‑ coming in, coming out. And that brings us to our next implementation tip.
And this applies to all the integration approaches. This just happens to be our first one that you're looking at.
Don't fail silently. Log everything.
So every time you make an API call, wrap it in a trap cache. In that cache statement have a log error or a log message. If you're failing silently, it means that you don't know what's wrong with your system. Or you don't know what the exceptions are in your data.
Or you don't know what your customers are experiencing or doing.
So never leave a situation where something can fail and throw an exception, and you don't catch it. It's extremely important, especially because these systems are semiorganic. Right?
With a dev, a stage, and a prod, you have three environments. Really, you have six because you have a commerce and a Drupal environment for each ‑‑ for each dev stage and prod, and that means things can be different in all of them, and you need to be able to know what's different when.
So don't fail silently. Log everything. There's a useful trait, I believe it's the logger work channel trait? Where you can use any class and it injects the logger service for you, instead of having to do the whole dependence injection route.
That ‑‑ that's haul I have to say about ‑‑ that's all I have to say about that.
The next one is import and export. Don't do the two‑way sync, two systems manipulating the same data and expecting the other system to know about it. If Drupal is doing something with the cart and your commerce system is doing something with your cart, and you're expecting Drupal to know about what the commerce system is doing with the cart, you end up in a very cyclical ‑‑ you don't know who actually owns the data and why they own it. Even though all the approaches I'm about to talk about are actually two‑way syncs, you never want to get into a situation where they're ...
Where both systems are acting independently of each other. You always want to think about as one system is acting. The next system is interpreting that action, and then the original system is reacting to the response.
Never get into a situation where they're acting independently.
The next approach is lazy load.
So this is useful for data that you want to store in Drupal but you don't need it until you need it. Right?
It's like, you don't need to load every user. You probably do not need to load every user into Drupal. You just need the users that are going to log into your system.
So lazy load them.
The same ‑‑ coupons are another example. Drupal only needs to know about the ones that people are trying to apply and people are trying to use.
So in general, if you can lazy load it, lazy load it. It's convenient.
For this, the general approach is usually a storage override or subscribers. For users, this is, like, if you're using an X and raw authentication method, that's a standard lining for ‑‑ [indistinct] ‑‑ there's an external off module that handle linking or creating new users, registers users, all that good stuff, as well as bringing data over for the user.
So use the external off module if you're using users.
But for other entities, especially commerce entities, you will have to override the entity storage provider to make it lazy load based off the commerce platform data, instead of references the Drupal database.
And that brings us to the next implementation tip. Make sure you can debug on production. Because you have data deploying randomly and not loading all of it at once so you can monitor it, if you have an issue, an environment, make sure you can debug on that environment without doing a deployment. Because there's really nothing worse than sitting on a call with the business owners. "We know this isn't working but I have to do a deployment to figure out why." Make sure you be enable debug on production.
A good example is an API I've worked with recently.
In order ‑‑ when something failed on the API side, the response you got back was, essentially, such and such failed. And then turn on debugging to view more information. Which is great. Except for your own production, and debug's not turned on, because you want your site to be performance.
And their answer to that is, well, send a debug parameter. In your ‑‑ in your API call. And we'll send you everything back.
That's also great. That's useful. Expect all your API calls are hard‑coded in your PHP classes, and you can't change that without doing a deployment.
So what I did is, in that integration there's a debug submodule. When it's turned on, it injects that debug parameter to all the API calls that the integration makes. Even though our users will ‑‑ will notice a performance impact when that's on, it allows me to debug production without doing a deployment and to get all the data I need to correct the issue without having to always take the performance impact and without having to do the deployment out to production. Make sure you know how you can turn on debugging without doing deployments.
All right. The next method. On demand.
So this is for ‑‑ on demand could be called ‑‑ this is really for data that Drupal has no need to know about, or no need to care about.
So for order history, that's pretty obvious. There's no reason to load in all your past orders into the Drupal head.
If you can write a custom block that does an API call out to your commerce platform, and just returns all the orders for that user.
That's a whole bunch of data you don't have to worry about importing into Drupal. Do the query on demand and display in a block and be done with it. I've taken it a step further in. Checkout, the cart, once it transitions to the order, I have the opinion that Drupal should not care about that order ever.
So even on the order confirmation page, all that data is pulled through a query from the commerce platform. Because that way, it's always accurate. It's one less failure point and one less integration point I have to care about.
So even on order confirmation, just pull it all in. And there's things like shipping methods and inventory. Inventory is obvious in that the commerce platform maintains the inventory and that's a dynamic thing. If you have to display inventory status, you want to be fetching that as necessary, and not ‑‑ not storing in Drupal, not letting Drupal determine that something is in stock or not.
But having Drupal reference out to the commerce platform for the total, tell you that.
And shipping methods are actually interesting example in that with a commerce system, there's integrations out to other systems like your shipping providers or your payment providers or taxes.
And the question is, do you maintain separate integrations on the head, which is Drupal, and ‑‑ or do you maintain integrations with Drupal as the head, and in the commerce platform as separate integrations, or are there end points available to tell you that shipping ‑‑ what shipping methods are available for our cart?
And the most recently I worked on, the shipping methods were available through the commerce platform. So I didn't have to maintain like a UPS or a FedEx integration. I just called out to the API to say, what shipping methods are available for this cart, and I got them back. Which is very convenient.
But for payment methods, that doesn't work. For payment methods, you have to maintain two integrations. Because you have to collect the credit card information on the front end and tokenize it, and send that token out to the commerce platforms. Because you can never have that credit card hit your server.
So this is one of those ones where depending on the platform and use, there might be anon demand one or you might have to write a separate integration and keep the two in sync, like for UPS or FedEx. And really, mostly for approach, mostly our custom blocks or event subscribers or just custom plugins within Drupal commerce. For, like, the shipped method one I wrote a custom shipping method plugin that queries out to the commerce platform.
And it gets back the shipping methods, and Drupal commerce treats it as any other shipping method the same as FedEx or UPS and just displays it.
And that brings us to the next implementation tip, which is, if you're loading it lazily or on demand, you should be able to delete it from Drupal. Drupal should not care about that data at all.
And if you delete it, nothing bad should happen. It shouldn't delete thing on the remote system. It shouldn't just fail to load it or need be told that it exists.
Integration should be able to tell, oh, I need to load this now that it's been requested, and it should be able to load it successfully without any prior knowledge that it existed, or without any prior data loading.
Just keep that in mind. Don't get into the trap where you lazily ‑‑ or you do an on demand load of your order history. But when you display the order details, you're reference Drupal product commerce entities. Because that's no longer decoupled. You're now tying your detail to the products in Drupal, and what if, like, you have an order that's three years old, and that product is no longer offered, and there's nothing to reference?
Then you have an issue because you don't have data in Drupal that you need to display that order detail, even though you shouldn't need it if your query is correct. That's just one consideration. Make sure that if you're doing things lazily or on demand you're separating out concerns ask not tying the two together accidently. And last integration ‑‑ second to last integration method is transactional. These are simply API calls where you send data out and you get a response. It's usually true or false or success or failure, or, you know, here's the tags or here's the price. These are simple. Happen all the time. User authentication, password, right or wrong. Checkout.
Usually for checkout, the ... the steps are validization step between cart and checkout to make sure you can enter checkout. And Drupal commerce handle all the checkout steps and collecting all of the information. And then after order review, doing a place transition from the Drupal system out to the remote system.
And then, you know, was that successful or not, and do you need to ‑‑ does the user need to collect more data.
And then, you know, things like taxes. You send the order out, and you get the taxes back, and you add the adjustment to the Drupal commerce order and pricing for products, Drupal commerce has a great concept of resolvers, which are plugins. So they have a price resolver that uses Drupal plugins. If you want to do a prying system, you write a price resolver plugin that makes the API call out as needed. Any time you display a price as calculated, it displays that. Any time you do a calculated price in Drupal commerce it runs through the resolvers. And gets the price in the remote system.
All right. That is transactional.
And then synchronization. This is probably the most conflicted one, the two‑way sync that I said don't do. But it can't be avoided, and it's okay as long as you maintain that act, interpret, react, and not a cyclical act, react, act between both systems. For profile data, the commerce systems owns the data but Drupal at the head is responsible for collecting new information. So you have to import the data from the commerce system to Drupal, and then you have to return that ...
You have to import it to Drupal ‑‑ you have to modify it, and send any updates out to the remote system.
So even though that's ‑‑ you know, import, export, it's a very direct ‑‑ import it, present it, change it, export it. It's not ‑‑ the commerce system changes something, Drupal knows about that change, user updates something, and then you have two changes to worry about. It's not that type of deal.
And the cart's another one. If you're maintaining a Drupal cart, and a remote ‑‑ well, if Drupal ‑‑ if Drupal commerce is maintaining the presentation of the cart, and you have ‑‑ the commerce system is maintaining the state of the cart, then what do you do, add to cart in Drupal, Drupal has to add the cart to your commerce platform to see if it was successful or not, and then act correctly.
And that's keeping two carts in sync.
Address book and payment methods, that's just data that you need to import. And then present during checkout. So the you've can use it. If they update it, you need to send the information out like profile data.
Typically do with subscribes and ‑‑ [indistinct] ‑‑ hooks, and actions like presave, update, delete, that kind of stuff.
And external entities. This one is once again a thought experiment.
I haven't got a chance to implement it, but I think there's a strong use case for standard data, or data that is fairly standardized. And is never needed outside of an odd‑man situation.
So that's for things like address book and payment methods where that data always has to be correct.
It always has to be accurate. It always has to be available.
But Drupal really has no need to know that information, because the only time you display it is on the user profile page or during checkout.
And if Drupal doesn't need to know about it, why write an import process for it if you can override the storage handler and just import it as ‑‑ to Drupal, as an internal entity that's really stored else where?
This is an interesting one, where it's a complex solution that ultimately simplifies the other integrations, because you're not having to worry about import and export and API updates if you're writing directly out to your remote system.
All right. That is all the integration approaches. I'm going to walk through kind of an sample in a product detail page, just to show you how many API calls you can ‑‑ how many integration points you can really have on what seems like a simple interaction.
So let's say that a user is on a PDP page and they decide to log in. They're going from anonymous to authenticated.
The first one is, there's an SSO tool to authenticate user. Simple enough.
Next, you load the profile data or the user data through synchronization, pulling the information out so that's available. But in if this user doesn't exist in Drupal yet, you have to do the lazy load to retrieve the information and then do the profile load. You have a lazy load in there for certain situations.
And then you finally end up on the product detail page. Once you're there, you could ‑‑ you're going to have a transactional call to price on your products on the page because now they're authenticated and you can't use the base price. You have to use their user pricing, if you have it.
You're going to have a synchronization call for the cart state. What if that anonymous user had a cart, and the ‑‑ what if the anonymous user had a cart, and then once they logged in, they already had a cart? How do you reconcile the two? Not only between the two carts but between the two calls still. If they hit "add to cart" you have to send the update out to the remote system to update that cart. If you're deploying inventory on the cart page, around the product detail page, that's going to be an on demand call to see if it's in stock, and if not, what do I do about it, how do I change the display of the page.
And maybe ‑‑ maybe that's because the anonymous user did not have a store selected, and once they logged in, they have a default store. Now you're doing inventory calls on this page.
And then there's probably a product access check too. If you have additional B2B offerings or variations available to certain authentication users.
Are those available now? That's a transactional call.
So even though a user logging in and going to the same page they're already on can seem simple, there's a lot of data that can change once they log in. Like, most of these calls don't need to be made for the anonymous user.
Actually ...
Let's walk through that.
So for anonymous user, the product pricing call doesn't need to be made because you can store the price in Drupal commerce. There's no API call there.
Cart state, you're still maintaining a cart state for the anonymous user if they have a cart. That one would still exist.
Inventory depends what you're doing for the inventory, displaying the inventory for the anonymous user as well. This one probably exists. Product access, you can maintain the product access for an anonymous user in Drupal itself. It's the B2B uses that you want to make sure to capture in an API call.
So really, we've cut out two to three calls, and ‑‑ for an anonymous user, we might just be maintaining the state. And for an authenticated user, we might have to deal with all of these different integration points.
So that's just kind of an example of what all could be going on, on a page. There's certainly more complex examples, like, what's going on with the cart page or the checkout page.
This seemed like a good walk through.
And a reminder, implementation tip #2. Respect data ownership.
Even though it's tempting to customize your data, don't do it. Because each one of these blue clouds represents ‑‑ if you make a data customization, by that I mean you get data from your remote system and you import it, but you change that value doing import or during the API call response, each one of these blue clouds represents a point where you have to maintain that customization or you potentially have to maintain that customization.
Whereas if the data is correct, you don't have to worry about it because you know your getting the data correctly from the remote system.
Keep in mind. Do not customize your data because there's so many integration points that you end up having to duplicate your customization all over the place and it becomes a mess to maintain.
And with that, I am done. Have any questions?
All right. I see there's some chat going.
>> AUDIENCE MEMBER: So contextualize, my question there was actually about ‑‑ about your remote entities.
>> KYLE EINECKER: Yeah. All right. Kris.
Sorry. I'm not seeing the question ...
>> AUDIENCE MEMBER: I think I'm the last one ‑‑
>> KYLE EINECKER: Here we go. All right. Can't you just do this as cached data locally with a web hook for invalidation, and then let it get re‑received from the source? Yeah. If your platform supports web hooks and you have the capability from the remote system out. Does that answer the question?
>> AUDIENCE MEMBER: Yeah. I guess, like, I seen a lot of people try to do remote entities over the years with various levels of success. And so I was just ‑‑ I was just kind of curious what your take on it was. I've also done similar things, where we ‑‑ we don't even have an entity. We just do the API calls and cache ‑‑ the render layer with appropriate tags.
>> KYLE EINECKER: Yeah, I would ‑‑
>> AUDIENCE MEMBER: But you can't do views data or things like that.
>> KYLE EINECKER: I would not want to do that with the current Drupal 8 implementation. That's why you need the entity in the first place, to make it easier to work with in Drupal commerce. Right now, I usually do, like, a cred operation where they import and export. It's annoying to maintain but it's simple than external entities.
All right.
Scrolling up.
Looks like Matt around Benji's question. Networks are not always reliable, and you want to be able to recover from any failure state you run into.
Migrated API. I touched on, Benji's. I'm not sure if you're happy with my answer.
>> AUDIENCE MEMBER: I like getting your honest answer.
>> KYLE EINECKER: I have tried to build a migrate import process, and I found it just wasn't maintainable for larger developers. It wasn't obvious.
All right. If there's no other questions, I will remind you about ... providing feedback ‑‑
>> AUDIENCE MEMBER: I have one more question for you, Kyle. In all of this, what was, like, the biggest challenge? Like, the biggest singular challenge that ‑‑ or that thing that rears its head over and over again?
>> KYLE EINECKER: Um ... caching.
So ‑‑ because to minimize ‑‑ was it caching?
I think ... yeah. It's either caching or we had some problems with the check ‑‑ I had some problems with checkout APIs.
So caching is mostly around just making sure you're validating pretty well for, like, pricing. In a system where you're importing the products and resolving the price and cashing that so you don't have to resolve it every time the page loads, invalidate it correctly. When the platform doesn't have the web hooks it send out validation events, touch make sure that your cache is short enough to catch any changes, and also, any actions that the user takes on the front end that should invalidate caches actually does.
>> AUDIENCE MEMBER: Thanks.
>> KYLE EINECKER: All right. I see Kathryn posted the link to feedback. That would be much appreciated.
And reminder about categorize day tomorrow, 10 a.m. to 4 p.m. Central. There will be a training from 10 a.m. to noon. If you haven't contributed, I highly encourage it. I will be there to help do commerce work for Matt. There's a time, I'm sure it will be a bit different virtually, but we will see how it goes.