{"id":18264,"date":"2025-10-02T14:21:56","date_gmt":"2025-10-02T12:21:56","guid":{"rendered":"https:\/\/collaborator.biz\/?p=18264"},"modified":"2025-10-02T16:37:00","modified_gmt":"2025-10-02T14:37:00","slug":"personalization-articulate-rise-360","status":"publish","type":"post","link":"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/","title":{"rendered":"Personalizing learning in Articulate Rise 360: a practical guide by Oleh Selezen"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_1 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#What_parameters_can_we_obtain\" >What parameters can we obtain?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Step_1_Formatting_variables_in_Articulate_Rise_360\" >Step 1. Formatting variables in Articulate Rise 360<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Step_2_User_photos_instead_of_standard_images\" >Step 2. User photos instead of standard images<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Step_3_Addressing_by_gender\" >Step 3. Addressing by gender<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Working_with_block_identifiers\" >Working with block identifiers<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Step_4_Managing_content_for_different_departments\" >Step 4. Managing content for different departments<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Lets_summarize\" >Let&#8217;s summarize<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Final_step_packaging_and_uploading_the_course_to_the_LMS\" >Final step: packaging and uploading the course to the LMS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/collaborator.biz\/en\/blog\/personalization-articulate-rise-360\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<p>An employee opens the course and sees a message addressed to them, text tailored to their gender, and sometimes even their avatar or photo. Sounds cool, doesn&#8217;t it? For the learner, it seems like a minor detail, but for L&amp;D specialists, it is a tool that significantly increases engagement and learning effectiveness. Personalized courses are better at holding attention and creating a sense of value: <em>\u00abthis course was made just for me\u00bb<\/em>.<\/p>\n<p>In addition, all data is already stored in the LMS. So all you need to do is configure it so that it is automatically uploaded to the course.<\/p>\n<p>Together with Oleh Selezny, we have already shared our experience of using user data in Articulate Storyline. Now let&#8217;s take a look at another tool \u2013 <strong>Articulate Rise 360<\/strong>, which is often chosen for its simplicity, speed, and modern design.<\/p>\n<p>In this article, we will focus on how to combine the convenience of Rise with the personalization capabilities of LMS Collaborator. Oleh Selezen, head of the distance learning department at VIYAR, will share his experience.<\/p>\n<p>Let&#8217;s move from theory to practice: what data from <strong>LMS Collaborator<\/strong> can be used to personalize courses in Rise 360?<\/p>\n<p><!--more--><\/p>\n<blockquote>\n<p style=\"text-align: center;\"><strong><a href=\"https:\/\/www.linkedin.com\/in\/oleh-selezen-284717b6\/\" target=\"_blank\" rel=\"nofollow noopener\">Oleh Selezen<\/a> \u2013 Head of Distance Learning at VIYAR<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18267 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image-9.png\" alt=\"\" width=\"136\" height=\"136\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image-9.png 245w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image-9-150x150.png 150w\" sizes=\"auto, (max-width: 136px) 100vw, 136px\" \/><\/p><\/blockquote>\n<h2><span class=\"ez-toc-section\" id=\"What_parameters_can_we_obtain\"><\/span>What parameters can we obtain?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>All data is transferred from LMS Collaborator to SCORM via the <strong>cmi.core.student_info<\/strong> variable. It can also be used for personalization in Articulate Rise 360.<\/p>\n<p>Unlike Storyline, Rise 360 does not directly work with triggers or conditions. However, the values obtained can be used for personalization: to customize learning scenarios, display the necessary blocks, and tailor appeals.<\/p>\n<p>To implement this, you will need to interact with the code a little. But don&#8217;t worry \u2013 it&#8217;s as simple as possible.\ud83d\ude0a<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18345 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/rise-en.png\" alt=\"\" width=\"780\" height=\"975\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/rise-en.png 1080w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/rise-en-240x300.png 240w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/rise-en-819x1024.png 819w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/rise-en-768x960.png 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>Next, step by step, how it looks in practice.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Step_1_Formatting_variables_in_Articulate_Rise_360\"><\/span>Step 1. Formatting variables in Articulate Rise 360<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>To pull user data, simply specify the variable from LMS Collaborator enclosed in percent signs, for example:<\/p>\n<ul>\n<li>user_id \u2192 <strong>%user_id%<\/strong><\/li>\n<li>user_firstname \u2192 <strong>%user_firstname%<\/strong><\/li>\n<li>user_email \u2192 <strong>%user_email%<\/strong><\/li>\n<\/ul>\n<p>When a user opens a course, the system automatically replaces the values with their actual data.<\/p>\n<blockquote><p><em><strong>Important: they do not work on their own. If you do not add the LMS connection code and configure the publication for SCORM, the course will simply remain %user_firstname%.<\/strong><\/em><\/p><\/blockquote>\n<p><strong>What to do next?<\/strong><\/p>\n<ol>\n<li>Publish the course in Rise 360: Publish \u2192 LMS, select SCORM 1.2 or 2004, and save as ZIP..<\/li>\n<li>Unzip the archive into any folder.<\/li>\n<li>Find and open the <strong>scormcontent<\/strong> folder..<\/li>\n<li>Find the <strong>index.html<\/strong> file and open it in any editor.<\/li>\n<li>Add this code immediately after the <strong>&lt;title&gt;<\/strong> tag:<\/li>\n<\/ol>\n<details>\n<summary><span style=\"color: #ff6600;\"><strong>Code<\/strong><\/span><\/summary>\n<pre><code>\r\n&lt;script defer src=\"https:\/\/cdn.jsdelivr.net\/gh\/asimut\/user-variables\/selezen_v1.js\"&gt;&lt;\/script&gt;\r\n<\/code><\/pre>\n<\/details>\n<p>Now the course will pull up user data.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Step_2_User_photos_instead_of_standard_images\"><\/span>Step 2. User photos instead of standard images<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Another simple way to personalize is <strong>to replace images with photos of specific user<\/strong>s. This works anywhere in the course where there are images.<\/p>\n<p>This provides noticeable personalization \u201cin the face\u201d without changing the block layout and works in any places of the course where there are images.<\/p>\n<p><strong>How to do it:<\/strong><\/p>\n<ol>\n<li>Open the desired block in Articulate Rise 360 and click <strong>Image Alt Text<\/strong>.<\/li>\n<li>Enter <strong>replace_user_img<\/strong> and confirm.<\/li>\n<li>Repeat for other images as needed.<\/li>\n<\/ol>\n<p>When opening the course, the system will automatically insert the user&#8217;s photo from the LMS.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18273 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image3.png\" alt=\"\" width=\"780\" height=\"554\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image3.png 1439w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image3-300x213.png 300w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image3-1024x727.png 1024w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image3-768x545.png 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Step_3_Addressing_by_gender\"><\/span>Step 3. Addressing by gender<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When the LMS transmits information about the user&#8217;s gender (e.g., male or female), we can automatically change words and their endings in the course to match the desired gender.<\/p>\n<p>An example of such a text block in Articulate Rise 360:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18282 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image2.png\" alt=\"\" width=\"776\" height=\"95\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image2.png 1754w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image2-300x37.png 300w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image2-1024x125.png 1024w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image2-768x94.png 768w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image2-1536x187.png 1536w\" sizes=\"auto, (max-width: 776px) 100vw, 776px\" \/><\/p>\n<p>The image shows a standard text block. It is in such blocks that you can configure replacements so that the addressees sound natural: <em>\u00abyou have completed\u00bb<\/em> or <em>\u00abyou have completed\u00bb<\/em>.<\/p>\n<p>To do this, you need to prepare a small script that checks the received value and substitutes the desired option.<\/p>\n<blockquote><p><strong>What to pay attention to:<\/strong><\/p>\n<p><em>By default, all forms of address can be left in the masculine form. The system will then change them to the appropriate form in the blocks where you specify this. It is important not to enable replacement everywhere, otherwise words outside the context of forms of address may be accidentally changed. This will look like an error.<\/em><\/p><\/blockquote>\n<p><strong>How to do it:<\/strong><\/p>\n<p>1. Add code that receives data from LMS.<br \/>\n2. Add a module for correct gender references:<\/p>\n<p>\u2013 Connect the main script with replacement logic (it performs search and replacement).<br \/>\n\u2013 In the configuration, specify the words to be replaced (for example, <strong>completed<\/strong>) and the IDs of the blocks (<strong>targetBlocks<\/strong>) where these replacements are allowed.<\/p>\n<p>As a result, the system will automatically substitute the correct forms of address depending on the user&#8217;s gender.<\/p>\n<details>\n<summary><span style=\"color: #ff6600;\"><strong>Code<\/strong><\/span><\/summary>\n<pre><code>\r\n&lt;script defer src=\"https:\/\/cdn.jsdelivr.net\/gh\/asimut\/user_gender_replacer\/selezen_v1.js\"&gt;&lt;\/script&gt;\r\n\r\n&lt;script&gt;\r\n  \/\/ \u041a\u043e\u043d\u0444\u0456\u0433 (\u0442\u0456\u043b\u044c\u043a\u0438 \u0434\u0430\u043d\u0456, \u043d\u0456\u044f\u043a\u043e\u0457 \u043b\u043e\u0433\u0456\u043a\u0438)\r\n  window.GenderReplacer = {\r\n    debug: false,\r\n    genderReplacements: {\r\n      female: {\r\n        '\u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0432': '\u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430',\r\n        '\u0434\u0456\u0437\u043d\u0430\u0432\u0441\u044f': '\u0434\u0456\u0437\u043d\u0430\u043b\u0430\u0441\u044f',\r\n        '\u043e\u0437\u043d\u0430\u0439\u043e\u043c\u0438\u0432\u0441\u044f': '\u043e\u0437\u043d\u0430\u0439\u043e\u043c\u0438\u043b\u0430\u0441\u044f',\r\n        '\u0437\u0440\u043e\u0437\u0443\u043c\u0456\u0432': '\u0437\u0440\u043e\u0437\u0443\u043c\u0456\u043b\u0430',\r\n        '\u043f\u0440\u043e\u0439\u0448\u043e\u0432': '\u043f\u0440\u043e\u0439\u0448\u043b\u0430',\r\n        '\u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0432': '\u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430',\r\n        '\u0433\u043e\u0442\u043e\u0432\u0438\u0439': '\u0433\u043e\u0442\u043e\u0432\u0430',\r\n        '\u0432\u0438\u0432\u0447\u0438\u0432': '\u0432\u0438\u0432\u0447\u0438\u043b\u0430',\r\n        '\u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0432': '\u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u043b\u0430',\r\n        '\u043e\u043f\u0430\u043d\u0443\u0432\u0430\u0432': '\u043e\u043f\u0430\u043d\u0443\u0432\u0430\u043b\u0430',\r\n        '\u0437\u0430\u0441\u0432\u043e\u0457\u0432': '\u0437\u0430\u0441\u0432\u043e\u0457\u043b\u0430',\r\n        '\u0434\u043e\u0441\u044f\u0433': '\u0434\u043e\u0441\u044f\u0433\u043b\u0430',\r\n        '\u0437\u0434\u043e\u0431\u0443\u0432': '\u0437\u0434\u043e\u0431\u0443\u043b\u0430',\r\n        '\u043e\u0442\u0440\u0438\u043c\u0430\u0432': '\u043e\u0442\u0440\u0438\u043c\u0430\u043b\u0430',\r\n        '\u0432\u0438\u043a\u043e\u043d\u0430\u0432': '\u0432\u0438\u043a\u043e\u043d\u0430\u043b\u0430',\r\n        '\u0441\u043a\u043b\u0430\u0432': '\u0441\u043a\u043b\u0430\u043b\u0430',\r\n        '\u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432': '\u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430'\r\n      }\r\n    },\r\n    targetBlocks: [\r\n      'cmckqk51l001c357b79yaongk' \r\n    ]\r\n  };\r\n&lt;\/script&gt;\r\n<\/code><\/pre>\n<\/details>\n<blockquote><p><em><strong>Important: the lower block is only a configuration (data). The actual substitution is performed by the main script with replacement logic, connected by the line above.<\/strong><\/em><\/p><\/blockquote>\n<h3><span class=\"ez-toc-section\" id=\"Working_with_block_identifiers\"><\/span>Working with block identifiers<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>To let the system know which text block to replace, you specify it in the <strong>targetBlocks<\/strong> list. To do this, each block in Rise has its own <strong>unique ID<\/strong>.<\/p>\n<p>There are two ways to find the ID:<\/p>\n<p><strong>Method 1.<\/strong><br \/>\nThrough DevTools developer tools. If you are confident using the browser console, open the page code and copy the required ID.<\/p>\n<p><strong>Method 2.<\/strong><br \/>\nUsing a plugin. It&#8217;s more convenient and faster, especially if you don&#8217;t want to work with the code directly.<\/p>\n<p>You can also expand the list of words to replace. If you don&#8217;t find what you need among the examples provided, feel free to add your own options to the configuration.<\/p>\n<p>To simplify the search for block identifiers, it is convenient to use a plugin.<\/p>\n<p><strong>How to install the plugin:<\/strong><\/p>\n<ol>\n<li>Open your browser and go to Extensions \u2013 Manage Extensions;<\/li>\n<li>Turn on Developer Mode;<\/li>\n<li>Download the archive with the plugin, unzip it, and add the extension from this folder to your browser;<br \/>\n<a href=\"https:\/\/drive.google.com\/file\/d\/1JV5mbwfpl4ZEwaHLqKqF4ZxBoDrcLH9Q\/view?pli=1\" target=\"_blank\" rel=\"nofollow noopener\"><strong>Link to archive<\/strong><\/a><\/li>\n<li>After that, it will automatically appear on your course editing page.<\/li>\n<\/ol>\n<p>The plugin can be enabled or disabled at any time. With its help, you can quickly find block IDs and add them to the configuration.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18288 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image6.jpg\" alt=\"\" width=\"780\" height=\"875\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image6.jpg 1713w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image6-268x300.jpg 268w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image6-914x1024.jpg 914w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image6-768x861.jpg 768w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image6-1370x1536.jpg 1370w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<p>Once we have learned how to quickly find IDs using the plugin, we can use these identifiers not only for point replacements, but also to control the visibility of entire course fragments. This will allow different departments to display their content within a single course \u2013 without duplicating materials and creating unnecessary copies.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Step_4_Managing_content_for_different_departments\"><\/span>Step 4. Managing content for different departments<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We already have all the variables from the LMS, including user_department. This means that there is no need to search for the department: the system reads it from the user data and opens the necessary course blocks based on this information. To do this, you only need to specify the name of the department that is in the LMS and the list of blocks that it should see. For everyone else, the default branch works.<\/p>\n<details>\n<summary><span style=\"color: #ff6600;\"><strong>Code<\/strong><\/span><\/summary>\n<pre><code>\r\n&lt;script&gt;\r\n  (function () {\r\n    'use strict';\r\n  \r\n    \/\/ \u041a\u043e\u043d\u0444\u0456\u0433\r\n    \/\/ \u0417\u0430\u043f\u043e\u0432\u043d\u0438 mapping \u043f\u0456\u0434 \u0441\u0432\u043e\u0457 \u0434\u0435\u043f\u0430\u0440\u0442\u0430\u043c\u0435\u043d\u0442\u0438 \u0442\u0430 \u0457\u0445\u043d\u0456 data-block-id\r\n    window.DepartmentBlocks = window.DepartmentBlocks || {\r\n      debug: false,\r\n      mapping: {\r\n        '\u043d\u0430\u0437\u0430\u0432\u0430 \u0434\u0435\u043f\u0430\u0440\u0442\u0430\u043c\u0435\u043d\u0442\u0443':    ['\u0422\u0423\u0422 \u0412\u041a\u0410\u0416\u0418\u0422\u0418 \u0406D \u0411\u041b\u041e\u041a\u0423'], \/\/ \u043d\u0430\u0437\u0432\u0430 \u043c\u0430\u0454 \u0431\u0443\u0434\u0438 \u0456\u0437 \u043c\u0435\u043b\u0435\u043d\u044c\u043a\u043e\u0457 \u043b\u0456\u0442\u0435\u0440\u0438\r\n        'default':     ['\u0422\u0423\u0422 \u0412\u041a\u0410\u0416\u0418\u0422\u0418 \u0406D \u0411\u041b\u041e\u041a\u0423'],     \/\/ \u0431\u043b\u043e\u043a \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u0456\u043d\u0448\u0438\u0445\r\n      },\r\n    };\r\n  \r\n    const DB = window.DepartmentBlocks;\r\n  \r\n    const ATTR_CANDIDATES = ['data-block-id','data-blockid','data-block','blockid','data-id','id'];\r\n    const HIDE_CLASS = 'dept-hidden-by-mapping';\r\n    const STYLE_ID = 'dept-visibility-style';\r\n    const OBS_CONFIG = { childList: true, subtree: true, attributes: false, characterData: false };\r\n  \r\n    let allListedIds = new Set();      \/\/ \u0443\u0441\u0456 ID, \u0449\u043e \u0437\u0443\u0441\u0442\u0440\u0456\u0447\u0430\u044e\u0442\u044c\u0441\u044f \u0443 mapping (\u0434\u043b\u044f \u043f\u0435\u0440\u0432\u0438\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f)\r\n    let allowedIds = new Set();        \/\/ ID, \u0434\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0456 \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0434\u0435\u043f\u0430\u0440\u0442\u0430\u043c\u0435\u043d\u0442\u0443\r\n    let currentDept = null;            \/\/ \u043d\u043e\u0440\u043c\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0434\u0435\u043f\u0430\u0440\u0442\u0430\u043c\u0435\u043d\u0442\u0443\r\n    let initialized = false;           \/\/ \u0449\u043e\u0431 \u043d\u0435 \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0443\u0432\u0430\u0442\u0438 \u0434\u0432\u0456\u0447\u0456\r\n    let mainObserver = null;\r\n  \r\n    const log = (...args) =&gt; { if (DB.debug) console.log('[DepartmentBlocks]', ...args); };\r\n    const warn = (...args) =&gt; console.warn('[DepartmentBlocks]', ...args);\r\n  \r\n    function normalize(str) {\r\n      return (str == null) ? '' : String(str).toLowerCase().trim();\r\n    }\r\n  \r\n    function injectStyleOnce(doc = document) {\r\n      if (doc.getElementById(STYLE_ID)) return;\r\n      const style = doc.createElement('style');\r\n      style.id = STYLE_ID;\r\n      style.textContent = `\r\n        .${HIDE_CLASS} { display: none !important; }\r\n      `;\r\n      doc.head.appendChild(style);\r\n    }\r\n  \r\n    function getBlockIdFromElement(el) {\r\n      for (const attr of ATTR_CANDIDATES) {\r\n        if (el.hasAttribute &amp;&amp; el.hasAttribute(attr)) {\r\n          const v = el.getAttribute(attr);\r\n          if (v &amp;&amp; v.trim()) return v.trim();\r\n        }\r\n      }\r\n      return null;\r\n    }\r\n  \r\n    function collectAllListedIds() {\r\n      allListedIds = new Set();\r\n      const map = DB.mapping || {};\r\n      Object.values(map).forEach(arr =&gt; {\r\n        (arr || []).forEach(id =&gt; allListedIds.add(String(id)));\r\n      });\r\n      log('All listed IDs:', Array.from(allListedIds));\r\n    }\r\n  \r\n    function computeAllowedIdsFor(dept) {\r\n      const mappingKey = DB.mapping?.[dept] ? dept : 'default';\r\n      allowedIds = new Set(DB.mapping?.[mappingKey] || []);\r\n      log('Allowed IDs for', dept, '(using mapping key:', mappingKey, '):', Array.from(allowedIds));\r\n    }\r\n  \r\n    function isListed(id) {\r\n      return allListedIds.has(id);\r\n    }\r\n  \r\n    function shouldShow(id) {\r\n      return allowedIds.has(id);\r\n    }\r\n  \r\n    function hideEl(el) {\r\n      if (!el.classList.contains(HIDE_CLASS)) {\r\n        el.classList.add(HIDE_CLASS);\r\n      }\r\n    }\r\n  \r\n    function showEl(el) {\r\n      if (el.classList.contains(HIDE_CLASS)) {\r\n        el.classList.remove(HIDE_CLASS);\r\n      }\r\n    }\r\n  \r\n    function initialHideListedBlocks(root = document) {\r\n      const candidates = root.querySelectorAll('*');\r\n      candidates.forEach(el =&gt; {\r\n        const id = getBlockIdFromElement(el);\r\n        if (id &amp;&amp; isListed(id)) hideEl(el);\r\n      });\r\n    }\r\n  \r\n    function applyDepartmentVisibility(root = document) {\r\n      const candidates = root.querySelectorAll('*');\r\n      candidates.forEach(el =&gt; {\r\n        const id = getBlockIdFromElement(el);\r\n        if (!id) return;\r\n  \r\n        if (!isListed(id)) return;\r\n        if (shouldShow(id)) showEl(el);\r\n        else hideEl(el);\r\n      });\r\n    }\r\n  \r\n    function isUserDataReady() {\r\n      const sources = [\r\n        window.UserVariables?.data,\r\n        window.UserVariables2?.data,\r\n        window.userData\r\n      ];\r\n      return sources.some(d =&gt; d &amp;&amp; typeof d === 'object');\r\n    }\r\n  \r\n    function getUserDepartment() {\r\n      if (DB.overrideDepartment) return normalize(DB.overrideDepartment);\r\n  \r\n      const sources = [\r\n        window.UserVariables?.data,\r\n        window.UserVariables2?.data,\r\n        window.userData\r\n      ];\r\n      for (const d of sources) {\r\n        if (!d || typeof d !== 'object') continue;\r\n        for (const key of ['user_department','department','dept','user_dept','org_unit','division']) {\r\n          if (d[key]) return normalize(d[key]);\r\n        }\r\n      }\r\n      return '';\r\n    }\r\n  \r\n    function processIframe(iframe) {\r\n      try {\r\n        const doc = iframe?.contentDocument;\r\n        if (!doc) return;\r\n        injectStyleOnce(doc);\r\n        initialHideListedBlocks(doc);\r\n        if (currentDept) applyDepartmentVisibility(doc);\r\n        const obs = new MutationObserver(() =&gt; {\r\n          if (!currentDept) initialHideListedBlocks(doc);\r\n          else applyDepartmentVisibility(doc);\r\n        });\r\n        obs.observe(doc.documentElement, OBS_CONFIG);\r\n      } catch (e) {}\r\n    }\r\n  \r\n    function watchIframes() {\r\n      const iframes = document.querySelectorAll('iframe');\r\n      iframes.forEach(ifr =&gt; {\r\n        if (ifr._deptBound) return;\r\n        ifr._deptBound = true;\r\n        if (ifr.contentDocument &amp;&amp; ifr.contentDocument.readyState !== 'loading') {\r\n          processIframe(ifr);\r\n        } else {\r\n          ifr.addEventListener('load', () =&gt; processIframe(ifr), { passive: true });\r\n        }\r\n      });\r\n    }\r\n  \r\n    function applyNow(root = document) {\r\n      injectStyleOnce(document);\r\n      watchIframes();\r\n      if (!currentDept) initialHideListedBlocks(root);\r\n      else applyDepartmentVisibility(root);\r\n    }\r\n  \r\n    function startObserver() {\r\n      if (mainObserver) return;\r\n      mainObserver = new MutationObserver(() =&gt; applyNow(document));\r\n      mainObserver.observe(document.documentElement, OBS_CONFIG);\r\n      ['#app','.rise-player','[data-rise]','.course-container'].forEach(sel =&gt; {\r\n        const c = document.querySelector(sel);\r\n        if (c &amp;&amp; !c._deptObserver) {\r\n          const o = new MutationObserver(() =&gt; applyNow(c));\r\n          o.observe(c, OBS_CONFIG);\r\n          c._deptObserver = o;\r\n        }\r\n      });\r\n    }\r\n  \r\n    function resolveDepartmentAndApply() {\r\n      const dept = getUserDepartment();\r\n      if (!dept) {\r\n        log('user_department \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e (\u043f\u043e\u043a\u0438 \u0449\u043e). \u041f\u0440\u0430\u0446\u044e\u0454\u043c\u043e \u0443 \u0440\u0435\u0436\u0438\u043c\u0456 initial-hide.');\r\n        return;\r\n      }\r\n      if (dept === currentDept) return;\r\n      currentDept = dept;\r\n      computeAllowedIdsFor(currentDept);\r\n      applyNow(document);\r\n    }\r\n  \r\n    function waitForDataThenInit() {\r\n      if (initialized) return;\r\n      initialized = true;\r\n      injectStyleOnce(document);\r\n      collectAllListedIds();\r\n      initialHideListedBlocks(document);\r\n      watchIframes();\r\n      startObserver();\r\n  \r\n      let tries = 0;\r\n      const quick = setInterval(() =&gt; {\r\n        tries++;\r\n        if (isUserDataReady()) {\r\n          resolveDepartmentAndApply();\r\n          if (currentDept) clearInterval(quick);\r\n        }\r\n        if (tries &gt;= 20) clearInterval(quick);\r\n      }, 500);\r\n  \r\n      setInterval(resolveDepartmentAndApply, 2000);\r\n    }\r\n  \r\n    DB.forceApply = () =&gt; applyNow(document);\r\n    DB.setDepartment = (deptName) =&gt; {\r\n      DB.overrideDepartment = deptName;\r\n      resolveDepartmentAndApply();\r\n    };\r\n  \r\n    if (document.readyState === 'loading') {\r\n      document.addEventListener('DOMContentLoaded', () =&gt; setTimeout(waitForDataThenInit, 50), { once: true });\r\n    } else {\r\n      setTimeout(waitForDataThenInit, 50);\r\n    }\r\n  })();\r\n&lt;\/script&gt;\r\n<\/code><\/pre>\n<\/details>\n<p><strong>How it works:<\/strong><\/p>\n<ul>\n<li>At the start, all \u201cmanaged\u201d temporary blocks are hidden.<\/li>\n<li>When the system reads <strong>user_department<\/strong>, it shows only those blocks that you have assigned to this department.<\/li>\n<li>Blocks from other lists remain hidden, and those that are not in the mapping are visible.<\/li>\n<li>If the department is not found or is empty, the user sees <strong>default<\/strong>.<\/li>\n<\/ul>\n<p>As a result, each employee receives only their own content \u2013 without duplicating courses or unnecessary versions.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18291 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image9.png\" alt=\"\" width=\"780\" height=\"696\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image9.png 1920w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image9-300x268.png 300w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image9-1024x914.png 1024w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image9-768x685.png 768w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image9-1536x1370.png 1536w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"Lets_summarize\"><\/span>Let&#8217;s summarize<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Now you have three ready-made tools:<\/p>\n<ul>\n<li><strong>Script \u21161<\/strong> \u2013 gets user data, pulling in the department name or personal photo.<\/li>\n<li><strong>Script \u21162<\/strong> \u2013 changes words and endings in the text depending on the user&#8217;s gender.<\/li>\n<li><strong>Script \u21163<\/strong> \u2013 manages content: hides or shows course blocks for different departments.<\/li>\n<\/ul>\n<p><em><strong>You don&#8217;t have to connect all of them at once \u2013 just use the ones that are really necessary for your course.<\/strong><\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18294 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image4.png\" alt=\"\" width=\"781\" height=\"938\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image4.png 1598w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image4-250x300.png 250w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image4-852x1024.png 852w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image4-768x923.png 768w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image4-1278x1536.png 1278w\" sizes=\"auto, (max-width: 781px) 100vw, 781px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Final_step_packaging_and_uploading_the_course_to_the_LMS\"><\/span>Final step: packaging and uploading the course to the LMS<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Once all the changes have been made, the simplest thing left to do is to package the course correctly.<\/p>\n<p><strong>How to do it:<\/strong><\/p>\n<ol>\n<li>Select all files and folders within the project (but not the top-level folder).<\/li>\n<li>Compress them into a ZIP file using any convenient archiver.<\/li>\n<li>Upload the ZIP file you received to LMS Collaborator.<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-18297 aligncenter\" src=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image5.png\" alt=\"\" width=\"780\" height=\"750\" srcset=\"https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image5.png 1773w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image5-300x288.png 300w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image5-1024x985.png 1024w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image5-768x739.png 768w, https:\/\/collaborator.biz\/wp-content\/uploads\/2025\/10\/image5-1536x1477.png 1536w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In this article, we have covered everything from how to pull data from the LMS and insert real photos to changing gender references and managing course blocks for different departments.<br \/>\nNow the course works \u00about of the box\u00bb and can be converted into multiple versions without duplication or extra work.<\/p>\n<p>What you get:<\/p>\n<ul>\n<li><strong>Personalization<\/strong> \u2013 addressing by name, user photo, relevant texts.<\/li>\n<li><strong>Content control<\/strong> \u2013 display different blocks for different departments.<\/li>\n<li><strong>Time savings<\/strong> \u2013 less manual work, less duplication.<\/li>\n<li><strong>Convenience for the team<\/strong> \u2013 learning becomes understandable, lively, and relevant to the needs of employees.<\/li>\n<\/ul>\n<p>The main idea is simple: less technical manipulation, more personalization, flexibility, and value for everyone.\ud83d\ude0a<\/p>\n<div class=\"try-block\" style=\"width: 100% max-width: 750px;\">\n<div class=\"container-fluid\">\n<div class=\"try-container d-lg-flex align-items-center\">\n<div class=\"try-info\" style=\"width: 100%; padding: 30px;\">\n<div class=\"anons\">At LMS Collaborator, we help make learning more personal and convenient for every employee. The platform allows you to customize courses for different roles, departments, and team needs. If you want to create courses that take into account user characteristics and make learning more effective, try LMS Collaborator.<\/div>\n<div class=\"anons\"><strong><em><a class=\"button white d-flex align-items-center justify-content-center call-request-form\" href=\"#\" data-toggle=\"modal\" data-target=\"#trial\">Try LMS Collaborator<\/a><\/em><\/strong><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Sorry, this entry is only available in UA.\u0421\u043f\u0456\u0432\u0440\u043e\u0431\u0456\u0442\u043d\u0438\u043a \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0454 \u043a\u0443\u0440\u0441 \u0456 \u0431\u0430\u0447\u0438\u0442\u044c \u0437\u0432\u0435\u0440\u043d\u0435\u043d\u043d\u044f \u043d\u0430 \u0441\u0432\u043e\u0454 \u0456\u043c\u2019\u044f, \u0442\u0435\u043a\u0441\u0442 \u0437 \u0443\u0440\u0430\u0445\u0443\u0432\u0430\u043d\u043d\u044f\u043c \u0439\u043e\u0433\u043e \u0433\u0435\u043d\u0434\u0435\u0440\u0443,&#8230;<\/p>\n","protected":false},"author":6,"featured_media":18300,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[282,630,360,51,77],"class_list":["post-18264","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-lmscollaborator","tag-rise360","tag-scorm","tag-elearning","tag-lms"],"_links":{"self":[{"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/posts\/18264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/comments?post=18264"}],"version-history":[{"count":17,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/posts\/18264\/revisions"}],"predecessor-version":[{"id":18348,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/posts\/18264\/revisions\/18348"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/media\/18300"}],"wp:attachment":[{"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/media?parent=18264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/categories?post=18264"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/collaborator.biz\/en\/wp-json\/wp\/v2\/tags?post=18264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}