<?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: Igor Kravchenko</title>
    <description>The latest articles on Forem by Igor Kravchenko (@gorniv).</description>
    <link>https://forem.com/gorniv</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%2F288378%2Faca62620-ae0f-421f-bac5-c443301a977b.jpg</url>
      <title>Forem: Igor Kravchenko</title>
      <link>https://forem.com/gorniv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gorniv"/>
    <language>en</language>
    <item>
      <title>How We Launched on ProductHunt Twice: Insights and Lessons</title>
      <dc:creator>Igor Kravchenko</dc:creator>
      <pubDate>Wed, 27 Nov 2024 12:31:08 +0000</pubDate>
      <link>https://forem.com/gorniv/how-we-launched-on-producthunt-twice-insights-and-lessons-1oil</link>
      <guid>https://forem.com/gorniv/how-we-launched-on-producthunt-twice-insights-and-lessons-1oil</guid>
      <description>&lt;p&gt;Many people have launched various projects on Product Hunt, but few have launched the same project twice. Sit back, and I’ll share some indie project horror stories...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A little introduction&lt;/strong&gt;: For those unfamiliar, Product Hunt is the most well-known (since 2013) and largest platform for launching various projects. Nowadays, even &lt;a href="https://www.producthunt.com/products/openai-api" rel="noopener noreferrer"&gt;openAI&lt;/a&gt; and &lt;a href="https://www.producthunt.com/products/nvidia" rel="noopener noreferrer"&gt;Nvidia&lt;/a&gt; launch there, or someone mimics them quite well...&lt;/p&gt;

&lt;h2&gt;
  
  
  Launch
&lt;/h2&gt;

&lt;p&gt;After &lt;strong&gt;two years&lt;/strong&gt; of developing &lt;a href="https://aso.dev" rel="noopener noreferrer"&gt;ASO.dev&lt;/a&gt;, we decided it was time to stop postponing marketing efforts.&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%2F1z3ejdx08mom701jyskv.jpg" 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%2F1z3ejdx08mom701jyskv.jpg" alt="Image description" width="335" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I’ve been studying startup materials for over 10 years, we didn’t dive deeply into launch guides (maybe a mistake) and proceeded with the understanding that we were aiming for an SEO link and maybe some traffic.&lt;/p&gt;

&lt;p&gt;We prepared materials and postponed the launch for two months, mainly improving the product and onboarding. We received connection requests on LinkedIn, voted for other projects, and, knowing that 700–800 votes were unattainable for us, decided not to compete for the top spots.&lt;br&gt;
We recorded a video (finished it right on the co-founder’s birthday) and scheduled our launch for the company’s two-year anniversary. I’d share a link, but... Product Hunt deleted everything (&lt;em&gt;oops, spoiler&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;We emailed our client base, shared the link in channels, and asked other company founders to vote for us (&lt;em&gt;sweet revenge for all the upvotes we’d given&lt;/em&gt;).&lt;br&gt;
The launch was on a Wednesday, and we got 69 votes...&lt;br&gt;
Let me explain in detail why this was a &lt;strong&gt;failure&lt;/strong&gt;, and it wasn’t because of the vote count—we made it into the day’s top 10 projects.&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%2Fldjxmu1jnz9424ky4x5q.jpg" 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%2Fldjxmu1jnz9424ky4x5q.jpg" alt="Image description" width="800" height="320"&gt;&lt;/a&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%2Fahw13al7yek1p8v8688l.jpg" 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%2Fahw13al7yek1p8v8688l.jpg" alt="Image description" width="591" height="1280"&gt;&lt;/a&gt;&lt;br&gt;
We went through the entire Product Hunt launch process, but even the day after voting ended, we could only be found via a direct link.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mentioning the product using &lt;code&gt;!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Appearing in search by product name&lt;/li&gt;
&lt;li&gt;Leaving a review for our project&lt;/li&gt;
&lt;li&gt;Adding it as an alternative to another project&lt;/li&gt;
&lt;li&gt;Listing the company or product usage in your profile\
&lt;strong&gt;None of this worked...&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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%2Fmrzoia8xmt8j0blfwzfw.jpg" 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%2Fmrzoia8xmt8j0blfwzfw.jpg" alt="Image description" width="800" height="361"&gt;&lt;/a&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%2Fy2k1klt2pdgqej1ql4pw.jpg" 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%2Fy2k1klt2pdgqej1ql4pw.jpg" alt="Image description" width="672" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over two days, we tried to resolve these issues with support.\&lt;br&gt;
On the first day—the launch day—responses were infrequent, mostly directing us to guides. It was clear they couldn’t fix their technical problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second Launch
&lt;/h2&gt;

&lt;p&gt;We asked support if a second launch could solve the issue, and by Friday, they deleted &lt;strong&gt;EVERYTHING&lt;/strong&gt;: all progress, the product, the company, and even the links.&lt;/p&gt;

&lt;p&gt;They replaced all links with new ones, and we redid everything in two days, scheduling a launch for Monday, November 25, 2024.&lt;br&gt;
For the second launch, we were "Featured" again, asked everyone to vote, and got even more upvotes, making it into the top 10 by the time of the newsletter.&lt;/p&gt;

&lt;p&gt;The "Product Hunt Daily" newsletter goes out at 15–20 UTC and includes the top 10 "Featured" products.&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%2Fibhnepyh8f9n2cnbaqdr.jpg" 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%2Fibhnepyh8f9n2cnbaqdr.jpg" alt="Image description" width="800" height="1320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can track voting, for example, &lt;a href="https://productwars2.akkio.com/?d=2024-11-25" rel="noopener noreferrer"&gt;here&lt;/a&gt;—it clearly shows vote deductions and spikes. It displays not only "Featured" projects, but we’re absent there—too few votes.&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%2Ft34qvli927cvo0s33reh.jpg" 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%2Ft34qvli927cvo0s33reh.jpg" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways:
&lt;/h2&gt;

&lt;p&gt;From the first launch, we gained experience and valuable lessons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DO NOT ask support to change links to more readable or pretty ones! (They can break everything.)&lt;/li&gt;
&lt;li&gt;Editing the launch title or product name may change the link (also applies to already published projects).&lt;/li&gt;
&lt;li&gt;If your project isn’t "Featured," the launch is almost useless.
Nowadays, "Featured" status is crucial—even if you have thousands of votes, without "Featured," you won’t get a badge or make it into the newsletter! "Featured" projects gather slightly more upvotes (personal experience 😂).
I don’t know if this is a new or old rule, BUT without "Featured," it’s mostly pointless!
Whether a project is "Featured" can be determined about a day before the launch—it says "Featured on" or "Posted on" at the bottom.&lt;/li&gt;
&lt;/ol&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%2Fcy7okaf810dvwlfpkpa5.jpg" 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%2Fcy7okaf810dvwlfpkpa5.jpg" alt="Image description" width="800" height="200"&gt;&lt;/a&gt;&lt;br&gt;
   Achieving "Featured" status AFTER launch is possible, but it’s difficult and time-consuming.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Their mobile app is weird, showing only "Featured" projects and usually limiting the number to 10 (+2 ads).&lt;/li&gt;
&lt;/ol&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%2Fhubk3a5u273y4mw3ng19.jpg" 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%2Fhubk3a5u273y4mw3ng19.jpg" alt="Image description" width="590" height="1280"&gt;&lt;/a&gt;&lt;br&gt;
   Some links are intercepted by the mobile app but don’t open...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comment notifications are only sent to the project’s hunter; makers receive no notifications.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Bonus Knowledge:
&lt;/h3&gt;

&lt;p&gt;You’ll receive lots of spam across all social media and email offering to support your product &lt;del&gt;with bots&lt;/del&gt;, ranging from 50 to 700 votes for varying sums of money, or posts about you in groups with hundreds or millions of &lt;del&gt;bots&lt;/del&gt; people 🙈. You’ll also hear from interesting people launching their projects (we understand them much better now ♡), as well as some sneaky ones claiming they supported you with their 100–500-person team on launch day, which often isn’t true.&lt;br&gt;
&lt;a href="https://www.producthunt.com/@gorniv/upvotes" rel="noopener noreferrer"&gt;Check&lt;/a&gt; users’ votes if you agree on mutual support, and verify they haven’t withdrawn their votes afterward (examples exist).&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%2Flmvpjndpyjoajx7ly9id.jpg" 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%2Flmvpjndpyjoajx7ly9id.jpg" alt="Image description" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We received almost NO organic traffic. We talked to founders of other projects that secured 1st and 2nd places—they also didn’t get significant user inflow. For 700–900 votes, they had about 100–180 registrations, with many bringing their audience...&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%2Feq1dd90gxq7w1hzvc5re.jpg" 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%2Feq1dd90gxq7w1hzvc5re.jpg" alt="Image description" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the video views, it’s clear almost no one watched it, despite TWO launches. From my observations, having a video is almost 100% mandatory to be "Featured."&lt;br&gt;
Changing the product category is still buggy—we can’t change it again, and for some reason, ASO.dev is now labeled as the &lt;strong&gt;best SEO-tool.&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%2Fenjktc2765g3dbxdg2ze.jpg" 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%2Fenjktc2765g3dbxdg2ze.jpg" alt="Image description" width="800" height="180"&gt;&lt;/a&gt;&lt;br&gt;
So far, we’ve had ONE purchase with a 25% discount promo code from the launch.&lt;br&gt;
&lt;a href="https://www.producthunt.com/posts/aso-dev-1" rel="noopener noreferrer"&gt;Our launch&lt;/a&gt; from November 25 ranked 11th by the end of the day.&lt;/p&gt;

&lt;p&gt;SEO performance updates will follow.&lt;/p&gt;

&lt;p&gt;P.S.: If you need to work with App Store Connect or organic growth (like SEO but for iOS), try our product &lt;a href="https://aso.dev" rel="noopener noreferrer"&gt;ASO.dev&lt;/a&gt; 👍&lt;/p&gt;

</description>
      <category>producthunt</category>
      <category>marketing</category>
      <category>aso</category>
    </item>
    <item>
      <title>SEO from a Newbie for Beginners</title>
      <dc:creator>Igor Kravchenko</dc:creator>
      <pubDate>Fri, 25 Oct 2024 09:51:13 +0000</pubDate>
      <link>https://forem.com/asodev/seo-from-a-newbie-for-beginners-bc6</link>
      <guid>https://forem.com/asodev/seo-from-a-newbie-for-beginners-bc6</guid>
      <description>&lt;p&gt;So, you've got a bootstrap project, an awesome &lt;a href="https://aso.dev" rel="noopener noreferrer"&gt;product&lt;/a&gt;, but few customers. My time has come to dive into SEO.\&lt;br&gt;
Running a bootstrap or indie project really sharpens a lot of skills and teaches you to focus more on business (money). Plus, you realize that marketers aren't just sitting around—they've got a tough job too!&lt;/p&gt;

&lt;p&gt;What follows is a pretty basic rundown of things I've learned and done over the last few days (or weeks). &lt;/p&gt;
&lt;h2&gt;
  
  
  First Things First: The Domain
&lt;/h2&gt;

&lt;p&gt;They say &lt;code&gt;.com&lt;/code&gt; is slightly better, but overall, it doesn't really matter. If your domain isn't brand new, that's even better—domain reputation and backlinks matter! This is also why buying underperforming but promising projects (including domains) can pay off if you know what you're doing.&lt;/p&gt;

&lt;p&gt;We snagged &lt;a href="https://aso.dev" rel="noopener noreferrer"&gt;aso.dev&lt;/a&gt; for a magical $98 (or close to that).&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%2Fs3.aso.dev%2Fblog%2Fseo%2Faso.dev.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%2Fs3.aso.dev%2Fblog%2Fseo%2Faso.dev.png" alt="aso.dev" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you build the site.\&lt;br&gt;
Since SEO is a priority, server-side rendering (SSR) is a must. There's a lot of talk about Google being able to parse JavaScript, but that's mostly nonsense. Sometimes it can, but it generally hates doing so, so don’t risk it. You could use a heavy SSR setup for React or Angular, but we went with &lt;a href="https://astro.build" rel="noopener noreferrer"&gt;astro.build&lt;/a&gt;—super fast, simple, and elegant. They have plenty of &lt;a href="https://astro.build/themes/?search=&amp;amp;price%5B%5D=free" rel="noopener noreferrer"&gt;free and complex themes&lt;/a&gt;, but we settled on their &lt;a href="https://starlight.astro.build/" rel="noopener noreferrer"&gt;Starlight theme&lt;/a&gt; after tweaking the home page a bit (you need to copy the Hero.astro component and override Head.astro).&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%2F1xz45in6kfh9dqba5q2t.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%2F1xz45in6kfh9dqba5q2t.png" alt="Starlight" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm loving it so far. We're even reworking the site for our player, &lt;a href="https://meows.app" rel="noopener noreferrer"&gt;meows.app&lt;/a&gt;, because dynamic rendering based on API responses works perfectly. We hired a junior dev to rewrite it from scratch on the same tech stack for cheap—great practice for him and a faster, simpler site for us. Angular 14 just isn't cutting it anymore, even with Universal rendering (feels like ages ago)—check out our &lt;a href="https://astro.meows.app/playlist/us/pl.6b4090f7cc3c4aa6a93ec725751715b5" rel="noopener noreferrer"&gt;WIP example with Astro&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s looking pretty good. Previously, we used &lt;a href="https://tinypng.com/" rel="noopener noreferrer"&gt;tinypng&lt;/a&gt; for compressing images (manually or through API + GPT script), but now we're sticking to the built-in image optimization tools in astro.build.&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%2F9wt51w19wx88m4c174q9.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%2F9wt51w19wx88m4c174q9.png" alt="SEO performance in Google Chrome for ASO.dev" width="800" height="877"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Google Search Console
&lt;/h2&gt;

&lt;p&gt;Next up: Google Search Console. Add your site to track indexing, spot errors, and unlock achievements (which you can flex on &lt;a href="https://x.com/gorniv/status/1834187073697255453" rel="noopener noreferrer"&gt;Twitter&lt;/a&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%2Fiw06of6f9q4zl7iqprsw.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%2Fiw06of6f9q4zl7iqprsw.png" alt="Achivements" width="800" height="983"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://search.google.com/search-console" rel="noopener noreferrer"&gt;Google Search Console&lt;/a&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%2Fs3.aso.dev%2Fblog%2Fseo%2Fsearch_console.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%2Fs3.aso.dev%2Fblog%2Fseo%2Fsearch_console.png" alt="Google Search Console" width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are plenty of tools out there, but for now, I’m sticking with a couple of free ones.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ahrefs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://app.ahrefs.com/dashboard" rel="noopener noreferrer"&gt;User login - Ahrefs&lt;/a&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%2Fi0852lrhm98dwbem9e7o.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%2Fi0852lrhm98dwbem9e7o.png" alt="Ahrefs dashboard" width="800" height="475"&gt;&lt;/a&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%2Frdiqgz1m4kskjam8fy2q.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%2Frdiqgz1m4kskjam8fy2q.png" alt="Ahrefs dashboard" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahrefs is great because you get 10k site queries and a detailed analysis of your pages’ issues. You can’t fix everything, but reducing errors helps a lot.&lt;/p&gt;

&lt;p&gt;This tool provided most of the insights I’ve used to improve my site.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fixes and Improvements
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Optimizing Page Titles and Descriptions
&lt;/h3&gt;

&lt;p&gt;Titles should be 50-60 characters, and descriptions 110-160. In the meta structure of my .md files, I added them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;seo:
  seo_title: "All-in-One ASO Solution for iOS Developers, marketing"
  seo_description: "ASO.dev is ultimate tool for App Store Optimization (ASO) with App Store Connect integration.Manage,optimize,grow your apps effortlessly with powerful features"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I asked GPT to write a Bash script to check these files. After about 30 tries, it finally worked (still faster than if I did it by hand):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Function to check the length of seo_title and seo_description&lt;/span&gt;
check_seo_params&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;in_seo_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
  local &lt;/span&gt;&lt;span class="nv"&gt;seo_title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;seo_description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; line
  &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c"&gt;# Look for the start of the seo block&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^seo: &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;in_seo_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
    &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="c"&gt;# If inside the seo block, search for seo_title and seo_description&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$in_seo_block&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="c"&gt;# Search for seo_title&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ seo_title:[[:space:]]&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;.&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;seo_title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_REMATCH&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;fi&lt;/span&gt;
      &lt;span class="c"&gt;# Search for seo_description&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ seo_description:[[:space:]]&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;.&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;seo_description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_REMATCH&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;fi
    fi&lt;/span&gt;

    &lt;span class="c"&gt;# If the seo block ends (new block or end of file), stop reading&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$in_seo_block&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^[^[:space:]] &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^seo &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;in_seo_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
    &lt;/span&gt;&lt;span class="k"&gt;fi
  done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;have_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;

  &lt;span class="c"&gt;# Check if seo_title is present and valid&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seo_title&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$divider&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"seo_title: Empty or not found"&lt;/span&gt;
    &lt;span class="nv"&gt;have_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
  &lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seo_title&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 50 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seo_title&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 60 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$divider&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"seo_title: Length &lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seo_title&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (50 &amp;lt;&amp;gt; 60): '&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;seo_title&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
    &lt;span class="nv"&gt;have_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;

  &lt;span class="c"&gt;# Check if seo_description is present and valid&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seo_description&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$have_errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$divider&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
    &lt;span class="k"&gt;fi
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"seo_description: Empty or not found"&lt;/span&gt;
    &lt;span class="nv"&gt;have_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
  &lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seo_description&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 110 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seo_description&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 160 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$have_errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$divider&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
    &lt;span class="k"&gt;fi
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"seo_description: Length &lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seo_description&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (110 &amp;lt;&amp;gt; 160): '&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;seo_description&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
    &lt;span class="nv"&gt;have_errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;

  &lt;span class="c"&gt;# Print divider only if there are no errors&lt;/span&gt;
  &lt;span class="c"&gt;# if [[ $have_errors = false ]]; then&lt;/span&gt;
  &lt;span class="c"&gt;#   echo $divider&lt;/span&gt;
  &lt;span class="c"&gt;# fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$divider&lt;/span&gt;
&lt;span class="c"&gt;# Recursive search for all .md and .mdx files in the src/content/docs directory&lt;/span&gt;
find src/content/docs &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="se"&gt;\(&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.md"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.mdx"&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;file&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c"&gt;# Check if the file contains a seo block before proceeding&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"seo:"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;check_seo_params &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$divider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the script, navigate to the file, copy the text into GPT, and ask for the optimal title and description. Here’s an example prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write seo_title and seo_description, send the result in English, use best practices and length requirements for seo.
Result in the format:
`yaml
  seo_title: ""
  seo_description: ""
`
seo_title 50-60 symbols, seo_description 100-160 symbols
text is ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, update all pages—super basic, I know, but better than having no metadata or duplicate content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Favicon Fixes
&lt;/h3&gt;

&lt;p&gt;We messed up the favicon a bit—used &lt;a href="https://realfavicongenerator.net/" rel="noopener noreferrer"&gt;realfavicongenerator&lt;/a&gt; to generate and test.&lt;/p&gt;

&lt;h3&gt;
  
  
  OG Tags
&lt;/h3&gt;

&lt;p&gt;I also added OG tags—meta tags that make your links look better in social media previews. At the very least, include &lt;strong&gt;og:title&lt;/strong&gt;, &lt;strong&gt;og:description&lt;/strong&gt;, and &lt;strong&gt;og:image&lt;/strong&gt; (use an absolute path). All our images are served via &lt;a href="https://bunny.net?ref=udwny5qidt" rel="noopener noreferrer"&gt;bunny.net&lt;/a&gt;, but I’m still fine-tuning that setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  application/ld+json
&lt;/h3&gt;

&lt;p&gt;Added some structured data with application/ld+json—no idea if it works, but it seems cool. Check out &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data" rel="noopener noreferrer"&gt;structured data markup&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/ld+json&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;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://schema.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WebSite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;headline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ogTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;page_description_seo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

            &lt;span class="na"&gt;mainEntity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Article&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;headline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;page_description_seo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;dateModified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Organization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ASO.dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://aso.dev&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="na"&gt;publisher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Organization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ASO.dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ImageObject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fileWithBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;favicon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&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="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;h3&gt;
  
  
  Custom 404 Page
&lt;/h3&gt;

&lt;p&gt;We built a custom 404 page. Defaulting to the index page is considered an error and could hurt SEO. &lt;/p&gt;

&lt;p&gt;Setting the &lt;code&gt;noindex&lt;/code&gt; meta tag on the 404 page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 404&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/404&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;headDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meta&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;robots&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noindex&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="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;Setting up a custom 404 page in Nginx config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt; &lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;absolute_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;# try_files $uri $uri/ /index.html;&lt;/span&gt;
            &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;"no-store,&lt;/span&gt; &lt;span class="s"&gt;no-cache,&lt;/span&gt; &lt;span class="s"&gt;must-revalidate,&lt;/span&gt; &lt;span class="s"&gt;max-age=0"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Pragma&lt;/span&gt; &lt;span class="s"&gt;"no-cache"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Expires&lt;/span&gt; &lt;span class="s"&gt;"Thu,&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="s"&gt;Jan&lt;/span&gt; &lt;span class="mi"&gt;1970&lt;/span&gt; &lt;span class="nf"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="s"&gt;GMT"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;# 404 page&lt;/span&gt;
        &lt;span class="k"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="n"&gt;/404.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/404.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;root&lt;/span&gt;   &lt;span class="n"&gt;/app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;internal&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;h3&gt;
  
  
  Redirects
&lt;/h3&gt;

&lt;p&gt;We had a bunch of 301 redirects. We made sure all URLs ended with a trailing slash (e.g., &lt;code&gt;https://aso.dev/aso/&lt;/code&gt; instead of &lt;code&gt;https://aso.dev/aso&lt;/code&gt;) to avoid duplication. After a thorough review, we eliminated outdated links in the code and added old URL redirects via NGINX.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# https://aso.dev/app-info/app-info/ https://aso.dev/aso/app-info/&lt;/span&gt;
  &lt;span class="k"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^(/ru|/en)?/app-info/app-info/?&lt;/span&gt;$ &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="n"&gt;/aso/app-info/&lt;/span&gt; &lt;span class="s"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  hreflang
&lt;/h3&gt;

&lt;p&gt;We added x-default to the hreflang attribute. Didn't know that was a thing until recently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Link to language alternates.&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canonical&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isMultilingual&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localeOpts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;localeOpts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;langPostfix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localeOpts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;localeOpts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;headDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alternate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;hreflang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;localeOpts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;localizedUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;langPostfix&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;href&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="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;headDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alternate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;hreflang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;localizedUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;href&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SEMrush
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.semrush.com/projects/" rel="noopener noreferrer"&gt;SEMrush&lt;/a&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%2Fhbq9gx564yrnuvgknh4l.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%2Fhbq9gx564yrnuvgknh4l.png" alt="SEMrush" width="800" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve been using SEMrush longer—it’s easier to downgrade to a free plan, but 100 checks and their pricing aren’t great.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backlinks
&lt;/h2&gt;

&lt;p&gt;Getting backlinks is tricky. You need links from reputable sites—spammy backlinks will hurt you. One good link from the New York Times beats hundreds from random blogs. We’re building up our backlink profile by listing our site on startup and indie project platforms. We found an Excel sheet with hundreds of link opportunities and are slowly working through it.&lt;/p&gt;

&lt;p&gt;Launching on &lt;a href="https://www.producthunt.com/products/asodev" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; can help—&lt;a href="https://www.producthunt.com/products/asodev" rel="noopener noreferrer"&gt;subscribe&lt;/a&gt; for updates. We've delayed the launch a few times, but it’s coming soon.&lt;/p&gt;

&lt;p&gt;Also, we try to write genuinely useful articles, not just filler.&lt;/p&gt;

&lt;p&gt;I might have missed something or gotten things wrong — feel free to share in the comments!&lt;/p&gt;

</description>
      <category>seo</category>
      <category>beginners</category>
      <category>startup</category>
      <category>developer</category>
    </item>
  </channel>
</rss>
