<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dana Ciubancan</title>
    <description>The latest articles on Forem by Dana Ciubancan (@danac0914).</description>
    <link>https://forem.com/danac0914</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F390511%2Fd60e8714-e281-4f01-a631-727d13bc2634.png</url>
      <title>Forem: Dana Ciubancan</title>
      <link>https://forem.com/danac0914</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/danac0914"/>
    <language>en</language>
    <item>
      <title>From Angular 16 to 17: The Strategy and The Results</title>
      <dc:creator>Dana Ciubancan</dc:creator>
      <pubDate>Wed, 22 Jan 2025 12:27:57 +0000</pubDate>
      <link>https://forem.com/danac0914/from-angular-16-to-17-the-strategy-and-the-results-1ea1</link>
      <guid>https://forem.com/danac0914/from-angular-16-to-17-the-strategy-and-the-results-1ea1</guid>
      <description>&lt;p&gt;Although a bit late to the party, I recently took on the task of upgrading a complex Angular project from version 16 to 17. While the official upgrade guide provides a great foundation, every project has unique challenges. Here’s my journey through the upgrade process, including the obstacles I encountered and how I resolved them. I hope sharing these experiences helps others facing similar challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Upgrade Strategy
&lt;/h2&gt;

&lt;p&gt;When starting an upgrade, I always (re-)read the official announcement (&lt;a href="https://blog.angular.dev/introducing-angular-v17-4d7033312e4b" rel="noopener noreferrer"&gt;Angular 17&lt;/a&gt;) to understand how our project might be impacted, what improvements I can bring to our codebase, and what new guidelines and concepts I can promote to our team.&lt;/p&gt;

&lt;p&gt;The second step is to check &lt;a href="https://angular.dev/update-guide?v=16.0-17.0&amp;amp;l=3" rel="noopener noreferrer"&gt;Angular’s official update guide&lt;/a&gt; for similar reasons: getting an understanding of possible failure points and changes I can expect in the code as part of the migration to the new version.&lt;/p&gt;

&lt;p&gt;The next and final step before starting the hands-on migration is to check the &lt;a href="https://nx.dev/nx-api/angular/documents/angular-nx-version-matrix" rel="noopener noreferrer"&gt;Angular-NX version compatibility matrix&lt;/a&gt;. Since our project uses NX this will be the driver for our migration steps.&lt;/p&gt;




&lt;p&gt;Another step I take, usually before I even consider an upgrade, is to check all our third-party dependencies and see if we might have any compatibility issues and possible solutions for them. With this in mind, after our main migration has successfully taken place I update each one of them to a compatible version.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Update Process
&lt;/h3&gt;

&lt;p&gt;For the update process, I always take an incremental approach: updating through each minor version rather than jumping straight to the latest. This helps me better identify the cause and resolve issues at each step.&lt;br&gt;
We’ve also decided to keep the NX version in sync with Angular and have not updated to the latest NX version. So, given the Angular-NX compatibility matrix below, we had a four-step migration on our hands: &lt;strong&gt;17.1.0 -&amp;gt; 17.3.0 -&amp;gt; 18.1.1 -&amp;gt; 18.2.0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqymemjwj5daz9hzgqr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqymemjwj5daz9hzgqr5.png" alt="Angular - Nx compatibility matrix" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each NX version, we followed these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;npx nx migrate &amp;lt;nx-version&amp;gt;&lt;/code&gt; — Initiate the migration&lt;/li&gt;
&lt;li&gt;Review and validate changes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm install&lt;/code&gt; — Update dependencies&lt;/li&gt;
&lt;li&gt;Commit changes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx nx migrate --run-migrations&lt;/code&gt; - Execute migrations&lt;/li&gt;
&lt;li&gt;Test, lint, and build for production&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Version-specific Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  npx nx migrate 17.1.0
&lt;/h3&gt;

&lt;p&gt;Our first interesting challenge was upgrading to NX version 17.1.0. The migration failed instantly. Can you guess why? :) NX version 17.1.0 doesn’t exist. If you go digging through versions you will see there have been some 17.1.0 beta versions but then directly 17.1.1.&lt;/p&gt;

&lt;p&gt;The solution was to use &lt;code&gt;npx nx migrate 17.1&lt;/code&gt; instead of &lt;code&gt;17.1.0&lt;/code&gt;, which allowed us to upgrade to the latest 17.1.x version.&lt;/p&gt;

&lt;p&gt;This first migration step updated the code base to the Angular 17 version and this brought our main issues of the migration, the unsupported libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ngx-matomo&lt;/li&gt;
&lt;li&gt;ngx-quill&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/ngx-matomo" rel="noopener noreferrer"&gt;ngx-matomo&lt;/a&gt; hasn’t seen updates in 2 years and it doesn’t support Angular 17. While this library has served us well until now, we moved to &lt;a href="https://github.com/EmmanuelRoux/ngx-matomo-client" rel="noopener noreferrer"&gt;ngx-matomo-client&lt;/a&gt; which offers the same functionality with few code changes and it is better maintained. For more details into this transition, you can check out my &lt;a href="https://dev.to/danac0914/migrate-from-ngx-matomo-to-ngx-matomo-client-32pl"&gt;ngx-matomo to ngx-matomo-client article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/ngx-quill" rel="noopener noreferrer"&gt;ngx-quill&lt;/a&gt; version that we had was using quill v1 underneath and only ngx-quill versions using quill v2 were also supporting Angular 17. While I thought quill v2 would bring many changes, the transition was quite smooth. We only encountered issues with our keyboard bindings, where we had to migrate from using key number values to names: &lt;code&gt;key: 13 -&amp;gt; key: ‘Enter’&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Other changes that we had to address included some changes to eslint rules that cause our linting step to fail. I reviewed the changes and decided for each to either adjust the code or adjust the rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  npx nx migrate 17.3.0
&lt;/h3&gt;

&lt;p&gt;During this phase, we encountered several (smaller) challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jest undefined errors required explicit imports from @jest/globals&lt;/li&gt;
&lt;li&gt;Comply with new lint rules regarding paths and module boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A notable issue we encountered was with the NX CLI commands. The &lt;code&gt;nx serve --project=project-name&lt;/code&gt; syntax stopped working in this version. While this was fixed in later NX versions, we temporarily switched to using &lt;code&gt;nx run project-name:serve&lt;/code&gt; as a workaround.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versions 18.1.0 and 18.2.0
&lt;/h3&gt;

&lt;p&gt;I have no issues to report for versions 18.1.0 and 18.2.0. The NX migrations worked perfectly on our code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Angular 17 Improvements
&lt;/h2&gt;

&lt;p&gt;We took this upgrade opportunity to implement some significant improvements in our codebase:&lt;/p&gt;

&lt;h3&gt;
  
  
  Standalone Components Migration
&lt;/h3&gt;

&lt;p&gt;While we have been migrating components to standalone one-by-one as part of our day-to-day business, we now took the opportunity to migrate all components (except the main app component). While this wasn’t strictly required for Angular 17, it aligned well with the framework’s direction and helped modernize our codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in Control Flow Implementation
&lt;/h3&gt;

&lt;p&gt;Implementing the new control flow syntax was one of our major goals. To optimise this step, I used the automatic migration command &lt;code&gt;npx nx generate @angular/core:control-flow-migration&lt;/code&gt; and then checked each changed file (yeah, about 300 of them), to make sure no defects were introduced. Plus, additional changes were needed for the &lt;a class="mentioned-user" href="https://dev.to/for"&gt;@for&lt;/a&gt; track by to be properly set. Besides this, I also discovered some important caveats of using the automated migration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At times it deleted &lt;code&gt;&amp;lt;ng-template&amp;gt;&lt;/code&gt; tags which led to duplicated code and broken ViewChild references&lt;/li&gt;
&lt;li&gt;Elements within new if/else statements that were used for content projection using &lt;code&gt;&amp;lt;ng-content select="..."&amp;gt;&lt;/code&gt; needed wrapping with &lt;code&gt;&amp;lt;ng-container&amp;gt;&lt;/code&gt;to work properly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Looking forward
&lt;/h2&gt;

&lt;p&gt;This upgrade has been an exciting journey. The performance benefits from the new control flow syntax are already noticeable in our application. I’m particularly looking forward to expanding our use of Angular 17’s features, especially implementing signals and deferrable views in the coming months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While every Angular project is unique, I hope sharing my way of approaching the upgrade, as well as the specific challenges and solutions I encountered, helps you plan your upgrade to Angular 17.&lt;/p&gt;

&lt;p&gt;Remember that the official upgrade guide is your foundation, but be prepared to tackle project-specific issues along the way. Take time to review your project’s dependencies and test thoroughly at each step.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>programming</category>
      <category>nx</category>
    </item>
    <item>
      <title>Migrate from ngx-matomo to ngx-matomo-client</title>
      <dc:creator>Dana Ciubancan</dc:creator>
      <pubDate>Fri, 16 Aug 2024 06:00:00 +0000</pubDate>
      <link>https://forem.com/danac0914/migrate-from-ngx-matomo-to-ngx-matomo-client-32pl</link>
      <guid>https://forem.com/danac0914/migrate-from-ngx-matomo-to-ngx-matomo-client-32pl</guid>
      <description>&lt;p&gt;Funny enough, my first interaction with Matomo was on the exact date they switched from Piwik.&lt;/p&gt;

&lt;p&gt;While &lt;a href="https://www.npmjs.com/package/ngx-matomo?activeTab=readme" rel="noopener noreferrer"&gt;ngx-matomo&lt;/a&gt; has been my go-to library for Matomo integration in Angular projects ever since, its delayed compatibility with recent Angular versions has motivated me to research other available options.&lt;/p&gt;

&lt;p&gt;In this article, I'll go over the reasons you might want to stick to ngx-matomo, but also what to do when you decide to switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ngx-matomo to begin with?
&lt;/h2&gt;

&lt;p&gt;When I first had to integrate Matomo in an Angular project, ngx-matomo was one of the few libraries available. It was quick to set up and easy to understand, so it was the best choice at the moment, the alternative being writing the integration from scratch. &lt;/p&gt;

&lt;p&gt;We used features ranging from tracking regular user navigation to advanced tracking via tag manager configurations and custom variables.&lt;/p&gt;

&lt;p&gt;What I appreciate about the library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's easy to get started with&lt;/li&gt;
&lt;li&gt;it has simple user consent management&lt;/li&gt;
&lt;li&gt;it comes with a small bundle, of 16.18kb on the production build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are already using ngx-matomo and are not looking to use the latest versions of Angular early on, this library still covers most of the use cases you might be looking for.&lt;/p&gt;

&lt;p&gt;You can follow &lt;a href="https://github.com/Arnaud73/ngx-matomo/issues/107" rel="noopener noreferrer"&gt;this thread&lt;/a&gt; for updates on the latest Angular version support (Angular 18).&lt;/p&gt;

&lt;h2&gt;
  
  
  Best alternative: &lt;a href="https://www.npmjs.com/package/ngx-matomo-client" rel="noopener noreferrer"&gt;ngx-matomo-client&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Previously distributed as two separate packages (&lt;a href="https://www.npmjs.com/package/@ngx-matomo/tracker" rel="noopener noreferrer"&gt;ngx-matomo/tracker&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/@ngx-matomo/router?activeTab=readme" rel="noopener noreferrer"&gt;ngx-matomo/router&lt;/a&gt;), &lt;strong&gt;ngx-matomo-client&lt;/strong&gt; is now the most popular and well-maintained Angular library for Matomo integration. Taking into account also its resemblance to the existing library and its minimal impact of just 15.92 kb on our production build, ngx-matomo-client stood out as the most logical for replacing ngx-matomo.&lt;/p&gt;

&lt;p&gt;If you are starting from scratch, I would definitely recommend going directly for the ngx-matomo-client library.&lt;/p&gt;




&lt;p&gt;In the following sections, I will show you how I translated the capabilities of ngx-matomo into ngx-matomo-client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;First up, is the configuration. This part has suffered the most changes, but it is still quite straightforward. &lt;/p&gt;

&lt;p&gt;In ngx-matomo, the configuration and module import might look something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.module.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MatomoModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ngx-matomo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;MatomoModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matomoConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// environment config&lt;/span&gt;

&lt;span class="nx"&gt;matomoConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;scriptUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;matomoBaseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/js/container_&amp;lt;containerId&amp;gt;.js`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;trackers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;trackerUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;matomoBaseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/matomo.php`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;siteId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;requireConsent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;routeTracking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For ngx-matomo-client it is a bit simpler, making use of Angular injection for including route tracking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.module.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MatomoModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MatomoRouterModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ngx-matomo-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;MatomoModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matomoConfig&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;MatomoRouterModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// environment config&lt;/span&gt;

&lt;span class="nx"&gt;matomoConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;siteId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;trackerUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;matomoBaseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;scriptUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;matomoBaseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/js/container_&amp;lt;containerId&amp;gt;.js`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;requireConsent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tracking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no route tracking is needed, the &lt;strong&gt;MatomoRouterModule&lt;/strong&gt; can be skipped and the import of &lt;strong&gt;MatomoModule&lt;/strong&gt; can be adjusted to avoid dependencies on @angular/router as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.module.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MatomoModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ngx-matomo-client/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only need to ask user consent for using cookies and not the tracking itself, the equivalent configurations are the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ngx-matomo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;requireConsent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;requireCookieConsent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ngx-matomo-client&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;requireConsent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cookie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  User consent management
&lt;/h2&gt;

&lt;p&gt;For managing user consent opt-in, there is not much difference between the two libraries. Both of them have similar methods on a class called &lt;strong&gt;MatomoTracker&lt;/strong&gt;, so what you have to do is make sure you change the import to the new library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MatomoTracker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ngx-matomo-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// usage&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matomoTracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rememberConsentGiven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hoursToExpire&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matomoTracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forgetConsentGiven&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom variables and custom dimensions
&lt;/h2&gt;

&lt;p&gt;Similar to user consent, methods like &lt;strong&gt;setUserId&lt;/strong&gt;, &lt;strong&gt;setCustomVariable&lt;/strong&gt;, &lt;strong&gt;setCustomDimension&lt;/strong&gt; are the same for both libraries. Here as well you just need to make sure the import is updated to the new library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom event triggers
&lt;/h2&gt;

&lt;p&gt;In our project, we had the need to create triggers based on custom events. This is a requirement that none of the two libraries provide a wrapper for, so for this, we were left interacting directly with the &lt;strong&gt;_mtm&lt;/strong&gt; object.&lt;/p&gt;

&lt;p&gt;You can read more about this and why we no longer use a third-party library in &lt;a href="https://dev.to/danac0914/learn-from-small-architectural-mistakes-frontend-edition-932"&gt;my article about architectural mistakes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;When looking into libraries I looked into the ones that focus on direct integration with Matomo. If you are looking for a vendor-agnostic library you might want to look into the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/angulartics2" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/angulartics2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you found this article helpful. Let me know in the comments section what was your experience with integrating Matomo.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>matomo</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Learn from small architectural mistakes — Frontend edition</title>
      <dc:creator>Dana Ciubancan</dc:creator>
      <pubDate>Tue, 13 Aug 2024 06:51:42 +0000</pubDate>
      <link>https://forem.com/danac0914/learn-from-small-architectural-mistakes-frontend-edition-932</link>
      <guid>https://forem.com/danac0914/learn-from-small-architectural-mistakes-frontend-edition-932</guid>
      <description>&lt;p&gt;As a junior developer, I would always reach out to a third-party library to cover my needs. Ranging from combo boxes to dialogs and toast messages, if it was out there it was definitely the best choice.&lt;/p&gt;

&lt;p&gt;I would later learn that, at times, it’s better to write your own code and be independent. You will understand why after reading this article.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Background: The Project and the Library
&lt;/h2&gt;

&lt;p&gt;The starting point was the need to integrate Matomo into our Angular application to gain more insights regarding its usage.&lt;/p&gt;

&lt;p&gt;To do this, there are a couple of libraries that offer wrapper functionality over the Matomo interface, the one that I recommend being &lt;a href="https://www.npmjs.com/package/ngx-matomo-client" rel="noopener noreferrer"&gt;ngx-matomo-client&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;There was just one requirement we couldn’t cover by the main integration library. We needed to create an event to be used as the trigger in our tag manager configuration.&lt;/p&gt;

&lt;p&gt;Matomo offers this by creating a trigger of type &lt;strong&gt;Custom Event&lt;/strong&gt;. And based on their documentation, this is how it should work:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Triggered when a custom event is pushed to the Data-Layer. Allows developers to define manually when this trigger should be triggered by pushing an event to the Data-Layer. This way you can for example execute certain actions when a product is added to the cart, or when a user logs in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  The Decision to Integrate
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.matomo.org/guides/tagmanager/datalayer" rel="noopener noreferrer"&gt;The Matomo Data Layer&lt;/a&gt; is represented by the &lt;strong&gt;_mtm&lt;/strong&gt; object and this is what we needed to interact with to achieve our last requirement. There were close to no examples of people using it and interacting directly with it, so we were not sure if this was the best approach or whether we should continue digging.&lt;/p&gt;

&lt;p&gt;Then, we found our holy grail, &lt;a href="https://www.npmjs.com/package/angular-matomo-tag-manager" rel="noopener noreferrer"&gt;angular-matomo-tag-manager&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;It was doing just what we needed, a wrapper over sending event information to the Matomo Data Layer. It was working and it was out there. This gave us the assurance we had the right solution, and the library was the obvious choice, right? This was happening three years ago.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Consequences and Confusion
&lt;/h2&gt;

&lt;p&gt;The library depends on Angular v11. At the integration time, our project was using Angular v12, but npm was throwing only warnings for mismatched dependencies, so it didn't catch the attention of the developer who integrated the library.&lt;/p&gt;

&lt;p&gt;This became a problem when updating to newer versions of Angular and npm. Both our local and CI/CD builds started failing as npm changed the warnings into errors for mismatching dependencies.&lt;/p&gt;

&lt;p&gt;The library had no updates for supporting newer versions of Angular and we were no longer sure why this library was needed, because of course, the person who stumbled upon the issues was not the same as the person who integrated the library, Murphy’s Law at its best.&lt;/p&gt;

&lt;p&gt;Pressed for time and unsure of the potential impact of taking the library out, we made the classic mistake of choosing the path of least resistance. We implemented a temporary fix to get our builds running again and moved on, leaving the underlying issue unresolved. Little did we know that the library would no longer get updates and this issue would come back to haunt us repeatedly, each time consuming valuable time and resources.&lt;/p&gt;




&lt;p&gt;Newer Angular versions, new version mismatch investigations, the same issues. When we reached this point the third time, we decided to invest a bit more time and finally took the library out.&lt;/p&gt;

&lt;p&gt;What is left now, is a one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window['_mtm'].push({ event: 'eventId' });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;By far the biggest lesson that I learned from this is that if all you need is a one-liner, don’t integrate a library for it :).&lt;/p&gt;

&lt;p&gt;Looking back, the following would have made our journey here easier to navigate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;spend more time understanding what you need before finding a solution (always a lesson, never learned)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;have requirement to implementation traceability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;don’t hesitate to question legacy code and dependencies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;As software architects and developers, we often pride ourselves on our ability to leverage existing solutions to solve complex problems efficiently. However, our experience, as described in this article, serves as a reminder that not all integrations are created equal, and the allure of a quick fix can sometimes blind us to the long-term implications of our choices.&lt;/p&gt;

&lt;p&gt;Let me know what is your viewpoint when it comes to integrating third-party libraries and if our experience changed your perspective in any way.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>frontend</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
