Our beginnings resemble a classic startup story. Our two founders, Zoran Tovarloža and Nikola Gorjanac, began their journey as colleagues forging their path in the IT industry together. At the beginning of 2017, they ventured off and founded Bee IT. Ever since, our company’s goal has been to deliver quality web, software development, and eCommerce services and solutions to customers. Today, Bee IT is a vibrant company that work with our forgein clients from Europe, USA and the Middle East using the latest generation tools and technologies.
VALUES THAT DRIVE US
Transparent communication - Our cooperative environment is based on mutual
respect and open communication where we appreciate free expressions of
Trust and dedication - Our clients count on our team, and our team counts on
its members. We have nurtured an environment based on honesty, trust and
accountability since day one.
We are a team - Each project is an opportunity to learn something new and hone
our craft, and with each new client - we get better at what we do.
Solidarity - Our colleagues are always there to help out. When there’s a
challenge to be solved, we are all there to help find a solution.
New career opportunities as the company evolves in the future
Flexible working hours
Private health insurance
Paid English language classes
Paid education and courses
1 on 1 coaching sessions and internal soft skills training
Regular team-building events and fun activities
Paid sports activities
Working in a modern, pet friendly office
Sonja Tatarin Ragaji
Increasing your Revenue with Abandoned Cart Feature
Email marketing is a way to promote products or services through email. It is used as a top digital media channel, and it is important for customer acquisition and retention. In this blog, we will build a mechanism that will collect data from an abandoned cart along with a visitor's email address, store it into a custom object, so that after a certain time we can use that data to notify our customers through email that they have uncompleted orders. We will achieve this with Salesforce Commerce Cloud, using some built-in functionalities in business manager and writing a custom code to support it. STORING INFORMATION ABOUT ABANDONED CARTS As we don't have any system object to store the data for all incomplete orders, we need to create our own custom object type. Following the path Administration > Site Development > Custom Object Types, we can find all the custom object types that are already created. To create a new one, we need to click New and provide an ID, which needs to be unique. A Key Attribute is also a unique identifier for the object type. From the dropdown menu, select a Storage Scope that determines whether it is assigned to a specific site or the entire organization. In the image below, you can see what we used for our case. After that, we need to go to the Attribute Definitions tab and add fields that will store information about a specific order. That information is the customer's email address, the cart's total price, an indication if the customer is a registered user or a guest, and a JSON object containing the cart's data before the customer decided to abandon it. We will achieve that by clicking on New and then defining the attribute by choosing a unique ID, a preferred Display Name, and an appropriate Value Type, and clicking Apply. In our case, for the customer’s email, the Value Type will be a String type, for totalPrice a Number, registeredCustomer Boolean, and for the JSON object a Text type. You can check out one example in the image below. To make it work, we also need to group the attributes that we created by going to the Attribute Grouping tab and creating a new Attribute Group by choosing an ID that is unique for this type and an arbitrary name. In our case, the ID will be ‘default’ and the name is ‘Default’, and after that, we click Add. Now we need to assign our attributes to the newly created group. Clicking the Edit link, we will be redirected to the Assign Attribute Definition page where we need to click the three-dot button, and now we have a popup that contains all the attributes of this object type. In our case, we will choose our new attributes along with the type ID required to identify the object later in the code. Now, by clicking the Select button, we have assigned the attributes. In addition, we will add a new Site Preferences group so the feature can be configurable. Firstly, we need to go to Administration -> System Object Types and search for SitePreferences. In the Site Preferences, we need to add two Attribute Definitions. AbandonedCartEnabled is a Boolean that tells us if the feature is enabled or not, and abandonedCartEmail is the email address from where we will be sending the objects. After that, we need to go to Attribute Grouping, create a new group called Abandoned Cart and add all three attributes to it. Now, we will need to set the values for the attributes by going to Merchant Tools->Custom Preferences. Find Abandoned Cart and add the values you want to the two fields as shown in the image below. After all these steps are done successfully, we have our custom object type and site preferences created in the business manager, and now we need to do some coding to implement it on our site. After all these steps are done successfully, we have our custom object type and site preferences created in the business manager, and now we need to do some coding to implement it on our site. CREATING AND HANDLING CUSTOM OBJECTS Firstly, we will create a helper with functions for handling the objects that will be used later in the code. The createNewObject function is used to initially create the custom objects and store them in the database. Start with mapping fields of the product that are important for restoring the basket afterwards, followed by creating a unique ID, which is created by merging the basket UUID and Date.now() timestamp. Now, by calling createCustomObject from customObectjMgr and passing the name of the object as the first parameter and the ID as the second, it will create it and store it in the custom object. Now we need to fill the object fields, and to do that, we will wrap it in a Transaction so it can be saved to the DB. Besides that, we will need to store the basket UUID and the abandoned cart ID to the session that will be used to make sure that we already created an object for the session and prevent it from making another one each time we enter the checkout process. For deleteObject we will just need the ID of the custom object, and by calling the remove() function and passing that ID, it will delete the object. Also, we need to delete the previously stored data from the session. UpdateCartInfo will be used when adding, removing and updating lineItems on the basket level. For that one, we will again just need the ID of the custom object to get it with the getCustomObject function, and similar to createNewObject, we will map the product and update the object by wrapping it all into a transaction. Similar to updating the cart, we will create the updateEmail function that will be used if a guest user changes it at the beginning of the checkout process. For this example, the object will be created in two cases, one for guest customers as soon as we know their email addresses, and one for logged customers at the moment of creating the basket. To cover the guest customer scenario, we need to extend the CheckoutServices.js controller from the base cartridge by using the server.extend function with a module.superModule parameter and appending the 'SubmitCustomer' endpoint. After we check if the feature is enabled in Site Preferences, we will check if the custom object is already created by looking into the data from the session and update the email to make sure it is the latest one. Now, if the basket is available, we will use our custom function createNewObject to create our custom object. Now, as we covered guest users, we need to cover the second case, and that is the registered customer. As we know the customer’s email right away, we will create the object as soon as they add a product to the basket. To achieve that, we will need to extend the AddProduct, RemoveProductLineItem and UpdateQuantity endpoint. As the helpers are already created, the logic is pretty straightforward for all endpoints. So, basically again making sure that the feature is enabled in Site Preferences, that the customer logged in, and if we have the current basket already saved in the session, we can decide whether we should call createNewObject or updateCartInfo. We have just one specific case here and that is when removing a product from the cart, we need to check if the basket is empty, in which case we will call the deleteObject function to delete the whole custom object. The email is sent only if the customer has abandoned the cart, so we need to make sure to delete the object if the customer actually places the order. So, we will now append the PlaceOrder endpoint the same way as we did with the last one using another custom-made function. All custom objects that we created can be found by going to site > Custom Objects > Custom Object Editor, finding our object type name from the list, and hitting the find button. It should be noted that on this page, with the right permissions, we can edit, add and remove our object manually, but these functionalities should be used just for testing purposes while implementing the code. One thing we need to keep in mind is that we have limits set for the number of created object types to 300 and a total of 400,000 custom objects, with a warning at 240,000. Now that we have the procedure to save all the necessary data, we can create a job that runs once at a time, fetches the objects one by one, and sends an email with the cart content to every customer for which we have created an object 15 days before the job executed, and after the email is successfully sent, deletes the custom object to make sure we don't exceed the limit we mentioned above. It is also recommended to set a retention on the custom object itself so we prevent sending really old abandoned carts to customers. CREATING A JOB A good practice when making some integrations is to create a new cartridge and name it with a prefix int as I have done in this example. Now, the first thing that needs to be done is to configure a step type by creating a JSON file as shown below. (više)
The Importance of Having a Psychologist in the Organization
Our environment is constantly changing. Since the changes happen so often, in most cases, people's reactions to them are automatic and without conscious perception that a change has even happened. Nevertheless, they surely affect our lives and can be private, social, and business in nature. (više)
Using the Full Potential of Salesforce Commerce Cloud (SFCC) SEO Functionality
In today’s world, it is increasingly important to do search engine optimization on your website because nearly half of customers start their shopping using a search engine. If we want our business to be successful online it is vital to use all available resources that Commerce Cloud offers to optimize your website for search engines. (više)
The Basics of Salesforce Commerce Cloud SEO
Before we start going into basics and best practices of SEO on your Salesforce site, you should also understand URL Request Analyzer. This tool can show you what URL requests are being processed on your storefront so you can see what configuration is being used to open that page. This can help us understand some parts of SEO we are still not familiar with and let us reach our goal faster. Basics of every page: title and description (više)
Internships at Bee IT Hive: What to Expect When you Apply for Internship at Bee IT
Our team is small but carefully selected. Currently, our Bee IT hive has 34 members and, as our CEO and Co-Founder Zoran Tovarloža said in his recent blog post about Bee IT’s New Year’s resolutions, we do not plan to stop growing. (više)
Getting Started with Controllers, Models and Decorators (SFCC)
Controllers were introduced as an update of pipelines and, eventually, they replaced them completely. They are one of the most important parts of the Salesforce Commerce Cloud project because they control the flow of data in our application. On the other hand, models fetch data from a server and provide it as a JSON object that will be used to render a page. In this article, we will show you how you can build on your existing RefArch site (or SFRA) to add new functionality with controllers and models. (više)
Salesforce Commerce Cloud Ocapi and Hooks
In this blog, I will give an overview of what hooks actually are, and how they can help in developing great features. Hooks help you a lot when you are in need of dynamic functionality that will execute only at certain times, and only when it's crucial for your software solution to do so. Hooks listen to certain events in the shop or in the data layer of your storefront. Which events will the hooks listen to is totally up to the development plan and customer needs. (više)
My Journey from Starting at Bee IT to Getting Certified as a Salesforce Commerce Developer
In September 2019, after graduating from the Faculty of technical sciences in Novi Sad I was at the crossroads in my life. I wanted to be independent and get a job as a developer but it was difficult since I only had freelance experience in that field. Due to the lack of experience, willingness to see how a professional workspace operates, and because I wanted to put certain things in practice I decided to apply for an internship at BeeIT. (više)
Zaprati kompaniju i ne propusti nove važne informacije. Dobićeš email obaveštenje kada poslodavac objavi novi oglas za posao, kada neko podeli platu, iskustvo o radu ili sa intervjua.