<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:webfeeds="http://webfeeds.org/rss/1.0">
    <channel>
        <title><![CDATA[Thought Industries]]></title>
        <description><![CDATA[Thought Industries]]></description>
        <link>https://community.thoughtindustries.com</link>
        <generator>Bettermode RSS Generator</generator>
        <lastBuildDate>Tue, 09 Jun 2026 18:16:26 GMT</lastBuildDate>
        <atom:link href="https://community.thoughtindustries.com/rss/feed" rel="self" type="application/rss+xml"/>
        <pubDate>Tue, 09 Jun 2026 18:16:26 GMT</pubDate>
        <copyright><![CDATA[2026 Thought Industries]]></copyright>
        <language><![CDATA[en-US]]></language>
        <ttl>60</ttl>
        <webfeeds:icon></webfeeds:icon>
        <webfeeds:related layout="card" target="browser"/>
        <item>
            <title><![CDATA[Custom icon for smartphone]]></title>
            <description><![CDATA[We are looking to improve the experience for learners that access their panorama based site using a mobile device. We can instruct them how to create a shortcut to provide access on their mobile ...]]></description>
            <link>https://community.thoughtindustries.com/basic-2-column-umfls66p/post/custom-icon-for-smartphone-cRD8JXpz7Ni7GQo</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/basic-2-column-umfls66p/post/custom-icon-for-smartphone-cRD8JXpz7Ni7GQo</guid>
            <category><![CDATA[Users]]></category>
            <dc:creator><![CDATA[Jim Walker]]></dc:creator>
            <pubDate>Mon, 08 Jun 2026 18:21:41 GMT</pubDate>
            <content:encoded><![CDATA[<p>We are looking to improve the experience for learners that access their panorama based site using a mobile device.  We can instruct them how to create a shortcut to provide access on their mobile device, but would like to populate the icon displayed on their smartphone or tablet with a custom icon.  Is there a way that we can do this by adding code in the header?</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Calculate GraphQL Query Points?]]></title>
            <description><![CDATA[What would be the query points for this mutation query?

mutation UpdateInPersonEvent(

$id:UUID!,

$title:String,

$status:String,

$sku:String,

$seatsLimit:Int,

$priceInCents:Int,

$customFields:[...]]></description>
            <link>https://community.thoughtindustries.com/basic-2-column-umfls66p/post/how-to-calculate-graphql-query-points-T6VzLfLFKQleyeT</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/basic-2-column-umfls66p/post/how-to-calculate-graphql-query-points-T6VzLfLFKQleyeT</guid>
            <category><![CDATA[Content]]></category>
            <dc:creator><![CDATA[Geoff Crego]]></dc:creator>
            <pubDate>Thu, 04 Jun 2026 17:04:28 GMT</pubDate>
            <content:encoded><![CDATA[<p>What would be the query points for this mutation query?<br><br>mutation UpdateInPersonEvent(</p><p>  $id:UUID!,</p><p>  $title:String,</p><p>  $status:String,</p><p>  $sku:String,</p><p>  $seatsLimit:Int,</p><p>  $priceInCents:Int,</p><p>  $customFields:[CustomFieldInput!],</p><p>  $courseStartDate:Date,</p><p>  $enrollmentStartDate:Date,</p><p>  $enrollmentEndDate:Date,</p><p>  $meetings:[MeetingFields!]</p><p>){UpdateInPersonEvent(</p><p>  id:$id,</p><p>  title:$title,</p><p>  status:$status,</p><p>  sku:$sku,</p><p>  seatsLimit:$seatsLimit,</p><p>  priceInCents:$priceInCents,</p><p>  customFields:$customFields,</p><p>  courseStartDate:$courseStartDate,</p><p>  enrollmentStartDate:$enrollmentStartDate,</p><p>  enrollmentEndDate:$enrollmentEndDate,</p><p>  meetings:$meetings</p><p>){</p><p>  id,</p><p>  createdAt,</p><p>  updatedAt,</p><p>  slug,</p><p>  status,</p><p>  title,</p><p>  seatsLimit,</p><p>  courseStartDate,</p><p>  courseEndDate,</p><p>  enrollmentStartDate,</p><p>  enrollmentEndDate,</p><p>  sku,</p><p>  meetings{</p><p>    id,</p><p>    title,</p><p>    attendeeInfo,</p><p>    startDate,</p><p>    endDate</p><p>  }</p><p>}}</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New: Release Review May 2026]]></title>
            <description><![CDATA[May brought 10 product updates focused on speed and reliability: SCORM replacement with version control, seamless content completion with no intermediate clicks, sub-license auto-checks, email ...]]></description>
            <link>https://community.thoughtindustries.com/what-s-new-siweac6k/post/what-s-new-release-review-may-2026-oRvL0GTBPaiQF4d</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/what-s-new-siweac6k/post/what-s-new-release-review-may-2026-oRvL0GTBPaiQF4d</guid>
            <dc:creator><![CDATA[Thought Industries]]></dc:creator>
            <pubDate>Wed, 03 Jun 2026 19:19:09 GMT</pubDate>
            <content:encoded><![CDATA[<p>May brought 10 product updates focused on speed and reliability: SCORM replacement with version control, seamless content completion with no intermediate clicks, sub-license auto-checks, email filtering by address, certificate analytics in BI Connector, bulk event import with instructor emails and webinar links, related content widget expansion across all content types, smarter page reuse search, and accessibility improvements for keyboard and screen reader users.</p><p><strong>Watch the 45-minute demo walkthrough:</strong> <a class="text-interactive hover:text-interactive-hovered" rel="noopener noreferrer nofollow" href="https://ti-customer-education.wistia.com/medias/vn80f88l86/manage">View Recording →</a></p><div data-embed-url="https://ti-customer-education.wistia.com/medias/vn80f88l86/manage" data-id="ADLWvKYOl62GRZF3lH09Q" data-type="embed"></div><p><strong>Questions?</strong> Reply below or email <a class="text-interactive hover:text-interactive-hovered" rel="noopener noreferrer nofollow" href="mailto:success@thoughtindustries.com">success@thoughtindustries.com</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New June: Release Review]]></title>
            <description><![CDATA[✨ You’ve got the details; now see them in action. ✨

Join us monthly for our What’s New? Webinar to understand the impact of our product releases and latest innovations. Each session delivers a dynamic,...]]></description>
            <link>https://community.thoughtindustries.com/events-4gc7zrwp/post/what-s-new-may-release-review-EG8tPr1daGK5Qm6</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/events-4gc7zrwp/post/what-s-new-may-release-review-EG8tPr1daGK5Qm6</guid>
            <dc:creator><![CDATA[Thought Industries]]></dc:creator>
            <pubDate>Wed, 03 Jun 2026 17:09:27 GMT</pubDate>
            <content:encoded><![CDATA[<p>✨ <strong>You’ve got the details; now see them in action. ✨</strong></p><p>Join us monthly for our <strong>What’s New? Webinar </strong>to understand the impact of our product releases and latest innovations. Each session delivers a dynamic, visual walk-through of our most impactful enhancements including what’s new and what you should do next.<br><br>We’ll take a tour of the new capabilities and how they work, where they shine, and how to put them to work quickly. This is your shortcut to staying current in the platform, so you can turn TI updates into your business momentum!</p><p>🚀 Join us live on the first Wednesday of each month at 11am EST for an overview of our most impactful releases from the past month.</p><p><strong>Note:</strong> While we won’t be providing live support or troubleshooting during this time, we’re always happy to point you in the right direction or connect you with resources that can help.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New Micro-Course Drop: API Fundamentals]]></title>
            <description><![CDATA[If you've ever wanted to use the Thought Industries API but had no idea where to begin - we built this for you.

API Fundamentals is now live in Academy. It's a short, practical micro course that takes ...]]></description>
            <link>https://community.thoughtindustries.com/basic-3-column-sw0ngprk/post/new-micro-course-drop-api-fundamentals-FEVyptXjJ55XeKc</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/basic-3-column-sw0ngprk/post/new-micro-course-drop-api-fundamentals-FEVyptXjJ55XeKc</guid>
            <dc:creator><![CDATA[Thought Industries]]></dc:creator>
            <pubDate>Mon, 01 Jun 2026 20:50:02 GMT</pubDate>
            <content:encoded><![CDATA[<p>If you've ever wanted to use the Thought Industries API but had no idea where to begin - we built this for you.<br><br><strong>API Fundamentals</strong> is now live in Academy. It's a short, practical micro course that takes you from "what even is an API?" to running your first real API recipe inside TI.<br><br><strong>Here's what's inside:</strong></p><ul><li><p>API Basics &amp; Core Terms</p></li><li><p>Understanding API Requests</p></li><li><p>Why Use APIs (and risks to know before you start)</p></li><li><p><strong>Your First API Recipe:</strong> Export Your Course Data</p></li><li><p><strong>Your Second API Recipe:</strong> Reset &amp; Revoke Course Access</p><p><br><br>By the end, you won't just understand APIs - you'll have actually used them.<br>Open to everyone. No experience required.<br><br>👉 <a class="text-interactive hover:text-interactive-hovered" rel="noopener noreferrer" href="https://academy.thoughtindustries.com/learn/course/api-fundamentals">Check it out here</a></p></li></ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Prerequisite Content showing in the catalogue]]></title>
            <description><![CDATA[Hi

I've done a search & couldn't find the question or answer anyway. We have started using the Prerequisite Content feature on the Enrolment Page when designing the course. However when the course is ...]]></description>
            <link>https://community.thoughtindustries.com/basic-2-column-umfls66p/post/prerequisite-content-showing-in-the-catalogue-DQMDrhAXtZovbsa</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/basic-2-column-umfls66p/post/prerequisite-content-showing-in-the-catalogue-DQMDrhAXtZovbsa</guid>
            <category><![CDATA[Accessibility]]></category>
            <category><![CDATA[Content]]></category>
            <category><![CDATA[Design]]></category>
            <category><![CDATA[Settings]]></category>
            <category><![CDATA[Users]]></category>
            <dc:creator><![CDATA[Natasha Sargent]]></dc:creator>
            <pubDate>Mon, 01 Jun 2026 07:07:35 GMT</pubDate>
            <content:encoded><![CDATA[<p>Hi<br><br>I've done a search &amp; couldn't find the question or answer anyway.   We have started using the <strong>Prerequisite Content </strong>feature on the Enrolment Page when designing the course.  However when the course is released to the catalogue the course say the learner hasn't meant the prerequisite - but doesn't say what the prerequisite is.  What step am I missing for the prerequisites to show in catalogue view.  Thank you<br></p><figure data-align="center" data-size="best-fit" data-id="xuTQ3RU7cPPaEgQqtmjBn" data-version="v2" data-type="image"><img data-id="xuTQ3RU7cPPaEgQqtmjBn" src="https://tribe-s3-production.imgix.net/xuTQ3RU7cPPaEgQqtmjBn?auto=compress,format"></figure>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Authoring at Scale: How IMA Built a Competency Framework That Moves at the Speed of Market Demand]]></title>
            <description><![CDATA[
Learn how the Institute of Management Accountants transformed their learning operations from a highly manual, time-intensive process into a scalable machine that publishes up to 50 courses per day.

In ...]]></description>
            <link>https://community.thoughtindustries.com/on-demand-recordings-worj00j9/post/authoring-at-scale-how-ima-built-a-competency-framework-that-moves-at-7vRYs6czhZalyK9</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/on-demand-recordings-worj00j9/post/authoring-at-scale-how-ima-built-a-competency-framework-that-moves-at-7vRYs6czhZalyK9</guid>
            <dc:creator><![CDATA[Thought Industries]]></dc:creator>
            <pubDate>Thu, 28 May 2026 20:23:44 GMT</pubDate>
            <content:encoded><![CDATA[<p></p><div data-embed-url="https://ti-customer-education.wistia.com/s/1bb9nde07aw3ltw" data-id="sPt0foK147nSWGJkoxWQK" data-type="embed"></div><p><br>Learn how the Institute of Management Accountants transformed their learning operations from a highly manual, time-intensive process into a scalable machine that publishes up to 50 courses per day.</p><p>In this virtual roundtable, Emily Masterson (Strategic Design Lead) and Eric Regnell (Curriculum Innovation Specialist) from IMA share the strategic framework and practical systems that enable their team to respond to market shifts within days—not months.<br><br><strong>Key Takeaways</strong></p><ul><li><p><strong>Start with a Clear Plan</strong>: IMA built a framework that defines what accountants need to know—no more guessing what to teach</p></li><li><p><strong>Build Small, Reuse Often</strong>: Break courses into bite-sized pieces that can be mixed and matched into different learning paths</p></li><li><p><strong>Move Fast</strong>: Launch courses in weeks, not months. Some courses are built in just an afternoon</p></li><li><p><strong>Use the Right Tools</strong>: Stick with tools like Articulate and templates so your team stays consistent and doesn't reinvent the wheel</p></li><li><p><strong>Automate the Repetitive Work</strong>: Use APIs to publish dozens of courses at once instead of uploading them one by one</p></li><li><p><strong>Organize Your Content</strong>: Managing 500+ courses is messy—hear how IMA keeps everything organized and findable</p></li></ul><p><strong>Who Should Watch</strong></p><ul><li><p>Learning leaders managing growing course catalogs</p></li><li><p>Instructional designers wanting to move faster without losing quality</p></li><li><p>Curriculum teams struggling with content organization and reuse</p></li><li><p>Organizations considering micro-credentials or atomic learning architecture</p></li><li><p>Anyone who's asked: "How do we scale course development with a lean team?"</p></li></ul><h3 class="text-lg" data-toc-id="bd5fdd61-72f7-4ff4-83cd-7ff5a0b20aa8" id="bd5fdd61-72f7-4ff4-83cd-7ff5a0b20aa8">What to Expect</h3><p>Real, practical wisdom from IMA's years of platform experience—including what's working brilliantly, lessons learned the hard way, and the ongoing challenges they're solving right now. This isn't a polished case study. It's a working conversation with peers who've done the work.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Auto-Hide Completed Featured Content Widgets on the Dashboard]]></title>
            <description><![CDATA[SUMMARY

Once a learner completes all content in a Featured Content widget on their dashboard, that widget becomes a wall of checkmarks that adds visual clutter without adding value. This play gives you...]]></description>
            <link>https://community.thoughtindustries.com/guides-tutorials-g3mgzv80/post/auto-hide-completed-featured-content-widgets-on-the-dashboard-TUcHmGBoMg68ME6</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/guides-tutorials-g3mgzv80/post/auto-hide-completed-featured-content-widgets-on-the-dashboard-TUcHmGBoMg68ME6</guid>
            <dc:creator><![CDATA[Thought Industries]]></dc:creator>
            <pubDate>Wed, 27 May 2026 21:42:20 GMT</pubDate>
            <content:encoded><![CDATA[<h2 class="text-xl" data-toc-id="372a9e29-668f-4a32-816d-056ca6e79ad3" id="372a9e29-668f-4a32-816d-056ca6e79ad3"><strong>Summary</strong></h2><p>Once a learner completes all content in a Featured Content widget on their dashboard, that widget becomes a wall of checkmarks that adds visual clutter without adding value. This play gives you a lightweight script that automatically hides any Featured Content widget where all items are completed — keeping the dashboard clean and focused on what still needs the learner's attention. Content remains assigned and tracked in reporting; it's simply hidden from the dashboard view.</p><h2 class="text-xl" data-toc-id="348ded2f-bb3d-4893-b404-197edf7ab7d9" id="348ded2f-bb3d-4893-b404-197edf7ab7d9"><strong>Requirement Overview</strong></h2><p>If any of these requirements fit your end goal, this may be the play for you.</p><ul><li><p><strong>Requirement 1:</strong> You use Featured Content widgets on the learner dashboard to highlight specific content (e.g., onboarding courses, recommended training, promoted content).</p></li></ul><p><strong>Requirement 2:</strong> You want those widgets to disappear automatically once the learner has completed everything in them, so the dashboard stays focused on active or upcoming work.<br><br><strong>Functional Areas to be Used</strong></p><ul><li><p>Custom Scripts (Site → Site Builder → Pages → Dashboard → Custom Scripts)</p></li><li><p>Dashboard Layout</p></li><li><p>Featured Content Widgets (Tiles, Carousel, or Standard)<br><br></p><figure data-align="center" data-size="best-fit" data-id="Kke44PxTniE29Co8nWJxa" data-version="v2" data-type="image"><img data-id="Kke44PxTniE29Co8nWJxa" src="https://tribe-s3-production.imgix.net/Kke44PxTniE29Co8nWJxa?auto=compress,format"></figure><p></p></li></ul><hr><p></p><h2 class="text-xl" data-toc-id="629f520e-f745-43ae-8c86-e4e4a4fd304f" id="629f520e-f745-43ae-8c86-e4e4a4fd304f"><strong>Core Functionality Configurations</strong></h2><h3 class="text-lg" data-toc-id="6025490b-862f-4acf-a785-a2c2622a9eb3" id="6025490b-862f-4acf-a785-a2c2622a9eb3"><strong>How the Script Works</strong></h3><p><strong>Description:</strong> The script runs on the learner dashboard after the page loads. It looks at every Featured Content widget on the page, counts the total number of content items in each widget, and compares that to the number of completed items. If every item in a widget is completed, the widget is hidden. This is a visual-only hide — the content remains assigned to the learner, remains visible in the Learner Access Widget, and continues to appear in reporting.<br><br><strong>What the script is actually doing:</strong></p><ol><li><p>Wait 1.5 seconds after page load to allow all widgets to render.</p></li><li><p>Find all elements with the class .widget--featured-content (this is the class TI uses for Featured Content widgets).</p></li><li><p>For each widget, count the total content items (.catalog-grid-item) and the completed items (.catalog-grid-item__completed).</p></li><li><p>If total equals completed and total is greater than zero, hide the widget.<br><br></p><hr><p><br><strong>What to Customize for Your Instance</strong></p></li><li><p><strong>The delay before running (1500ms).</strong> If your dashboard loads slowly and widgets haven't fully rendered by the time the script runs, increase this value. If your dashboard loads quickly, you can decrease it for a snappier experience:<br></p></li></ol><hr><pre><code>}, 1500);</code></pre><p><strong>The widget selector.</strong> The script targets .widget--featured-content, which covers Featured Content Tiles, Featured Content Carousel, and standard Featured Content widgets. If you want to apply this logic to a different widget type, change the selector:</p><pre><code>var widgets = document.querySelectorAll('.widget--featured-content');</code></pre><p><strong>The completion indicator.</strong> The script checks for the class .catalog-grid-item__completed to identify completed items. If TI changes this class name in a future update, you'll need to update this selector:</p><pre><code>var completed = widget.querySelectorAll('.catalog-grid-item__completed').length;</code></pre><p><strong>The content item selector.</strong> The script uses .catalog-grid-item to count all content items in a widget. Same consideration as above — if TI changes this class, update accordingly:</p><pre><code>var total = widget.querySelectorAll('.catalog-grid-item').length;</code></pre><p></p><hr><h2 class="text-xl" data-toc-id="8b4bf70b-e10f-458f-9992-51ad5f2eb81f" id="8b4bf70b-e10f-458f-9992-51ad5f2eb81f"><strong>The Script</strong></h2><p>Install the entire script below with your customizations into the <strong>Custom Scripts</strong> area of your Dashboard layout (Site → Site Builder → Pages → Dashboard).<br><br><strong>Installation</strong></p><h3 class="text-lg" data-toc-id="5040a5b1-374a-41cb-9a60-d40b8acd1989" id="5040a5b1-374a-41cb-9a60-d40b8acd1989"><strong>Configuration</strong></h3><ol><li><p>Navigate to <strong>Site → Site Builder → Pages</strong>.</p></li><li><p>Open the <strong>Dashboard</strong> layout.</p></li><li><p>Locate the <strong>Custom Scripts</strong> area.</p></li><li><p>Paste the entire script below (including the &lt;script&gt; tags) into the Custom Scripts field.</p></li><li><p>Save the layout.</p></li><li><p>Test by logging in as a learner who has completed all content in at least one Featured Content widget.</p></li></ol><pre><code>&lt;script&gt;
(function () {

  // ──────────────────────────────────────────────
  // AUTO-HIDE COMPLETED FEATURED CONTENT WIDGETS
  // Hides any Featured Content widget where all
  // content items have been completed by the learner.
  // Visual only — does not affect enrollment,
  // reporting, or the Learner Access Widget.
  // ──────────────────────────────────────────────

  // Only run on the dashboard
  if (window.location.pathname !== '/learn/dashboard') return;

  function hideCompletedWidgets() {
    var widgets = document.querySelectorAll('.widget--featured-content');
    widgets.forEach(function (widget) {
      var total = widget.querySelectorAll('.catalog-grid-item').length;
      var completed = widget.querySelectorAll('.catalog-grid-item__completed').length;
      if (total &gt; 0 &amp;&amp; completed === total) {
        widget.style.display = 'none';
      }
    });
  }

  // Wait for widgets to render before checking
  setTimeout(hideCompletedWidgets, 1500);

  // ──────────────────────────────────────────────
  // SPA NAVIGATION — re-run when learner returns
  // to the dashboard via in-app navigation
  // ──────────────────────────────────────────────

  function checkIfDashboard() {
    if (window.location.pathname === '/learn/dashboard') {
      setTimeout(hideCompletedWidgets, 1500);
    }
  }

  window.addEventListener('popstate', checkIfDashboard);

  var originalPushState = history.pushState;
  history.pushState = function () {
    originalPushState.apply(this, arguments);
    setTimeout(checkIfDashboard, 100);
  };

  var originalReplaceState = history.replaceState;
  history.replaceState = function () {
    originalReplaceState.apply(this, arguments);
    setTimeout(checkIfDashboard, 100);
  };

})();
&lt;/script&gt;</code></pre><h3 class="text-lg" data-toc-id="20dddb9f-99b1-48f9-921f-6544ec510997" id="20dddb9f-99b1-48f9-921f-6544ec510997"><strong>Testing Checklist</strong></h3><ul><li><p>A Featured Content widget where all items are completed is hidden on the dashboard.</p></li><li><p>A Featured Content widget where some but not all items are completed remains visible.</p></li><li><p>A Featured Content widget with no completed items remains visible.</p></li><li><p>An empty Featured Content widget (zero items) remains visible (the script only hides when total &gt; 0 and total equals completed).</p></li><li><p>The Learner Access Widget still shows all assigned content, including completed items — this script only affects Featured Content widgets.</p></li><li><p>Navigate away from the dashboard and back — the hide logic re-runs and widgets are correctly hidden again.</p></li><li><p>Content that was in a hidden widget still appears in reporting and in the learner's content actions log.</p><p></p></li></ul><hr><h2 class="text-xl" data-toc-id="299783af-6c17-416c-8fc0-1e7b22038c4d" id="299783af-6c17-416c-8fc0-1e7b22038c4d"><br><strong>Risk and Mitigation Strategy</strong></h2><ul><li><p><strong>Any CSS or JavaScript added via custom scripts may not be supported by the Thought Industries Technical Support team.</strong> This is a custom implementation — document it internally.</p><ul><li><p>You can use a tool like <a class="text-interactive hover:text-interactive-hovered" rel="noopener noreferrer nofollow" href="https://code.visualstudio.com/"><u>Visual Studio</u></a> to store your code internally.</p></li></ul></li><li><p><strong>This is a visual-only hide (display: none).</strong> The content is still assigned to the learner, still tracked in reporting, and still visible in the Learner Access Widget. No enrollment or completion data is affected.</p></li><li><p><strong>The script depends on TI's CSS class names</strong> (.widget--featured-content, .catalog-grid-item, .catalog-grid-item__completed). If TI changes these class names in a platform update, the script will stop working. It will fail silently — widgets will simply remain visible rather than being hidden. Test after platform updates.</p></li><li><p><strong>If new content is added to a previously hidden widget</strong> (e.g., you add a new course to a tag that powers a Featured Content widget), the widget will remain hidden for learners who had previously completed all items — until the next full page reload or dashboard navigation, at which point the script recalculates and will show the widget again (since total will now be greater than completed).</p></li><li><p><strong>The script overrides history.pushState and history.replaceState</strong> for SPA navigation handling. If you have other custom scripts on your instance that do the same (including the Welcome Card script from the companion configuration play), they can coexist — each one wraps the previous override. However, test them together to ensure no conflicts.</p></li><li><p><strong>If using both this script and the Welcome Card script (link to welcome card config play)</strong>, you can paste them both into the Custom Scripts area sequentially. They are designed as independent modules and do not share variables or state. The Welcome Card script does not include the hide-completed-widgets logic, so both scripts are needed if you want both features.</p></li><li><p><strong>Dashboard path:</strong> The script checks for /learn/dashboard. If your instance uses a different dashboard URL, update this path in both locations in the script.</p></li></ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build a Personalized Dashboard Welcome Card]]></title>
            <description><![CDATA[SUMMARY

Want your learners to feel like the platform knows them the moment they land on their dashboard? This play walks you through a custom script that adds a branded welcome card to the top of the ...]]></description>
            <link>https://community.thoughtindustries.com/guides-tutorials-g3mgzv80/post/build-a-personalized-dashboard-welcome-card-rYmcsBENuJPeX12</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/guides-tutorials-g3mgzv80/post/build-a-personalized-dashboard-welcome-card-rYmcsBENuJPeX12</guid>
            <dc:creator><![CDATA[Thought Industries]]></dc:creator>
            <pubDate>Wed, 27 May 2026 21:26:54 GMT</pubDate>
            <content:encoded><![CDATA[<h2 class="text-xl" data-toc-id="f3dcbc3f-c68d-4b38-a1d3-31f4da2dce63" id="f3dcbc3f-c68d-4b38-a1d3-31f4da2dce63"><strong>Summary</strong></h2><p>Want your learners to feel like the platform knows them the moment they land on their dashboard? This play walks you through a custom script that adds a branded welcome card to the top of the learner dashboard — greeting them by name with a time-appropriate message, optionally displaying contextual information from their profile (like their product or team), showing them where they left off with a direct link to their last course, and providing a "Continue Learning" button that scrolls them to their assigned content. The card is fully customizable to match your brand.<br></p><figure data-align="center" data-size="best-fit" data-id="wqJbIaKYNU0SwTTDZaf25" data-version="v2" data-type="image"><img data-id="wqJbIaKYNU0SwTTDZaf25" src="https://tribe-s3-production.imgix.net/wqJbIaKYNU0SwTTDZaf25?auto=compress,format"></figure><p><br><strong>Requirement Overview</strong></p><p>If any of these requirements fit your end goal, this may be the play for you.</p><ul><li><p><strong>Requirement 1:</strong> You want a personalized greeting on the dashboard that addresses the learner by first name and changes based on time of day (Good morning / Good afternoon / Good evening).</p></li><li><p><strong>Requirement 2:</strong> You want to display contextual information from the learner's profile — such as their product, team, or organization — pulled from a learner reference field.</p></li><li><p><strong>Requirement 3:</strong> You want a "Pick up where you left off" link that remembers the last course a learner visited and provides a direct link back to it.</p></li></ul><p><strong>Requirement 4:</strong> You want a "Continue Learning" button that scrolls the learner down to their assigned content on the dashboard.<br><br><strong>Functional Areas to be Used</strong></p><ul><li><p>Custom Scripts (Site → Site Builder → Pages → Dashboard → Custom Scripts)</p></li><li><p>Learner Reference Fields (for personalized data like product or role)</p></li><li><p>Dashboard Layout - this can be added to the global layout or any customized panorama layout</p></li><li><p>CSS Styling</p></li></ul><p></p><hr><p></p><h2 class="text-xl" data-toc-id="46832f1c-dd92-44b8-a47b-24a036331bf2" id="46832f1c-dd92-44b8-a47b-24a036331bf2"><strong>Core Functionality Configurations</strong></h2><h3 class="text-lg" data-toc-id="1ee70aac-ed61-4987-9d11-a678227f9a7c" id="1ee70aac-ed61-4987-9d11-a678227f9a7c"><strong>Understanding the Script &amp; What It Does</strong></h3><p><strong>Description:</strong> This script is a single block of JavaScript that runs on the learner dashboard. It does four things:</p><ol><li><p><strong>Personalized Welcome Card</strong> — A styled card at the top of the dashboard with a time-based greeting, the learner's first name, an optional product/context line pulled from a reference field, a subtitle message, and a "Continue Learning" button.<br><br></p></li><li><p><strong>Last Course Tracking</strong> — Tracks the last course the learner visited using the browser's localStorage (scoped per learner) and displays a "Pick up where you left off" link inside the welcome card.<br><br></p></li><li><p><strong>Continue Learning Button</strong> — A button on the welcome card that smooth-scrolls the learner down to the Learner Access Widget (their assigned content section) on the dashboard.<br><br></p></li></ol><p><strong>Navigation Handling</strong> —  The script intercepts browser history events to ensure tracking and display logic work correctly as learners navigate between the dashboard and course pages without full page reloads.<br><br></p><hr><p></p><h3 class="text-lg" data-toc-id="4fab364d-3947-4665-9f3e-cb12b47f688b" id="4fab364d-3947-4665-9f3e-cb12b47f688b"><strong>1. The Personalized Welcome Card</strong></h3><p><strong>Description:</strong> The core visual component. Injects a styled card directly below the dashboard header that greets the learner by name with a time-appropriate message. Optionally displays a value from a learner reference field (e.g., their product, team, or company).</p><p><strong>How it works:</strong> The script reads the learner's first name and a reference field value from the TI platform's window.CONF.preload.currentUser object — this is data that TI makes available on every page for the logged-in user. It determines the time of day and selects "Good morning," "Good afternoon," or "Good evening." It then builds an HTML card element and injects it into the dashboard DOM directly after the dashboard header.</p><p><strong>What to customize for your instance:</strong><br><br>The <strong>eyebrow text</strong> — the small label above the greeting. In the script it reads "FlowStack Academy." Find this line and change it to your academy or program name:</p><pre><code>'&lt;p class="wc-eyebrow"&gt;Your Academy Name&lt;/p&gt;'</code></pre><p>The <strong>reference field</strong> used for the product/context line. The script reads from ref4:</p><pre><code>product = window.CONF.preload.currentUser.currentUser.ref4 || '';</code></pre><p><br>Change ref4 to whichever reference field holds the value you want to display (e.g., ref1, ref2, ref3). If you don't want to display a reference field value at all, you can remove this line and the corresponding HTML block:</p><pre><code>product ? '&lt;p class="wc-product"&gt;' + product + '&lt;/p&gt;' : '',</code></pre><p><br>The <strong>subtitle text</strong> — the line below the greeting:</p><pre><code>'&lt;p class="wc-sub"&gt;Great to have you here. Keep building momentum — every lesson gets you one step closer to your goals.&lt;/p&gt;'</code></pre><p><br>The <strong>CSS styling</strong> — The script injects its own CSS for the welcome card. Key values you'll likely want to customize to match your brand:</p><table style="width: 599px" class="border-collapse m-0 table-fixed"><colgroup><col style="width: 190px"><col style="width: 200px"><col style="width: 209px"></colgroup><tbody><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p><strong>CSS Property</strong></p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p><strong>What It Controls</strong></p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p><strong>Where to Find It</strong></p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>background: linear-gradient(...)</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Card background gradient</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>#ti-welcome-card rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>border: 1px solid rgba(24,95,165,.15)</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Card border color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>#ti-welcome-card rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>color:#185fa5</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Eyebrow text color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-eyebrow rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>background:#2b7de9</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Eyebrow accent line color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-eyebrow::before rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>color:#2b6ff5</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Product line text color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-product rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>color:#1a1d2e</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Headline text color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-headline rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>color:#2b6ff5</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>First name highlight color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-headline span rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>color:#4a5568</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Subtitle text color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-sub rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>background:#2b6ff5</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Button background color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-btn rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>background:#1a5de0</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Button hover color</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>.wc-btn:hover rule</p></td></tr><tr class="isolation-auto"><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>fill and opacity values in SVG polygons</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>Geometric accent shape colors</p></td><td class="relative border p-2 min-h-6 align-top [&amp;_p]:m-0" rowspan="1" colspan="1"><p>geoSvg variable</p></td></tr></tbody></table><p>To match your brand colors, do a find-and-replace on the primary blue values (#2b6ff5, #185fa5, #1a5de0, #2b7de9, #5b9cf6) with your brand's primary and secondary colors.</p><hr><p><br><strong>2. Last Course Tracking ("Pick Up Where You Left Off")</strong></p><p><strong>Description:</strong> Tracks the last course the learner visited and displays a "Pick up where you left off" link inside the welcome card with the course title and a direct link back to it.</p><p><strong>How it works:</strong> The script intercepts SPA navigation events across the entire platform. Whenever the learner navigates to a URL containing /learn/course/ or /courses/, the script waits 800ms (to let the page title update), captures the course title from document.title, and saves it to localStorage with a key scoped to the learner's user ID.</p><p>When the learner returns to the dashboard, the script reads from localStorage and displays the "Pick up where you left off" section inside the welcome card.</p><p><strong>What to customize for your instance:</strong><br><br>The <strong>localStorage key prefix</strong>. The script uses fs_last_course_. Change this to match your brand:</p><pre><code>var storageKey = 'fs_last_course_' + userId;</code></pre><p>The <strong>URL patterns</strong> that trigger tracking. If your instance uses different URL patterns for content, update this condition:</p><pre><code>if (path.indexOf('/learn/course/') !== -1 || path.indexOf('/courses/') !== -1) {</code></pre><p>The <strong>delay before capturing the title</strong> (800ms). If your instance loads slowly, increase this value:</p><pre><code>setTimeout(function () { ... }, 800);</code></pre><p><br><strong>Risk and Mitigation Strategy:</strong></p><ul><li><p>This feature uses localStorage, which is browser-specific and can be cleared by the learner. It does not persist across browsers or devices.</p></li><li><p>The script parses the course title from document.title by splitting on - and taking the first segment. If your page titles are formatted differently, the displayed title may be incorrect. Test with your actual content.</p></li></ul><p></p><hr><p></p><h3 class="text-lg" data-toc-id="713990d3-9b4a-4ef3-8da7-63129350ec4e" id="713990d3-9b4a-4ef3-8da7-63129350ec4e"><strong>3. Continue Learning Button</strong></h3><p><strong>Description:</strong> A button on the welcome card that smooth-scrolls the learner down to their assigned content section on the dashboard (the Learner Access Widget).<br><br><strong>What to customize for your instance:</strong></p><p>The <strong>target element</strong> for scrolling. If your primary content section uses a different widget, change the CSS selector:</p><pre><code>var target = document.querySelector('.dashboard-access__header');</code></pre><p>The <strong>fallback scroll distance</strong> (500 pixels). Adjust based on your dashboard layout:</p><pre><code>window.scrollBy({ top: 500, behavior: 'smooth' });</code></pre><p>The <strong>button text</strong>:</p><pre><code>'Continue Learning ',</code></pre><hr><p><br><strong>4. Navigation Handling</strong></p><p><strong>Description:</strong> The script intercepts history.pushState, history.replaceState, and popstate events to ensure the last-course tracking works as learners navigate between pages, and to re-inject the welcome card when learners return to the dashboard.</p><p><strong>What to customize for your instance:</strong></p><p>The <strong>dashboard path</strong>. The script checks for /learn/dashboard. If your instance uses a different dashboard URL, update these checks:</p><pre><code>if (window.location.pathname !== '/learn/dashboard') {</code></pre><pre><code>var onDashboard = window.location.pathname === '/learn/dashboard';</code></pre><hr><h2 class="text-xl" data-toc-id="e8e67368-4b12-4878-bda6-10f22f2e8534" id="e8e67368-4b12-4878-bda6-10f22f2e8534"><strong>The Script</strong></h2><p>Make any customizations you need from above to the script below and then put the entire script into the <strong>Custom Scripts</strong> area of your Dashboard layout (Site → Site Builder → Pages → Dashboard).<br><br></p><figure data-align="center" data-size="best-fit" data-id="NVBHqTsZJGWyAYhTzsU3N" data-version="v2" data-type="image"><img data-id="NVBHqTsZJGWyAYhTzsU3N" src="https://tribe-s3-production.imgix.net/NVBHqTsZJGWyAYhTzsU3N?auto=compress,format"></figure><h2 class="text-xl" data-toc-id="06d75bfe-05ac-45b7-90a0-0b9da821ea25" id="06d75bfe-05ac-45b7-90a0-0b9da821ea25"><strong>Installation</strong></h2><h3 class="text-lg" data-toc-id="637952e7-d839-43cd-a1f2-0f0dfb6ce9db" id="637952e7-d839-43cd-a1f2-0f0dfb6ce9db"><strong>Configuration</strong></h3><ol><li><p>Navigate to <strong>Site → Site Builder → Pages</strong>.</p></li><li><p>Open the <strong>Dashboard</strong> layout.</p></li><li><p>Locate the <strong>Custom Scripts</strong> area.</p></li><li><p>Put the entire script below with your customizations (including the &lt;script&gt; tags) into the Custom Scripts field.</p></li><li><p>Save the layout.</p></li><li><p>Test by logging in as a learner and navigating to the dashboard.</p></li></ol><pre><code>&lt;script&gt;
(function () {

  // ──────────────────────────────────────────────
  // LAST COURSE TRACKING — scoped per learner
  // ──────────────────────────────────────────────
  var userId = '';
  try {
    userId = window.CONF.preload.currentUser.currentUser.id || '';
  } catch (e) {}
  var storageKey = 'fs_last_course_' + userId;

  function trackCourseIfOnCoursePage() {
    var path = window.location.pathname;
    if (path.indexOf('/learn/course/') !== -1 || path.indexOf('/courses/') !== -1) {
      setTimeout(function () {
        try {
          var title = document.title.split(' - ')[0].trim();
          if (title &amp;&amp; storageKey) {
            localStorage.setItem(storageKey, JSON.stringify({
              title: title,
              url: path,
              time: Date.now()
            }));
          }
        } catch (e) {}
      }, 800);
    }
  }

  // Run on initial load in case learner lands directly on a course page
  trackCourseIfOnCoursePage();

  // ──────────────────────────────────────────────
  // NON-DASHBOARD PAGES — track courses only, exit early
  // ──────────────────────────────────────────────
  if (window.location.pathname !== '/learn/dashboard') {
    var _push = history.pushState;
    history.pushState = function () {
      _push.apply(this, arguments);
      setTimeout(trackCourseIfOnCoursePage, 100);
    };
    var _replace = history.replaceState;
    history.replaceState = function () {
      _replace.apply(this, arguments);
      setTimeout(trackCourseIfOnCoursePage, 100);
    };
    window.addEventListener('popstate', trackCourseIfOnCoursePage);
    return;
  }

  // ──────────────────────────────────────────────
  // DASHBOARD — personalized welcome card
  // ──────────────────────────────────────────────

  // Read learner data
  var firstName = '';
  var product = '';
  try {
    firstName = window.CONF.preload.currentUser.currentUser.firstName || '';
    firstName = firstName.charAt(0).toUpperCase() + firstName.slice(1);
    product = window.CONF.preload.currentUser.currentUser.ref4 || '';
  } catch (e) {}
  if (!firstName) firstName = 'there';

  // Time-based greeting
  var hour = new Date().getHours();
  var greeting = hour &lt; 12 ? 'Good morning' : hour &lt; 17 ? 'Good afternoon' : 'Good evening';

  // State
  var sectionCreating = false;

  // ──────────────────────────────────────────────
  // CSS — customize colors to match your brand
  // ──────────────────────────────────────────────
  var style = document.createElement('style');
  style.textContent = [
    '#ti-welcome-card *{box-sizing:border-box;margin:0;padding:0}',
    '#ti-welcome-card{background:linear-gradient(135deg,#e8edf7 0%,#eef1fa 60%,#e6f1fb 100%);border-radius:16px;padding:36px 40px;margin:0 0 28px;display:flex;align-items:center;position:relative;overflow:hidden;border:1px solid rgba(24,95,165,.15);font-family:inherit}',
    '#ti-welcome-card .wc-geo{position:absolute;right:-20px;top:0;bottom:0;width:260px;pointer-events:none;z-index:1}',
    '#ti-welcome-card .wc-left{flex:1;position:relative;z-index:2;max-width:520px}',
    '#ti-welcome-card .wc-eyebrow{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:#185fa5;margin-bottom:6px;display:flex;align-items:center;gap:8px}',
    '#ti-welcome-card .wc-eyebrow::before{content:"";display:inline-block;width:20px;height:2px;background:#2b7de9;border-radius:2px}',
    '#ti-welcome-card .wc-product{font-size:12px;font-weight:600;color:#2b6ff5;margin-bottom:8px;letter-spacing:.02em;display:inline-flex;align-items:center;gap:6px}',
    '#ti-welcome-card .wc-product::before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;background:#2b6ff5}',
    '#ti-welcome-card .wc-headline{font-size:30px;font-weight:800;color:#1a1d2e;line-height:1.2;margin-bottom:10px;letter-spacing:-.02em}',
    '#ti-welcome-card .wc-headline span{color:#2b6ff5}',
    '#ti-welcome-card .wc-sub{font-size:14px;color:#4a5568;line-height:1.6;margin-bottom:24px;max-width:440px}',
    '#ti-welcome-card .wc-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap}',
    '#ti-welcome-card .wc-btn{display:inline-flex;align-items:center;gap:8px;background:#2b6ff5;color:#fff;font-size:13px;font-weight:700;padding:11px 22px;border-radius:8px;border:none;cursor:pointer;letter-spacing:.01em;transition:background .18s,transform .15s;text-decoration:none}',
    '#ti-welcome-card .wc-btn:hover{background:#1a5de0;transform:translateY(-1px)}',
    '#ti-welcome-card .wc-btn svg{transition:transform .18s}',
    '#ti-welcome-card .wc-btn:hover svg{transform:translateX(3px)}',
    '#ti-last-accessed{margin-top:20px;padding-top:16px;border-top:1px solid rgba(24,95,165,.15)}',
    '#ti-last-accessed .wc-last-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:#185fa5;margin-bottom:6px}',
    '#ti-last-accessed .wc-last-link{font-size:14px;font-weight:600;color:#1a1d2e;text-decoration:none;display:inline-flex;align-items:center;gap:6px;transition:color .15s}',
    '#ti-last-accessed .wc-last-link:hover{color:#2b6ff5}',
    '@media(max-width:600px){#ti-welcome-card{flex-direction:column;align-items:flex-start;padding:24px 20px}#ti-welcome-card .wc-headline{font-size:22px}#ti-welcome-card .wc-geo{display:none}}'
  ].join('');
  document.head.appendChild(style);

  // ──────────────────────────────────────────────
  // GEOMETRIC SVG ACCENT — decorative shape on right side of card
  // ──────────────────────────────────────────────
  var geoSvg = [
    '&lt;svg class="wc-geo" viewBox="0 0 260 200" preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg"&gt;',
      '&lt;polygon points="260,0 130,0 260,110" fill="#2b6ff5" opacity="0.12"/&gt;',
      '&lt;polygon points="260,200 100,200 260,80" fill="#185fa5" opacity="0.10"/&gt;',
      '&lt;polygon points="260,60 160,0 260,0" fill="#2b6ff5" opacity="0.18"/&gt;',
      '&lt;polygon points="260,140 150,200 260,200" fill="#185fa5" opacity="0.16"/&gt;',
      '&lt;polygon points="220,200 260,140 260,200" fill="#5b9cf6" opacity="0.20"/&gt;',
      '&lt;polygon points="190,0 260,0 260,70" fill="#5b9cf6" opacity="0.14"/&gt;',
    '&lt;/svg&gt;'
  ].join('');

  // ──────────────────────────────────────────────
  // WELCOME CARD HTML — customize eyebrow, subtitle, button text
  // ──────────────────────────────────────────────
  var card = document.createElement('div');
  card.id = 'ti-welcome-card';
  card.innerHTML = [
    geoSvg,
    '&lt;div class="wc-left"&gt;',
      '&lt;p class="wc-eyebrow"&gt;FlowStack Academy&lt;/p&gt;',
      product ? '&lt;p class="wc-product"&gt;' + product + '&lt;/p&gt;' : '',
      '&lt;h2 class="wc-headline"&gt;' + greeting + ', &lt;span&gt;' + firstName + '&lt;/span&gt;!&lt;/h2&gt;',
      '&lt;p class="wc-sub"&gt;Great to have you here. Keep building momentum — every lesson gets you one step closer to your goals.&lt;/p&gt;',
      '&lt;div class="wc-actions"&gt;',
        '&lt;button class="wc-btn" onclick="tiScrollToLearning()"&gt;',
          'Continue Learning ',
          '&lt;svg width="14" height="14" viewBox="0 0 14 14" fill="none"&gt;',
            '&lt;path d="M2 7h10M8 3l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/&gt;',
          '&lt;/svg&gt;',
        '&lt;/button&gt;',
      '&lt;/div&gt;',
    '&lt;/div&gt;'
  ].join('');

  // ──────────────────────────────────────────────
  // PICK UP WHERE YOU LEFT OFF — reads from localStorage
  // ──────────────────────────────────────────────
  function updateSection(course) {
    var courseUrl = course.url;
    var existingLink = document.querySelector('#ti-last-accessed .wc-last-link');
    if (existingLink) {
      existingLink.href = courseUrl;
      var lastNode = existingLink.lastChild;
      if (lastNode) lastNode.textContent = course.title;
      return;
    }
    if (sectionCreating) return;
    sectionCreating = true;
    var wcLeft = document.querySelector('#ti-welcome-card .wc-left');
    if (!wcLeft) {
      sectionCreating = false;
      setTimeout(function () { updateSection(course); }, 200);
      return;
    }
    var lastAccessed = document.createElement('div');
    lastAccessed.id = 'ti-last-accessed';
    lastAccessed.innerHTML = [
      '&lt;p class="wc-last-label"&gt;Pick up where you left off&lt;/p&gt;',
      '&lt;a href="' + courseUrl + '" class="wc-last-link"&gt;',
        '&lt;svg width="14" height="14" viewBox="0 0 14 14" fill="none"&gt;',
          '&lt;circle cx="7" cy="7" r="6" stroke="#2b6ff5" stroke-width="1.5"/&gt;',
          '&lt;path d="M5.5 4.5l4 2.5-4 2.5V4.5z" fill="#2b6ff5"/&gt;',
        '&lt;/svg&gt;',
        course.title,
      '&lt;/a&gt;'
    ].join('');
    wcLeft.appendChild(lastAccessed);
    sectionCreating = false;
  }

  function getLastAccessedCourse() {
    if (!storageKey) return;
    try {
      var stored = localStorage.getItem(storageKey);
      if (!stored) return;
      var course = JSON.parse(stored);
      if (course &amp;&amp; course.title &amp;&amp; course.url) {
        updateSection(course);
      }
    } catch (e) {}
  }

  // ──────────────────────────────────────────────
  // CONTINUE LEARNING BUTTON — scrolls to Learner Access Widget
  // ──────────────────────────────────────────────
  window.tiScrollToLearning = function () {
    var target = document.querySelector('.dashboard-access__header');
    if (target) {
      target.scrollIntoView({ behavior: 'smooth', block: 'start' });
      return;
    }
    window.scrollBy({ top: 500, behavior: 'smooth' });
  };

  // ──────────────────────────────────────────────
  // INJECT CARD — uses MutationObserver to wait for dashboard header
  // ──────────────────────────────────────────────
  var observer = new MutationObserver(function () {
    if (window.location.pathname !== '/learn/dashboard') return;
    if (document.getElementById('ti-welcome-card')) return;
    var header = document.querySelector('.header--dashboard');
    if (header &amp;&amp; header.parentNode) {
      header.parentNode.insertBefore(card, header.nextSibling);
      observer.disconnect();
      getLastAccessedCourse();
    }
  });

  // ──────────────────────────────────────────────
  // SPA NAVIGATION — re-inject card when returning to dashboard
  // ──────────────────────────────────────────────
  function checkPage() {
    var onDashboard = window.location.pathname === '/learn/dashboard';
    if (!onDashboard) {
      trackCourseIfOnCoursePage();
      var existingCard = document.getElementById('ti-welcome-card');
      if (existingCard) existingCard.parentNode.removeChild(existingCard);
      var oldSection = document.getElementById('ti-last-accessed');
      if (oldSection) oldSection.parentNode.removeChild(oldSection);
      sectionCreating = false;
      try { observer.observe(document.body, { childList: true, subtree: true }); } catch (e) {}
    } else {
      setTimeout(getLastAccessedCourse, 900);
    }
  }

  window.addEventListener('popstate', checkPage);
  var originalPushState = history.pushState;
  history.pushState = function () {
    originalPushState.apply(this, arguments);
    setTimeout(checkPage, 100);
  };
  var originalReplaceState = history.replaceState;
  history.replaceState = function () {
    originalReplaceState.apply(this, arguments);
    setTimeout(checkPage, 100);
  };

  // Start observer
  observer.observe(document.body, { childList: true, subtree: true });

})();
&lt;/script&gt;</code></pre><p><br><strong>Testing Checklist</strong></p><ul><li><p>The welcome card appears below the dashboard header with the correct greeting (based on time of day) and the learner's first name.</p></li><li><p>If the learner has a value in the configured reference field (default: ref4), it appears as the product/context line on the card.<br><br></p><figure data-align="center" data-size="best-fit" data-id="TWI2dIKhFsi2J45IvQhSs" data-version="v2" data-type="image"><img data-id="TWI2dIKhFsi2J45IvQhSs" src="https://tribe-s3-production.imgix.net/TWI2dIKhFsi2J45IvQhSs?auto=compress,format"></figure></li></ul><p><br>If the learner has no first name set, the greeting falls back to "there" (e.g., "Good morning, there!").</p><ul><li><p>If the learner has no reference field value, the product line does not appear (no empty space or broken layout).</p></li><li><p>The "Continue Learning" button scrolls to the Learner Access Widget.</p></li><li><p>Navigate to a course, then return to the dashboard — the "Pick up where you left off" link appears with the course title and a working link.</p></li><li><p>Test on mobile — the card stacks vertically and the geometric accent hides (responsive CSS is included).</p></li><li><p>Navigate away from the dashboard and back — the card re-injects correctly.</p><p></p></li></ul><hr><p><br><strong>Risk and Mitigation Strategy</strong></p><ul><li><p><strong>Any CSS or JavaScript added via custom scripts may not be supported by the Thought Industries Technical Support team.</strong> This is a custom implementation — document it internally and maintain it as part of your platform administration.</p><ul><li><p>You can use a tool like <a class="text-interactive hover:text-interactive-hovered" rel="noopener noreferrer nofollow" href="https://code.visualstudio.com/"><u>Visual Studio</u></a> to store your code internally.&nbsp;</p></li></ul></li><li><p><strong>The script depends on TI's DOM structure and CSS class names</strong> (.header--dashboard, .dashboard-access__header). Platform updates may change these. Test after every platform update.</p></li><li><p><strong>The script depends on window.CONF.preload.currentUser</strong> for learner data. If TI changes this data structure, the personalization features will break. The script uses try/catch blocks for graceful failure — the card will still render with fallback values.</p></li><li><p><strong>localStorage is browser-specific.</strong> The "Pick up where you left off" feature does not persist across browsers or devices, and clears if the learner clears browser data.</p></li><li><p><strong>The script overrides history.pushState and history.replaceState.</strong> If other custom scripts on your instance do the same, test for conflicts.</p></li><li><p><strong>The welcome card is injected via DOM manipulation, not TI's native widget system.</strong> It will not appear in the layout editor and cannot be repositioned using the drag-and-drop builder. To change its position, modify the JavaScript that targets the .header--dashboard insertion point.</p></li><li><p><strong>Document your customizations.</strong> When modifying colors, text, reference fields, or class names, note what you changed and why so future admins can maintain the script.</p></li><li><p>The custom script can be localized using third party tool.</p></li></ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[API: How to set a learner's course status (e.g. Not Started, In Progress)?]]></title>
            <description><![CDATA[Hi,

I'm looking for guidance on how to programmatically set or update a specific course status for a learner via the Thought Industries API.

Our use case: we occasionally need to reset or manually ...]]></description>
            <link>https://community.thoughtindustries.com/basic-2-column-umfls66p/post/api-how-to-set-a-learner-s-course-status-e-g-not-started-in-progress-SPF1V8yxrpc8lYY</link>
            <guid isPermaLink="true">https://community.thoughtindustries.com/basic-2-column-umfls66p/post/api-how-to-set-a-learner-s-course-status-e-g-not-started-in-progress-SPF1V8yxrpc8lYY</guid>
            <category><![CDATA[API]]></category>
            <category><![CDATA[Automation]]></category>
            <category><![CDATA[Workflows]]></category>
            <dc:creator><![CDATA[Pedro da Silva]]></dc:creator>
            <pubDate>Wed, 27 May 2026 15:02:08 GMT</pubDate>
            <content:encoded><![CDATA[<p>Hi,</p><p>I'm looking for guidance on how to programmatically set or update a specific course status for a learner via the Thought Industries API.</p><p>Our use case: we occasionally need to reset or manually assign a course status (for example, forcing a course back to <strong>Not Started</strong>, or flagging it as <strong>In Progress</strong>) for individual learners, as part of an automation workflow.</p><p>I've explored the learner enrollment and progress endpoints in the API docs but haven't found a clear method for writing a specific status value to a learner's course record. The read side seems well documented, but the write/update side is less clear to me.</p><p>Specifically, I'd love to know:</p><ol><li><p>Is there an API endpoint that accepts a course status value for a given learner and course?</p></li><li><p>What are the accepted status values (e.g. <code>not_started</code>, <code>in_progress</code>, <code>completed</code>)?</p></li><li><p>Are there any permissions or conditions that restrict what can be set via API (e.g. if SCORM completion is involved)?</p></li></ol><p>Any examples, endpoint references, or workarounds from those who've tackled this would be really appreciated. Happy to share back what we end up implementing.</p><p>Thanks in advance!</p>]]></content:encoded>
        </item>
    </channel>
</rss>