Understanding Weak Reference In JavaScript

Memory and performance management are important aspects of software development and ones that every software developer should pay attention to. Though useful, weak references are not often used in JavaScript. WeakSet and WeakMap were introduced to JavaScript in the ES6 version.

Weak Reference

To clarify, unlike strong reference, weak reference doesn’t prevent the referenced object from being reclaimed or collected by the garbage collector, even if it is the only reference to the object in memory.

Before getting into strong reference, WeakSet, Set, WeakMap, and Map, let’s illustrate weak reference with the following snippet:

// Create an instance of the WeakMap object.
let human = new WeakMap(): // Create an object, and assign it to a variable called man.
let man = { name: "Joe Doe" }; // Call the set method on human, and pass two arguments (key and value) to it.
human.set(man, "done") console.log(human)

The output of the code above would be the following:

WeakMap {{…} => 'done'} man = null;

The man argument is now set to the WeakMap object. At the point when we reassigned the man variable to null, the only reference to the original object in memory was the weak reference, and it came from the WeakMap that we created earlier. When the JavaScript engine runs a garbage-collection process, the man object will be removed from memory and from the WeakMap that we assigned it to. This is because it is a weak reference, and it doesn’t prevent garbage collection.

It looks like we are making progress. Let’s talk about strong reference, and then we’ll tie everything together.

Strong Reference

A strong reference in JavaScript is a reference that prevents an object from being garbage-collected. It keeps the object in memory.

The following code snippets illustrate the concept of strong reference:

let man = {name: "Joe Doe"}; let human = [man]; man = null;

The result of the code above would be this:

// An array of objects of length 1. [{…}]

The object cannot be accessed via the dog variable anymore due to the strong reference that exists between the human array and object. The object is retained in memory and can be accessed with the following code:


The important point to note here is that a weak reference doesn’t prevent an object from being garbage-collected, whereas a strong reference does prevent an object from being garbage-collected.

Garbage Collection in JavaScript

As in every programming language, memory management is a key factor to consider when writing JavaScript. Unlike C, JavaScript is a high-level programming language that automatically allocates memory when objects are created and that clears memory automatically when the objects are no longer needed. The process of clearing memory when objects are no longer being used is referred to as garbage collection. It is almost impossible to talk about garbage collection in JavaScript without touching on the concept of reachability.


All values that are within a specific scope or that are in use within a scope are said to be “reachable” within that scope and are referred to as “reachable values”. Reachable values are always stored in memory.

Values are considered reachable if they are:

  • values in the root of the program or referenced from the root, such as global variables or the currently executing function, its context, and callback;
  • values accessible from the root by a reference or chain of references (for example, an object in the global variable referencing another object, which also references another object — these are all considered reachable values).

The code snippets below illustrate the concept of reachability:

let languages = {name: “JavaScript”};

Here we have an object with a key-value pair (with the name JavaScript) referencing the global variable languages. If we overwrite the value of languages by assigning null to it…

languages = null;

… then the object will be garbage-collected, and the value JavaScript cannot be accessed again. Here is another example:

let languages = {name: “JavaScript”}; let programmer = languages;

From the code snippets above, we can access the object property from both the languages variable and the programmer variable. However, if we set languages to null

languages = null;

… then the object will still be in memory because it can be accessed via the programmer variable. This is how garbage collection works in a nutshell.

Note: By default, JavaScript uses strong reference for its references. To implement weak reference in JavaScript, you would use WeakMap, WeakSet, or WeakRef.

Comparing Set and WeakSet

A set object is a collection of unique values with a single occurrence. A set, like an array, does not have a key-value pair. We can iterate through a set of arrays with the array methods for… of and .forEach.

Let’s illustrate this with the following snippets:

let setArray = new Set(["Joseph", "Frank", "John", "Davies"]);
for (let names of setArray){ console.log(names)
}// Joseph Frank John Davies

We can use the .forEach iterator as well:

 setArray.forEach((name, nameAgain, setArray) =>{ console.log(names); });

A WeakSet is a collection of unique objects. As the name applies, WeakSets use weak reference. The following are properties of WeakSet():

  • It may only contain objects.
  • Objects within the set can be reachable somewhere else.
  • It cannot be looped through.
  • Like Set(), WeakSet() has the methods add, has, and delete.

The code below illustrates how to use WeakSet() and some of the methods available:

const human = new WeakSet(); let paul = {name: "Paul"};
let mary = {gender: "Mary"}; // Add the human with the name paul to the classroom. const classroom = human.add(paul); console.log(classroom.has(paul)); // true paul = null; // The classroom will be cleaned automatically of the human paul. console.log(classroom.has(paul)); // false

On line 1, we’ve created an instance of WeakSet(). On lines 3 and 4, we created objects and assigned them to their respective variables. On line 7, we added paul to the WeakSet() and assigned it to the classroom variable. On line 11, we made the paul reference null. The code on line 15 returns false because WeakSet() will be automatically cleaned; so, WeakSet() doesn’t prevent garbage collection.

Comparing Map and WeakMap

As we know from the section on garbage collection above, the JavaScript engine keeps a value in memory as long as it is reachable. Let’s illustrate this with some snippets:

let smashing = {name: "magazine"};
// The object can be accessed from the reference. // Overwrite the reference smashing.
smashing = null;
// The object can no longer be accessed.

Properties of a data structure are considered reachable while the data structure is in memory, and they are usually kept in memory. If we store an object in an array, then as long as the array is in memory, the object can still be accessed even if it has no other references.

let smashing = {name: "magazine"}; let arr = [smashing]; // Overwrite the reference.
smashing = null;
console.log(array[0]) // {name: 'magazine'}

We’re still able to access this object even if the reference has been overwritten because the object was saved in the array; hence, it was saved in memory as long the array is still in memory. Therefore, it was not garbage-collected. As we’ve used an array in the example above, we can use map too. While the map still exists, the values stored in it won’t be garbage-collected.

let map = new Map(); let smashing {name: "magazine"}; map.set(smashing, "blog"); // Overwrite the reference.
smashing = null; // To access the object.

Like an object, maps can hold key-value pairs, and we can access the value through the key. But with maps, we must use the .get() method to access the values.

According to Mozilla Developer Network, the Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either key or value.

Unlike a map, WeakMap holds a weak reference; hence, it doesn’t prevent garbage collection from removing values that it references if those values are not strongly referenced elsewhere. Apart from this, WeakMap is the same as map. WeakMaps are not enumerable due to weak references.

With WeakMap, the keys must be objects, and the values may be a number or a string.

The snippets below illustrate how WeakMap works and the methods in it:

// Create a weakMap.
let weakMap = new WeakMap(); let weakMap2 = new WeakMap(); // Create an object.
let ob = {}; // Use the set method.
weakMap.set(ob, "Done"); // You can set the value to be an object or even a function.
weakMap.set(ob, ob) // You can set the value to undefined.
weakMap.set(ob, undefined); // WeakMap can also be the value and the key.
weakMap.set(weakMap2, weakMap) // To get values, use the get method.
weakMap.get(ob) // Done // Use the has method.
weakMap.has(ob) // true weakMap.delete(ob) weakMap.has(ob) // false

One major side effect of using objects as keys in a WeakMap with no other references to it is that they will be automatically removed from memory during garbage collection.

Areas of Application of WeakMap

WeakMap can be used in two areas of web development: caching and additional data storage.


This a web technique that involves saving (i.e. storing) a copy of a given resource and serving it back when requested. The result from a function can be cached so that whenever the function is called, the cached result can be reused.

Let’s see this in action. Create a file, name it cachedResult.js, and write the following in it:

 let cachedResult = new WeakMap(); // A function that stores a result.
function keep(obj){
if(!cachedResult.has(obj){ let result = obj; cachedResult.set(obj, result); }
return cachedResult.get(obj);
} let obj = {name: "Frank"}; let resultSaved = keep(obj) obj = null; // console.log(cachedResult.size); Possible with map, not with WeakMap

If we had used Map() instead of WeakMap() in the code above, and there were multiple invocations on the function keep(), then it would only calculate the result the first time it was called, and it would retrieve it from cachedResult the other times. The side effect is that we’ll need to clean cachedResult whenever the object is not needed. With WeakMap(), the cached result will be automatically removed from memory as soon as the object is garbage-collected. Caching is a great means of improving software performance — it could save the costs of database usage, third-party API calls, and server-to-server requests. With caching, a copy of the result from a request is saved locally.

Additional Data

Another important use of WeakMap() is additional data storage. Imagine we are building an e-commerce platform, and we have a program that counts visitors, and we want to be able to reduce the count when visitors leave. This task would be very demanding with Map, but quite easy to implement with WeakMap():

let visitorCount = new WeakMap();
function countCustomer(customer){ let count = visitorCount.get(customer) || 0; visitorCount.set(customer, count + 1);

Let’s create client code for this:

let person = {name: "Frank"}; // Taking count of person visit.
countCustomer(person) // Person leaves.
person = null;

With Map(), we will have to clean visitorCount whenever a customer leaves; otherwise, it will grow in memory indefinitely, taking up space. But with WeakMap(), we do not need to clean visitorCount; as soon as a person (object) becomes unreachable, it will be garbage-collected automatically.


In this article, we learned about weak reference, strong reference, and the concept of reachability, and we tried to connect them to memory management as best we could. I hope you found this article valuable. Feel free to drop a comment.

Developing An Award-Winning Onboarding Process (Case Study)

The notion of onboarding is all about helping users quickly and easily find value in your offering. Speed and ease of use are equally important because users might lose interest if going through an onboarding takes more time or is more complicated than what they expected. Speed and ease of use are also relative to a person’s point of view: a salesperson can have vastly different expectations for an onboarding than a developer.

A well-constructed onboarding process boosts engagement, improves product adoption, increases conversion rates, and educates users about a product. Optimizing the onboarding experience is a journey. You should have a plan but be agile, utilizing processes and tools to garner feedback from target users in a bid to constantly improve.

In this article, we will walk you through how we developed the onboarding processes for platformOS from the very beginning. You will be able to follow how we carried out user experience research, how our onboarding has changed over time, what assumptions we made, and how we adjusted them. We will talk about all the tools we used as examples, but the same processes can be implemented with a wide variety of other tools. You will get practical examples and a complete overview of how we built our onboarding, with insights into UX research and the specifics of working with different audience segments.

Our audience has always combined technical people with various levels of programming skills, and non-technical people who come to our docs to evaluate if platformOS would be a good fit for their projects like Project Owners, Business Analysts, and Project Managers. Because our main target audience is divided into different segments, you will also get a glimpse of the processes we developed for our documentation, developer education, and developer relations.

Challenge: Onboarding For Different Target Audiences

platformOS is a model-based application development platform aimed at front-end developers and site builders automating infrastructure provisioning and DevOps.

DevOps is a combination of development methodologies, practices, and tools that enable teams to evolve and improve products at a faster pace to better serve their customers and compete more effectively in the market. Under a DevOps model, development and operations teams are merged into a single team where the engineers work across the entire application lifecycle, from development and test to deployment to operations.

Our main target audience is developers, and the foundation for their onboarding, education, and support is our developer portal — but our onboarding has to cater to other target audience segments as well.

Defining Our Target Audience Segments

We defined our target audience during the discovery phase of the Design Thinking process that we used to plan our developer portal. Since then, we have frequently revalidated the results to see if we are on the right track because we want to be sure that we understand the people who will be using our product, and what motivates them. We also know that in the lifecycle of a product this audience can change as a result of product positioning, and how well we can address their needs.

Our target audience currently has four segments:

  • Experienced developers,
  • Junior developers,
  • Agency Owner, Sales/Marketing,
  • PM, Business Analyst.

User Base Shifts

We created the first target audience map when we started planning our developer portal. In the discovery phase, we mapped out four proto-personas that covered the following segments: Experienced Developers, Junior Developers, Site Builders, and Marketplace Owners.

We revalidated these results a year later, and we realized that our audience had shifted a bit.

  • The Experienced Developers and the Junior Developers stayed as the main target audiences. However, we collected new knowledge related to the needs of the junior devs. They needed more detail to be able to understand and start working with the product. This new information helped us specify their user journey.
  • At this point, the Site Builders were the smallest group. We identified we needed to address the needs of the developers group first, creating a strong foundation to support site builders in the platform.
  • The non-technical segment shifted on the way. The Marketplace Owners segment was divided into two separate audiences: the Agency Owners, who have a sales and marketing background, and the Business Analysts, who have an enterprise background in business management or transformation — a new audience who started to show interest in our product.

Along the way, we were able to specify the needs of these audiences in more detail. These details helped with the prioritization of the onboarding tasks and kept our focus on the needs of the audience.

Defining Entry Points For Target Audience Segments

Getting to know the needs of the target audience segments provided guidance for identifying the entry points to the product.

  • The Agency Owners’ key goal is to work on multiple web projects that they host and manage on the platform. They won’t work on the platform themselves, but they would like to know the status and the progress of the platform without worrying about DevOps. They need to see the business perspective, the security, and that they are part of a reliable ecosystem with a helpful community around without diving deep into the technical part of the product.
  • The Business Analysts’ goal is to identify solution providers for their specific business problems. They need to find a long-term solution that fits with their use case, is scalable, and gives them the possibility for easy evaluation that shows the key business values in action.
  • The Junior Developers’ goal is to learn the basics without much hassle, under the guidance of experienced community members. They need clear technical communication on how to set up a dev environment and how to troubleshoot common errors.
  • The Experienced Developers’ goal is to find a solution that is reliable and flexible enough for all their project needs and at the same time provides good performance. They need to be able to evaluate quickly if it’s a good fit, then see how their project could work on the platform. They also need to see that the platform has a future with a solid community behind it.

All segments needed an actionable onboarding where they can interact with the product (and engage with the community) based on their level of technical knowledge.

  • In the non-technical journey, users can go from the 1-click route that takes them through registering on the Partner Portal to creating a demo site and installing the blog module by clicking through a setup wizard.
  • In the semi-technical journey, users can create a sandbox in which they can experiment by cloning a demo site from our GitHub repository, and they also have the option to go through our “Hello, World!” guide.
  • In the technical journey, users can follow a more complex tutorial that walks them through the steps of creating an app on platformOS from setting up their development environment to deploying and testing their finished app. It explains basic concepts, the main building blocks, and the logic behind platformOS, while also giving some recommendations on the workflow.

How We Approached The Challenge: Methods And Tools

We followed various methods to tackle different aspects of the main challenge. We selected a Design process to follow, used many different user research methods to collect insights and feedback from our users, chose a framework for our editorial workflow and technical implementation that could work well for our Agile, iterative process and our target audience, and went with an approach for content production that allowed community members to contribute early on.

Design Thinking

Because of the strategic role our developer portal plays in the adoption and use of our product, we wanted to use a creative design process that solves traditional business problems with an open mindset.

Our goal was to:

  • help our community to be able to use our documentation site for their needs as early as possible;
  • measure user needs and iterate the product based on the feedback;
  • keep the long-term user and business goals in mind and take a step closer with each iteration.

We found the Design Thinking framework a perfect fit because it is a user-centric approach that focuses on problem-solving while fostering innovation.

We followed the stages of the design thinking process:

  • Empathize
    In the beginning, we explored our audience, our documentation needs, and existing and missing content through in-depth interviews and workshops.
  • Define
    Then, we defined personas and our Content Inventory.
  • Ideate
    We shared our ideas for content and features through a Card Sorting exercise.
  • Prototype
    Based on our findings, we created a sitemap and prioritized content needs, and created layouts and wireframes. Content production started based on the results of our discovery phase.
  • Test
    We followed an iterative, Docs as Code approach: at each stage, we work with quick feedback rounds, deploy often, and improve features and content based on feedback from real users.

User Research

In the life of a product, each development stage has a fitting UX research method that we can use, depending on the business plans, time constraints, stage of product/feature, and the current concerns.

In the last three years we used the following methods:

  • Interviews
    We met with users, sales, and support persons to discuss in-depth what the participant experienced about various topics.
  • Remote Usability Testing
    We asked potential or current users of the product to complete a set of tasks during this process, and we observed their behavior to define the usability of the product. We used two types of remote usability testing:
    • Moderated: We conducted the research remotely via screen-sharing software, and the participants joined in from their usual work environment. This approach is advantageous when analyzing complex tasks — where real-time interaction and questioning with participants are essential.
    • Unmoderated: We sent tasks for users to complete in their own time. As moderators are not present, we measured less complex tasks and focused on the overall level of satisfaction they experienced when interfacing with the product.
  • Card Sorting
    A quantitative or qualitative method, where we ask users to organize items into groups and assign categories to each group. This process makes it possible to reflect the users’ mental model on the architecture.
  • Tree tests
    We used tree tests to validate the logic of the used information architecture. We gave users a task to find certain elements in the navigation structure and asked them to talk about where they would go next to accomplish the task.
  • Surveys, Questionnaires
    We used questionnaires and surveys to gather a large amount of information about a topic. This quantitative data can help us have a better understanding of specific topics that we can further research to understand what motivates users.
  • Analytics review
    We used site analytics to gather quantitative data about usage patterns and identify possible flow breaks. Based on the data we either fixed the problem or if needed, we further tested with usability research.

Docs As Code And CI/CD

We engaged our users in an Agile and iterative process right from the beginning discovery phase. This ensured that we were able to test and validate all of our assumptions, and quickly make modifications if needed. As our internal team members and our community participants are distributed, we needed a workflow that made it possible to collaborate on changes, large or small, remotely. Consequently, we needed a robust approach to version control accommodating authors, reviewers, and editors all working on content concurrently. As we wanted to encourage developers to contribute, we needed a framework that they’re familiar with. We also wanted to make our documentation open-source, so that anyone could duplicate and reuse it for their own projects. Based on these requirements, we decided to follow the Docs as Code approach.

Documentation as Code or Docs as Code refers to a philosophy of writing documentation with the same tools as software coding. This means following the same workflows as development teams, including being integrated into the product team. It enables a culture where writers and developers both feel they have ownership of the documentation and work together to aim for the best possible outcome. In our case, we didn’t only have writers and developers working on our onboarding but also UX researchers, account and project managers, and of course, a range of users in varying roles.

Our documentation is in a separate repository on GitHub. We have a central branch, and we work locally in a dedicated branch, then we send pull requests for review to be merged into the main branch. To preview docs, we use our own staging site which is an exact copy of the live documentation site.

Once we accept changes, we take steps to push them live almost immediately. To maintain the integrity of the site during this process, we follow the practice of continuous integration and continuous deployment (CI/CD). We run test scripts automatically and deploy the codebase to staging. If a test fails, an error report is generated. Alternatively, if everything goes well, our CI/CD of choice — GitHub Actions — deploys the codebase to production and sends us a notification. We release updates continuously, at times merging multiple changes in a single day, at other times only once or twice a week.

Editorial Workflow

Docs as Code provides the foundation for our processes, but for the various users to work efficiently together, we needed to define a clear editorial workflow that worked for all participants (internal and external writer, developer, contributor, and so on) and for all stages of the process (writing, reviewing, editing); but that was also simple enough to involve new contributors. Following Docs as Code, each stage of our workflow is in git, including project management (contributors can also add tickets to report issues or requests).

These are the steps of our editorial workflow:

  1. Write new content in Markdown using the templates. You can use any editor that can produce Github Flavored Markdown.
  2. Submit the new topic as a pull request on GitHub.
  3. Review. We have a peer-review system in place for code and docs alike. Topics are reviewed by both technical reviewers (developers) and writers.
  4. Edit as needed. Repeat steps 3-4 until approved.
  5. Merge approved pull request.
  6. Deploy to staging, then to production.

Our editorial workflow ensures that contribution works the same way for everyone, and we support our contributors with guidelines and ready-to-use templates.

Content Production And Contribution

When we started developing our onboarding and documentation, we followed the Content First approach. We planned to develop some initial content that we could work with, but even before that, we decided what types of content we would need and outlined the structure of each content type. These outlines became templates that ensure consistency and encourage contribution.

We were inspired by topic-based authoring and DITA, in the sense that we decided to have three main content types for our documentation, tutorials that describe how to accomplish a task, concepts that provide background information and context, and references like our API Reference. Our onboarding consists of tutorials that link to concepts and references when needed.

DITA, short for Darwin Information Typing Architecture, is an XML standard, an architectural approach, and a topic-based writing methodology where content is authored in topics rather than in larger documents or publications. A DITA topic must make sense in its own right.

Involving our users from the beginning ensured that we could test and validate all of our assumptions, and quickly modify anything if needed. This proved to be a time and cost-efficient approach: although we edit and rewrite our content, and change things on our documentation site all the time, we don’t run the risk of creating large chunks of work that have to be thrown away because they don’t correspond to the needs of our users.

Constant collaboration also builds trust: as our process is completely transparent, our community continuously knows what we’re working on and how our docs evolve, and community members can be sure that their opinions are heard and acted upon.

Involving the community from an early stage means that our users saw lots of stuff that was partially done, missing, or ended up totally rewritten. So, for all of this to work, our users had to be mature enough to give feedback on half-done content, and we had to be level-headed enough to utilize sometimes passionate criticism.

Encouraging Contribution

We wanted to make it very easy to get involved for all segments of our target audience, so we offer several ways to contribute, taking into consideration the time contributors have available, and their skill level. We describe ways for our community members to get involved in our Contributor Guide. For some quick editing, like fixing typos or adding links, contributors can edit the content easily on the GitHub UI. For heavy editing, adding new content, or for developers who prefer to use git, we provide a complete Docs as Code workflow. This approach proved to be extremely valuable for our onboarding. We got direct feedback on where users struggled with a step or had too little or too much information, and we could immediately make adjustments and verify that we have fixed the issue.

To help contributors write larger chunks of text or complete topics, we provide guidelines and templates to start from:

  • Style Guide
    Our style guide contains guidelines for writing technical content (e.g. language, tone, etc.) and each content type in our documentation (e.g. tutorials, concept topics, etc.).

  • Templates
    Our site uses Liquid pages, but to make editing easier for contributors, we write documentation content in Markdown and use a Markdown converter to turn it into Liquid. Our templates include all non-changeable content and placeholders with explanations for the parts that are editable. Placeholders provide information on the recommended format (e.g. title) and any requirements or limitations (e.g. maximum number of characters).

We thank all of our contributors by giving recognition to them on our Contributors page as well as on our GitHub repository’s README page.


Our team and community members are scattered across different time zones. Similarly to how we communicate among team members, we use mostly asynchronous and sometimes real-time communication tools to communicate with our community. We even leverage real-time communication tools, like a video conference, to become somewhat asynchronous. For example, video conferences and webinars are recorded, and community members can discuss them on various channels.

  • pOS Community site
    One of our main communication channels is our community site, where you can ask, answer, upvote, and downvote questions, and get to know other members of the platformOS Community. More features coming soon!
  • Slack support
    One of our main communication channels is dedicated Slack channels, where community members ask questions, share ideas, and get to know our team members and each other. Based on their feedback, community members have confirmed how helpful it is to be able to communicate directly with us and each other: they can share what they’ve learned, plan their module development in sync with our roadmap and each other’s projects, and allocate their resources according to what’s going on in the business and the wider community. This communication seeds the documentation site with the most sought-after topics.
  • Video conference
    We regularly have video conferences over Zoom called Town Halls, where community members and the platformOS team share news, demo features, and modules and have the opportunity to engage in real-time, face-to-face conversation. Our team and community members are distributed over different continents, so we try to accommodate participants in different time zones by rotating the time of this event so that everyone has the chance to participate. We also share the recording of each session.
  • User experience research
    Besides getting constant feedback from the community through the channels described above, we plan regular checkpoints in our process to facilitate testing and course correction. During development, we tie these checkpoints to development phases. At the end of each larger release, we conduct user interviews and compile and share a short survey for community members to fill out. This helps us clarify the roadmap for the next development phase.

We make sure to keep community members informed about what’s happening through different channels:

  • Status reports
    We regularly share status reports on our blog to keep our community updated on what we’ve achieved, what we are working on, and what we are planning for the near future. Our status reports also include calls for contribution and research participation and the results and analysis of UX research. Subscribers can also choose to receive the status reports via email newsletter.
  • Release notes
    We share updates regarding new features, improvements, and fixes in our release notes.
  • Blog
    We regularly share articles about best practices and general news on our blog.

Accessibility And Inclusiveness

We address accessibility right from the design phase, where we use Figma’s Able accessibility plugin. We regularly test for accessibility with various tools and ensure that the site complies with all accessibility requirements.

From a technical writing perspective, we support Accessibility and Usability by providing well-structured, clear, concise, and easy-to-understand copy. All of our documentation topics follow a predefined structure (predefined headings, steps, sections, link collections, and so on) applicable to that topic type (tasks, concepts, references), inspired by the principles of topic-based authoring.

Semantic HTML is important for Accessibility, and we make sure not to style text any other way than through Markdown which is then translated into HTML. This way, screen readers can properly navigate through the content, and it also helps overall consistency when, for example, we want to do a design update.

We also review all content to ensure accessible and inclusive language as specified in our style guide.

How We Developed Our Onboarding: Rounds And Lessons Learned

Developing Our Onboarding Using Continuous Iteration Rounds

At the beginning of the project, we started with a focused effort around discovery to identify the main business goals and user needs. As a result of this research, we were able to articulate the big picture. After we had all the user journeys and a sitemap for the big picture plan, we were able to break it down to identify the first iteration that would become the first working MVP version of the site.

Moving forward, we continue to follow an iterative approach, moving fast with an agile mindset. Steps: gather user feedback, identify areas of improvement and possible new directions, define the solution based on resources, business goals, and user needs, and implement it. This circle repeats indefinitely. So, we have an overarching plan outlined for our documentation that we keep in mind, but we always focus on the next couple of action steps we’d like to take.

We can highlight five distinctive rounds that had a great impact on the development of our developer portal.

  1. For our onboarding process, we started with exploring the requirements following the Design Thinking approach. Through a Card Sorting session, we explored the areas of interest for each target audience and that helped us define the topics that concern them the most. This worked as a persona-based content prioritization for the documentation site.
  2. We wanted to guide our users with actionable items that they can try out on our site as a next step. At this point, we were already aware that our target audience shifted. The interviews and the support feedback helped us understand their needs that pointed in two main directions. We needed an easy journey for non-technicals and another one for technicals who like to understand the logic of the platform. In this stage, we planned, tested, and developed the first version of the 1-click journey and the sandbox.
  3. We already had experienced platform users who we wanted to see in action. Using remote field studies, we discovered how they use the tools, the documentation site, and the partner portal we provide. At the same time, we started to conduct continuous onboarding interviews with partners who joined the platform. The two research directions helped us to realize how users with a varying degrees of experience interpret the platform.
  4. By this point, our content grew a lot on the developer portal, and we wanted to discover if we needed a structural and content reorganization based on the user research.
  5. In this latest round, we wanted to dedicate some time to fine-tuning and adjustments, and to double down on the developer portal’s accessibility and inclusiveness.

Round 1: Identifying The Target Audience Segments, Defining Proto-Personas, Base Discovery

With the Design Thinking workshops, we first focused on understanding our users. Based on the user research results, we defined the proto-personas and created a detailed description of each to show their needs and expectations and help us identify who we were designing for. It provided a good foundation for guiding the ideation process and prioritizing features based on how well they address the needs of one or more personas.

On our documentation site, we are working with a large amount of data that we need to present clearly to all users. To define a Content Inventory:

  • we created a list of our proto-personas’ needs based on the problems they needed to solve with the platform;
  • we created a detailed list of content from our previous documentation site and identified missing, reusable, and non-reusable content for our future site;
  • we analyzed the competitor sites to create a list of inspirations.

We ideated with the workshop participant using a Card Sorting exercise. The task was to map out the Content Inventory elements and define connections between them. The result showed us the connected areas and the proto-persona’s preference through color coding.

Based on the Content Inventory and the results of the Card Sorting sessions, we outlined the Information Architecture by creating a sitemap and the navigation for our future site. This plan included all the needs that were discovered and offered a roadmap to keep track of site improvements, content needs, and project phases.

During the Card Sorting sessions, we explored areas of interest for each user persona and, on the sitemaps, we highlighted these as user journeys. We also validated the importance of these areas to assign higher priorities to the ones that need more attention. This process kept our focus on the most important needs of the personas.

The most important sections for the four segments:

  • Experienced Developers: Quickstart guide, How to guide, API docs;
  • Junior Developers: Quickstart guide, Tutorials, Conceptual documentation;
  • Site Builders: Quickstart guide, Tutorials, FAQ, Forum;
  • Marketplace Owners: About platformOS, Blog.

This concluded our Information Architecture phase. We have discovered and organized all the information we needed to continue to the next phase, where we started creating templates for content types, building the wireframes for each page, producing content, and making Design decisions.

Round 2: Onboarding Strategy And Testing Of The Onboarding Process


Before we jumped into planning an onboarding strategy, we did a revalidation on proto-personas. At that point, we discovered that our audience shifted to Experienced developers, Junior developers, Agency Owner, Sales/Marketing, PM and Business Analyst, and we realized that we needed to cover a broader spectrum of needs than previously identified.

We interviewed 20 platformOS users. We identified how long they have been using the system, how they use the platform, what the key ‘aha’ moments were, what struggles they faced, and how they solved them. Their needs pointed in two main directions: we needed an easy journey for non-technicals and another one for technicals, covering those with less experience as well as those more capable developers who wished to understand the deeper logic and nuances of platformOS.

Our main goals with the new onboarding strategy were:

  • to connect our systems (developer portal — partner portal — platform), so our users can go through their discovery experience in one flow during their first visit;
  • to provide an actionable stepped process that the users can walk through;
  • allow users/personas to quickly identify the most fitting journey.

Usability Test

We conducted remote Usability Test sessions in three rounds to validate the platformOS onboarding process.

The onboarding section connects the Documentation site and the Partner Portal where users can select one of three journeys based on their programming experience. The goal was to learn how users with different levels of technical knowledge reacted to the three journeys. Are they able to quickly identify what is included in each journey? If yes, how do they engage from that time forward? Did they follow the pathway most appropriate for them?

During the Usability study, we asked users to do several short tasks using a prototype of the planned features built with Figma. We used both moderated and unmoderated remote usability testing techniques and conducted extra tests with platformOS team members to verify the represented business, technical, and content goals.

We conducted six moderated remote Usability Tests in two rounds and set up three unmoderated remote Usability Tests. These tests were separated into three rounds, and after each round, we updated the prototype with the test results.

Based on the test results, we decided that instead of showing three options to the users, we show the two quickest options: 1-click install and Build a basic ‘Hello world’ app. This helps them to quickly decide which is the best fit for them, and at the same time they can immediately try out the platformOS basics. Then, if they want to, they can check out our third journey — the Get Started guide that explains how to build a to-do app.

We redesigned the Instance welcome screen to help users identify the next steps. Based on the results, we had to optimize the UI copy to make it comfortable for non-technical users as well.

As the flow connects two sites and shows the product, the main goal was to show that the user is on the right track and still on the selected journey. We achieved it by showing the steps of the journey upfront, using consistent wording, and allowing the user to step back and forth.

Round 3: Remote Field Study And Onboarding Interviews

In this round, the goal was to examine the overall journey of the experienced and prospective pOS users, focusing on both successes and challenges they are facing. We conducted an interview with a remote field study to get a better understanding of how they work and what processes they are using.

We focused on four main topics:

  1. Development with pOS (workflows, preferences on version control, tools),
  2. Community and collaboration (support, discussions),
  3. Developer Portal (overall experience, obstacles, suggestions for improvements),
  4. Partner Portal (usage, dashboard preferences).

Key insights from the user research results:

  • The development with platformOS has a flexible and limitless offering which is a great strength of the system, but it also means that learning the workings of the platform, especially in the very beginning, takes more effort and patience from developers.
    Solution: Templates might provide aid during the learning process.

  • As platformOS is new in the market, there’s not much information on Google or StackOverflow yet. On the positive side, the pOS team always provides great support via Slack and introduces new solutions in Town Hall meetings, status reports, and release notes.
    Solution: To further strengthen the community, a separate Community Site can be an efficient and quick platform for peer-to-peer support by having a search function, and users can follow useful topics.

  • Related to the Developer Portal, we saw that the user easily gets to the documentation and finds the solution for most of their use cases. However, the search results were not precise enough in some cases, and the naming of the tutorials caused uncertainty about where to find items.
    Solution: Run a content reorganization session for the tutorials and fix the search function.

  • We discovered that the Partner Portal was used mostly at the beginning of the projects by experienced devs. Junior developers preferred that they can find helping instructions on the instances page that supported their work on the new instances. Agency Owners/Business Analyst preferred to use the site to see the payments related information and the analytics of the instance use. We saw that they generally had problems handling the permissions related to the instances and identifying the hierarchy between their instances.
    Solution: Partner Portal design update with new information structure of the instances and permissions.

Round 4: Structural And Content Reorganization, User Testing, Implementation

Structural And Content Reorganization

In this round, we renamed the Tutorials section to Developer Guide. This was in line with our plan to extend our tutorials in this section with more concept topics, as requested. We planned to have a comprehensive Get Started section for beginners with the “Hello, World!” tutorial and the Build a To-do List App series, and the Developer Guide for everyone working with platformOS — from users who have just finished the Get Started guides to experienced platformOS developers. This separated and highlighted the onboarding area of the site, and this is when the current structure of our Get Started section came to be: a separate tutorial for when you start your journey with platformOS, that you can use as a first step to go through the more advanced onboarding tutorials.

Card Sorting

At this point, we had 136+ topics in our Tutorials section organized into 27 groups, and we knew that we wanted to add more. Based on user feedback, we could improve the usability of the Tutorials section by organizing the topics better. Our goal was to identify a structure that best fits users’ expectations. We used a Card Sorting exercise to reach our goal.

We have analyzed the inputs, and based on the results, we concluded that seven categories can cover our 27 topics: Data management, Schema, Templates, Modules and Module examples, Partner Portal, Third-Party Systems, and Best Practices. We used the similarity matrix and the category namings to identify which topics are connected and what names users suggested for them.

With this research, we managed to restructure the Tutorials section to become in line with the mental models of the users.

Round 5: Fine-Tuning, Content Production

In the latest round, we added the possibility, on our onboarding, to start from a template. Based on our discovery, the marketplace template is a good option for site builders who would like to have a marketplace up and running fast and don’t want to explore the development in detail.

The pOS marketplace template is a fully functional marketplace built on platformOS with features like user onboarding, ad listings and ads, purchase and checkout process, and online payment. Following the tutorial we added, users can deploy this code within minutes to have a list of working features and start customizing the back- and front-end code.

We also keep fine-tuning our content for clarity, brevity, readability, accessibility, and inclusive language. We have regular accessibility reviews where we pay attention to aspects, such as terminology, technical language, gender-neutral pronouns, and informative link text while avoiding ableist language, metaphors, and colloquialisms. We summarized our experience with fine-tuning accessibility in the article “Code and Content for Accessibility on the platformOS Developer Portal” which includes examples of what we changed and how.

Future Plans

The platformOS Developer Portal was very positively received and even won a few peer-reviewed awards. We are honored and grateful that our efforts have yielded such great recognition. We will keep revalidating and improving our onboarding just like we have been doing since the beginning. We are also working on a developer education program for our soon-to-be-launched community site that includes various learning pathways that will try to accommodate users’ different learning styles and also offer ways for them to get more involved with our developer community.


So, after years of working on our onboarding, what are our key takeaways?

  • Don’t feel pressured to get everything right the first time around. Instead, become comfortable with change and consider each adjustment progress.
  • Get to know your target audience and be ready to revalidate and shift target audience segments based on your findings.
  • Get familiar with different user research methods to know when to use which approach. Carry out extensive user research and, in turn, listen to your users. To support feedback, allow users multiple different channels to give you feedback.
  • Choose a flexible workflow, so that the editorial process does not become an obstacle to continuous change. We love Docs as Code.
  • A product is never ready. Shaping and updating an already done flow is perfectly fine.
  • Iteration and prioritization are your best friends when it comes to delivering large amounts of work.

We hope that this case study helps and encourages you as you build an onboarding experience for your product.

7 Reasons Why Marketing Emails Fail

Underperforming marketing emails are often an indicator of overall program deterioration. Reductions in clicks, conversions, and revenue are typically symptoms of a larger problem.

In this post, I’ll address seven causes of poor email performance and how to fix them.

Email Not Reaching Inbox

All email marketing platforms will report a deliverability rate — the percentage of emails that recipients received. Usually this is 98% or more.

However, what your email provider is not reporting is how many of those delivered emails ended up in the inbox versus a subfolder, such as spam or junk. Unfortunately, no tool detects that percentage.

Encourage inboxing by:

  • Avoiding spam triggers such as using all caps or excessive exclamation points,
  • Keeping domain and IP address reputation high,
  • Staying off blacklists,
  • Maintaining high subscriber engagement.

Not Optimizing for Gmail

According to Litmus; in April 2022 Gmail was the second most popular global email client (behind Apple), accounting for roughly 30% of the market. In 2013, Gmail added tabs in the recipient’s inbox, leading most marketing emails to be filtered to Promotions.

Gmail recently released a few new features to help marketers stand out in the Promotions tab. You can check how your emails will filter for free using the Litmus Gmail tab tool.

Litmus's Gmail tab toolLitmus's Gmail tab tool

Litmus’s free Gmail tab tool will detect where in Gmail an email will end up.

Marketers can now boost their promotional emails in Gmail by highlighting an offer, offer code, adding a promotions preview image, and defining a logo URL that will appear as a custom icon next to the From line.

Screenshot of enhancements in Gmaiil Promotions tabScreenshot of enhancements in Gmaiil Promotions tab

Marketers can now boost promotional emails in Gmail by highlighting an offer, offer code, a preview image, and a logo.

Gmail for Developers offers documentation on how to code emails for these features. In addition, Gmail has several email partners that include promotional annotations in their software, including Litmus, Salesforce, Sailthru, Oracle Bronto, and more.

Gmail also features relevant promotional emails within the primary tab to help add more visibility to your messages.

The Wrong Offer

Offers are tricky. Always test email offers to help determine which works best for your audience. In my experience, performance can vary drastically depending on the product and service.

  • For product sales, usually a gift or a pre-populated cart helps. The latter auto-loads a free item into a recipient’s shopping cart.
  • Free shipping has lost some appeal as most retailers offer it in some capacity.
  • Dollar-off offers tend to perform a bit better than percentage-off.

Make sure to pair the offer with your recipients. For example, a small amount off will not likely appeal to a high-end jewelry buyer.

Outdated Data

Email data can become obsolete quickly. According to Return Path, on average only 56% of subscribers remain on an email list after 12 months! Of those that remain, roughly 47% are “active” — having opened and read at least one email.

While these statistics seem scary, there are several ways to maintain an engaged list.

  • Removing unengaged subscribers.
  • Running email verification on any subscriber that hasn’t been emailed in over 30 days.
  • Encouraging new email subscriptions.
  • Keep email frequency low to new subscribers to prevent immediate opt-outs.

I addressed email database cleaning tips last year.

Too Many Emails

Even the most loyal customers will eventually unsubscribe if you send them too many emails. Frequency in email marketing is a fine art and requires testing and monitoring. A few unsubscribes may seem inconsequential, but too many will impact performance.

Each subscriber has unique tolerance levels. But no one wants to receive multiple emails a day from a single sender. I recently unsubscribed to a few of my favorite brands that sent upwards of 15 emails a week.

Remember that elevated unsubscribed rates will hurt your reputation score, leading to more emails in junk or spam folders.

In my experience, two to three emails per week are optimal for ecommerce retailers. Again, testing is critical.

Mismatched Content

Irrelevant content drives unsubscribes. This means understanding your customers — what they have searched and purchased. Match email content — product recommendations, notifications — to those interests.

Personalization can help keep content relevant. I recently received an email from the Red Cross promoting upcoming blood drives that provided a good, basic example of personalization. The email included blood drive locations near me instead of a generic “find event” button.

Poor Subject, From, Preheader

Always preview the combination of your “Subject” line, “From” line, and preheader, especially on mobile. Keep subject lines short with the preheader as an extension. Do not repeat words.

Zurb offers a free subject-line preview tool.