<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Marco Venturi - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Marco Venturi - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:19:51 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/marco-venturi/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use WPScan to Keep Your WordPress Site Secure ]]>
                </title>
                <description>
                    <![CDATA[ Over 40% of the web is powered by WordPress. But this makes this popular CMS an attractive target for hackers. So if you run a WordPress site, you’ll need to make sure it’s secure. And this isn’t just a technical task, but is also a key responsibilit... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-wpscan-to-keep-your-wordpress-site-secure/</link>
                <guid isPermaLink="false">6751e08319cee0c3e45cb876</guid>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ethicalhacking ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Thu, 05 Dec 2024 17:18:59 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732705985906/49090646-5b75-40f4-ad55-473d723b4237.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Over 40% of the web is powered by WordPress. But this makes this popular CMS an attractive target for hackers.</p>
<p>So if you run a WordPress site, you’ll need to make sure it’s secure. And this isn’t just a technical task, but is also a key responsibility from several points of view such as brand reputation, data breach, and business continuity.</p>
<p>One tool that stands out in the WordPress ecosystem is <strong>WPScan.</strong> It’s a security scanner that’s specifically designed for WordPress. It comes with both a paid and free license, according to your needs. It is also pre-installed in Kali Linux distributions.</p>
<p>So whether you’re a seasoned website admin or a website owner looking to improve your site's security, WPScan can help you identify vulnerabilities before attackers exploit them.</p>
<p>Before going ahead, one very important thing: the purpose of this article is to help individuals and organizations strengthen the security of their WordPress websites by effectively utilizing WPScan.</p>
<p>While this tool is incredibly powerful in identifying vulnerabilities, it’s important to emphasize that any unauthorized use of WPScan—such as scanning websites without proper permission—is not only unethical but also illegal.</p>
<p>My goal in sharing this information is to empower site administrators and developers to proactively secure their websites, safeguard their data, and create a safer online environment for everyone.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-wpscan">What is WPScan?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-scan-your-wordpress-site-using-wpscan">How to Scan Your WordPress Site Using WPScan</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-to-do-with-wpscan-results">What to do with WPScan Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-limitations-of-wpscan">Limitations of WPScan</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-for-using-wpscan">Best Practices for Using WPScan</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-monitor-results-effectively">How to Monitor Results Effectively</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-is-wpscan">What is WPScan?</h2>
<p>WPScan is a command-line tool that helps you identify potential vulnerabilities in your WordPress installation. It’s like a security guard for your website, keeping an eye on outdated plugins, misconfigurations, and other common issues.</p>
<p>What makes WPScan unique is its focus on WordPress. It uses a database maintained by security experts, which is updated regularly to track thousands of known vulnerabilities in WordPress core, plugins, and themes.</p>
<h3 id="heading-what-can-wpscan-do">What Can WPScan Do?</h3>
<p>Here are just a few things WPScan can help you with:</p>
<ul>
<li><p>Detecting outdated WordPress core versions.</p>
</li>
<li><p>Identifying vulnerabilities in plugins and themes.</p>
</li>
<li><p>Enumerating users (for example, discovering usernames).</p>
</li>
<li><p>Testing for weak passwords (using a dictionary attack).</p>
</li>
<li><p>Finding exposed sensitive files (like backups or debug logs).</p>
</li>
</ul>
<p>Let’s see now the most common commands you can use.</p>
<h2 id="heading-how-to-scan-your-wordpress-site-using-wpscan">How to Scan Your WordPress Site Using WPScan</h2>
<h3 id="heading-1-basic-scan"><strong>1. Basic Scan</strong></h3>
<p>A basic scan provides an overview of your WordPress site's security by identifying key vulnerabilities or misconfigurations. It can detect the WordPress core version and flag it if it's outdated, highlighting potential risks like SQL injection or cross-site scripting (XSS) vulnerabilities associated with older versions.</p>
<p>The scan might also reveal publicly accessible backup files (for example, <code>.sql</code> or <code>.zip</code>) or debug files like <code>debug.log</code>, which could expose sensitive information such as database credentials or server paths.</p>
<p>It can flag missing or improperly configured HTTP security headers, such as Strict-Transport-Security (HSTS) or Content-Security-Policy (CSP), which are critical for protecting against protocol downgrade attacks and unauthorized script execution.</p>
<p>Open directories that expose your site's file structure and potentially vulnerable plugins or themes may also be flagged if they are identified in public metadata.</p>
<p>These findings provide a starting point to address fundamental security gaps.</p>
<pre><code class="lang-bash">wpscan --url http://yourwebsite.com
</code></pre>
<p>This is what you’ll see on your terminal when you run this command:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733225875769/0b1daa21-a258-41e3-88c1-62b9a7a23554.png" alt="Results of basic scan with WPScan" class="image--center mx-auto" width="2688" height="1006" loading="lazy"></p>
<h3 id="heading-2-enumerating-users"><strong>2. Enumerating Users</strong></h3>
<p>User enumeration is a process of identifying usernames on your WordPress site. Knowing these usernames can help attackers target specific accounts for brute-force attacks.</p>
<p>To enumerate users, run:</p>
<pre><code class="lang-bash">wpscan --url http://yourwebsite.com --enumerate u
</code></pre>
<p>The output will show usernames:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733226140065/3650be6a-e8e6-4c8b-a183-f986643c8ac2.png" alt="3650be6a-e8e6-4c8b-a183-f986643c8ac2" class="image--center mx-auto" width="2678" height="454" loading="lazy"></p>
<p>If you find default usernames like <code>admin</code>, you should replace them with something unique and secure.</p>
<p>Here are some best practice for usernames:</p>
<ul>
<li><p><strong>Avoid default names</strong>: Replace default usernames like <code>admin</code> or <code>user</code> with something unique and not easily guessable.</p>
</li>
<li><p><strong>Rename vulnerable usernames</strong>: To change a username, you can create a new user with administrator privileges, transfer ownership of posts or content, and then delete the old user.</p>
</li>
<li><p><strong>Use role-based usernames carefully</strong>: Avoid naming accounts after their roles (for example, <code>editor</code>, <code>manager</code>), as these can be easy targets.</p>
</li>
<li><p><strong>Implement login lockouts</strong>: Combine secure usernames with plugins that lock accounts after repeated failed login attempts.</p>
</li>
<li><p><strong>Enable Two-Factor Authentication (2FA)</strong>: Adding 2FA ensures that even if a username is guessed, the account remains secure.</p>
</li>
</ul>
<h3 id="heading-3-checking-plugins-and-themes"><strong>3. Checking Plugins and Themes</strong></h3>
<p>Plugins and themes can have security issues. WPScan can list all installed plugins and themes, along with any associated vulnerabilities.</p>
<p>For plugins, run this:</p>
<pre><code class="lang-bash">wpscan --url http://yourwebsite.com --enumerate p
</code></pre>
<p>It’ll have an output like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733226282550/d428be3a-5b0d-410d-979a-2c65e3fb7846.png" alt="Results of plugin scan" class="image--center mx-auto" width="2678" height="618" loading="lazy"></p>
<p>For themes, run this:</p>
<pre><code class="lang-bash">wpscan --url http://yourwebsite.com --enumerate t
</code></pre>
<p>It’ll have output similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733226484963/ae2ded5c-2d71-41db-8b1e-4a74df3dd94d.png" alt="Results of theme scan" class="image--center mx-auto" width="2694" height="998" loading="lazy"></p>
<p>Look for outdated versions or known vulnerabilities in the results, and update or replace those components immediately.</p>
<p>Let’s look at some common security issues in plugins and themes.</p>
<p>First, we have <strong>Cross-Site Scripting (XSS)</strong>. Insecure input handling in plugins or themes can allow attackers to inject malicious scripts, potentially stealing user information or taking over admin sessions. A poorly secured WordPress site with an XSS vulnerability can allow attackers to steal session cookies, potentially gain unauthorized admin access, inject malicious redirects, take users to phishing sites, display deceptive content, tricking users into providing sensitive information.</p>
<p>There’s also <strong>SQL Injection</strong>. Poorly written plugins or themes can enable attackers to manipulate database queries, exposing sensitive data or damaging your site. SQL injection vulnerabilities can be exploited to dump sensitive data, bypass authentication, and modify or delete data</p>
<p>Some plugins or themes might include malicious code—intentionally or due to poor security—that grants attackers unauthorized access to your site, known as <strong>backdoors</strong>. Once installed, a backdoor can grant persistent access, enable arbitrary file uploads, undermine site integrity, and steal sensitive data.</p>
<p>There’s also <strong>Remote Code Execution (RCE)</strong> – vulnerabilities that allow attackers to execute arbitrary code on your server, often leading to full control of your site or server. Once attackers gain RCE access, they can create admin users, exfiltrate data, launch further attacks, and privilege escalation.</p>
<h4 id="heading-best-practices">Best Practices:</h4>
<ul>
<li><p>Always keep plugins and themes updated to the latest versions.</p>
</li>
<li><p>Remove any unused or inactive plugins and themes, as these can still pose a risk.</p>
</li>
<li><p>Ensure plugins and themes are downloaded from trusted, reputable sources and have a history of active maintenance.</p>
</li>
<li><p>Consider using security plugins to monitor changes to plugin or theme files and detect suspicious activity.</p>
</li>
</ul>
<h3 id="heading-4-password-testing"><strong>4. Password Testing</strong></h3>
<p>WPScan can test for weak passwords by attempting a brute-force attack using a wordlist:</p>
<pre><code class="lang-bash">wpscan --url http://yourwebsite.com --passwords /path/to/passwords.txt
</code></pre>
<p>and this is the output on your command line:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733229769208/699aebbe-576d-4bb6-a626-2a1139822f2d.png" alt="Password testing output" class="image--center mx-auto" width="2708" height="280" loading="lazy"></p>
<h4 id="heading-what-is-brute-forcing">What is Brute-Forcing?</h4>
<p>Brute-forcing is a method attackers use to guess passwords by systematically trying every possible combination until the correct one is found. When combined with a <strong>wordlist</strong>—a file containing a collection of commonly used passwords—brute-forcing becomes much faster and more efficient.</p>
<p>A typical wordlist might include:</p>
<ul>
<li><p><strong>Simple passwords</strong> like <code>123456</code>, <code>password</code>, and <code>qwerty</code>.</p>
</li>
<li><p><strong>Common patterns</strong> such as <code>Spring2024!</code> or <code>welcome123</code>.</p>
</li>
<li><p><strong>Leaked passwords</strong> from previous data breaches.</p>
</li>
</ul>
<p>By simulating this type of attack, WPScan can identify accounts that use weak passwords, allowing you to address vulnerabilities proactively.</p>
<p>Weak passwords make brute-forcing easier and faster. A short or predictable password might be guessed in seconds, while a longer, complex password with unique elements is exponentially harder to crack.</p>
<h4 id="heading-how-to-create-strong-passwords">How to Create Strong Passwords</h4>
<p>Strong passwords are your first line of defense against brute-force attacks. Here are key characteristics of strong passwords:</p>
<ul>
<li><p><strong>Length</strong>: At least 12–16 characters long.</p>
</li>
<li><p><strong>Complexity</strong>: Use a mix of uppercase and lowercase letters, numbers, and special characters.</p>
</li>
<li><p><strong>Uniqueness</strong>: Avoid reusing passwords across multiple accounts.</p>
</li>
<li><p><strong>Unpredictability</strong>: Avoid dictionary words, common phrases, or personal information like birthdays.</p>
</li>
</ul>
<h4 id="heading-strategies-for-generating-strong-passwords">Strategies for Generating Strong Passwords</h4>
<p>There are various measures you can take to create strong passwords. First, use a password generator<strong>.</strong> Tools like LastPass and Bitwarden can create and store highly complex passwords for you.</p>
<p>You should also use pass phrases (instead of just regular passwords). Combine random, unrelated words with numbers and symbols, such as <code>Sky#Tree!Motorbike12</code>.</p>
<p>Finally, avoid patterns that might be easily guessed by an attacker. Don’t use sequential or keyboard patterns like <code>abcdef</code> or <code>qwerty</code>.</p>
<h4 id="heading-use-tools-to-manage-passwords">Use Tools to Manage Passwords</h4>
<p>Managing strong passwords can be challenging. Password managers simplify this by securely storing and autofilling your credentials. Popular options include:</p>
<ul>
<li><p><strong>Bitwarden</strong></p>
</li>
<li><p><strong>LastPass</strong></p>
</li>
</ul>
<p>These tools also have features like password auditing to detect reused or weak passwords.</p>
<h4 id="heading-use-two-factor-authentication-2fa">Use Two-Factor Authentication (2FA)</h4>
<p>Two-factor authentication (2FA) adds an additional layer of security by requiring users to verify their identity through a second factor beyond the password. This can include:</p>
<ul>
<li><p><strong>One-time codes</strong> sent via email or SMS.</p>
</li>
<li><p><strong>App-generated codes</strong> from tools like Google Authenticator or Authy.</p>
</li>
<li><p><strong>Biometric verification</strong>, such as fingerprints or facial recognition.</p>
</li>
</ul>
<p>Even if an attacker guesses your password through brute-forcing, 2FA prevents them from accessing your account without secondary verification. This additional step makes brute-forcing impractical, as attackers would also need to compromise your 2FA device or method.</p>
<h5 id="heading-how-to-implement-2fa-in-wordpress">How to Implement 2FA in WordPress</h5>
<ol>
<li><p>Install a WordPress plugin such as <strong>Google Authenticator</strong>.</p>
</li>
<li><p>Require all user accounts, especially administrators, to enable 2FA.</p>
</li>
<li><p>Offer backup codes or recovery options in case users lose access to their 2FA device.</p>
</li>
<li><p>Test and make sure that 2FA works reliably for all user roles before making it mandatory.</p>
</li>
</ol>
<h4 id="heading-the-importance-of-password-hygiene">The Importance of Password Hygiene</h4>
<p>By using strong passwords and implementing 2FA, you can significantly reduce the effectiveness of brute-force attacks.</p>
<p>WPScan’s password testing feature can help you identify weak credentials. It also underscores the critical need for proactive password hygiene and additional security layers to keep your WordPress site secure.</p>
<h2 id="heading-what-to-do-with-wpscan-results"><strong>What to Do with WPScan Results</strong></h2>
<p>WPScan reports provide actionable insights into your site’s security. Here’s what you can do with the information:</p>
<p>First, update WordPress core, plugins, and themes: Keep everything updated to patch vulnerabilities.</p>
<p>Second, address configuration issues: Fix misconfigured file permissions, insecure HTTP headers, and other warnings.</p>
<p>Here are a couple of remediation examples you can apply:</p>
<ul>
<li><p><strong>Directory indexing</strong>: If WPScan detects open directories, disable directory browsing by adding this line to your <code>.htaccess</code> file:</p>
<pre><code class="lang-apache">  <span class="hljs-attribute"><span class="hljs-nomarkup">Options</span></span> -Indexes
</code></pre>
</li>
<li><p><strong>File permissions</strong>: Ensure critical files like <code>wp-config.php</code> are read-only by setting permissions to <code>440</code> or <code>400</code> using the command:</p>
<pre><code class="lang-bash">  chmod 400 wp-config.php
</code></pre>
</li>
</ul>
<p>You should also harden all user accounts. You can do this in several ways:</p>
<ul>
<li><p><strong>Update weak passwords</strong>: Use strong, unique passwords for all user accounts (refer to the password testing section for tips).</p>
</li>
<li><p><strong>Remove unused accounts</strong>: Delete inactive accounts, especially those with administrator privileges.</p>
</li>
<li><p><strong>Rename predictable usernames</strong>: Change usernames like <code>admin</code> to something less obvious.</p>
</li>
</ul>
<p>Make sure you also secure any sensitive files: If WPScan finds exposed files like <code>debug.log</code>, delete or secure them. Delete unnecessary files or old backups.</p>
<p>For files you need to keep, move them to a directory outside the web root. You can also protect files with <code>.htaccess</code>, by blocking access to sensitive files using <code>Deny</code> and <code>Allow</code> rules:</p>
<pre><code class="lang-apache"><span class="hljs-section">&lt;Files wp-login.php&gt;</span>
    <span class="hljs-attribute"><span class="hljs-nomarkup">Order</span></span> <span class="hljs-literal">Deny</span>,<span class="hljs-literal">Allow</span>
    <span class="hljs-attribute"><span class="hljs-nomarkup">Deny</span></span> from <span class="hljs-literal">all</span>
    <span class="hljs-attribute"><span class="hljs-nomarkup">Allow</span></span> from <span class="hljs-number">123.456.789.000</span>
<span class="hljs-section">&lt;/Files&gt;</span>
</code></pre>
<h2 id="heading-limitations-of-wpscan">Limitations of WPScan</h2>
<p>WPScan is a powerful too, but it does have some limitations. Just be aware of them so you can take other measures to protect your WP sites.</p>
<h3 id="heading-1-known-vulnerabilities-only"><strong>1. Known Vulnerabilities Only</strong></h3>
<p>WPScan relies on its database of known vulnerabilities, so it won’t catch zero-day exploits or custom vulnerabilities.</p>
<p>Here are some tips on how you can mitigate this issue:</p>
<ul>
<li><p><strong>Stay informed</strong>: Monitor WordPress security blogs, vulnerability databases like CVE or WPVulnDB, and community forums for emerging threats.</p>
</li>
<li><p><strong>Use a Web Application Firewall (WAF)</strong>: Tools like Cloudflare or Sucuri can block suspicious activities and attempts to exploit unknown vulnerabilities.</p>
</li>
<li><p><strong>Conduct manual security reviews</strong>: Periodically review your site for unusual behavior or unauthorized changes, particularly in critical files like <code>wp-config.php</code> or your database.</p>
</li>
</ul>
<h3 id="heading-2-no-real-time-protection"><strong>2. No Real-Time Protection</strong></h3>
<p>WPScan a diagnostic tool, not a firewall or intrusion detection system. For real-time protection, it’s a good idea to combine WPScan with other tools.</p>
<p>Some steps you can take are:</p>
<ul>
<li><p><strong>Install security plugins</strong>: Use specific security plugins to provide continuous monitoring, malware scanning, and firewall protection.</p>
</li>
<li><p><strong>Monitor activity logs</strong>: Set up activity tracking to identify suspicious login attempts, file changes, or unauthorized user actions.</p>
</li>
</ul>
<h3 id="heading-3-resource-intensive"><strong>3. Resource-Intensive</strong></h3>
<p>Scanning large sites with many plugins and themes can be time-consuming and may impact server performance.</p>
<p>There are various strategies you can adopt to mitigate this such as scheduling scans during low-traffic periods to minimize disruption to site visitors. You can also perform scans on a staging copy of your site rather than directly on the live environment.</p>
<h3 id="heading-4-learning-curve"><strong>4. Learning Curve</strong></h3>
<p>As a command-line tool, WPScan can be intimidating for less technical users. However, the documentation is excellent, and with practice, you’ll become proficient.</p>
<p>If the CLI is overwhelming for you, try pairing WPScan with security plugins that offer GUI-based scanning and reporting.</p>
<h2 id="heading-best-practices-for-using-wpscan">Best Practices for Using WPScan</h2>
<p>To get the most out of WPScan, you’ll want to to tailor its usage to your site’s specific needs and establish a robust strategy for monitoring results. Here’s how you can maximize its effectiveness:</p>
<h3 id="heading-choose-the-right-scans-for-your-site">Choose the Right Scans for Your Site</h3>
<p>WPScan offers a variety of scan options, from basic scans to targeted vulnerability checks for plugins, themes, and user accounts. Choosing the right scans depends on the type of site you manage and the sensitivity of the data it handles.</p>
<p><strong>For small, low-traffic sites</strong>:</p>
<ul>
<li><p>Prioritize basic scans to check WordPress core, plugins, and themes for updates and vulnerabilities.</p>
</li>
<li><p>Run scans monthly or after major updates.</p>
</li>
<li><p>Use user enumeration (<code>--enumerate u</code>) if you suspect weak passwords or default usernames.</p>
</li>
</ul>
<p><strong>For medium-sized business sites</strong>:</p>
<ul>
<li><p>In addition to basic scans, include plugin and theme enumeration (<code>--enumerate p,t</code>) to ensure all components are secure.</p>
</li>
<li><p>Weekly scans to stay ahead of emerging threats.</p>
</li>
<li><p>Combine WPScan with activity log plugins to track user actions and file changes.</p>
</li>
</ul>
<p><strong>For high-traffic or e-commerce sites</strong>:</p>
<ul>
<li><p>Perform comprehensive scans, including user enumeration (<code>--enumerate u</code>), file enumeration (<code>--enumerate f</code>), and password brute-force testing (if allowed).</p>
</li>
<li><p>Daily or weekly scans to minimize risk.</p>
</li>
<li><p>Implement additional measures like 2FA for admin accounts, a web application firewall (WAF), and security headers to reinforce your site.</p>
</li>
</ul>
<p><strong>For sites handling sensitive data</strong>:</p>
<ul>
<li><p>Prioritize all available scans, including those for exposed files and configuration vulnerabilities.</p>
</li>
<li><p>Weekly scans with real-time monitoring via a security plugin.</p>
</li>
<li><p>Use staging environments to test security settings without affecting production.</p>
</li>
</ul>
<h3 id="heading-should-you-use-all-scans"><strong>Should You Use All Scans?</strong></h3>
<p>While it may seem beneficial to use every scan WPScan offers, there are various factors to consider.</p>
<p>First, think about your site’s size and your resources. For smaller sites, running all scans can be overkill and resource-intensive.</p>
<p>You’ll also want to focus on scans that address your site's most likely vulnerabilities. For example, an e-commerce site should prioritize user and payment security over exhaustive file enumeration.</p>
<p>Compliance requirements are also important to take into consideration. If you’re subject to regulations like GDPR, ensure you scan for and address vulnerabilities related to data protection.</p>
<h2 id="heading-how-to-monitor-results-effectively">How to Monitor Results Effectively</h2>
<p>Monitoring WPScan results is important. It helps you fix vulnerabilities, of course, but it also helps you create a system to track changes over time and stay vigilant.</p>
<h3 id="heading-set-up-reporting"><strong>Set Up Reporting</strong></h3>
<p>You can save scan results to files using the <code>--output</code> flag:</p>
<pre><code class="lang-bash">wpscan --url http://example.com --output /path/to/report.txt
</code></pre>
<p>Then review the reports regularly and compare them to previous scans to identify recurring issues or new vulnerabilities.</p>
<h3 id="heading-create-an-action-plan"><strong>Create an Action Plan</strong></h3>
<p>It’s a good idea to categorize vulnerabilities based on severity (for example, critical, moderate, low).</p>
<p>This allows you to address high-severity issues (like outdated plugins with known exploits) immediately. Then you can schedule lower-priority tasks, such as file permission adjustments or minor configuration changes, for routine maintenance.</p>
<h3 id="heading-track-trends-over-time"><strong>Track Trends Over Time</strong></h3>
<p>Use tools like spreadsheets or a project management app (for example, Trello, Asana) to log vulnerabilities, fixes, and follow-up actions.</p>
<p>Make sure you analyze recurring issues to identify patterns, such as frequent plugin vulnerabilities, and consider replacing problematic components.</p>
<h3 id="heading-automate-notifications"><strong>Automate Notifications</strong></h3>
<p>If you schedule scans using cron jobs, set up email alerts or notifications to review results without delay.</p>
<p>Use security plugins with real-time monitoring to notify you of suspicious activities in between WPScan checks.</p>
<h3 id="heading-communicate-with-your-team"><strong>Communicate with Your Team</strong>:</h3>
<p>You’ll want to make sure you share reports with relevant team members, such as developers or site administrators, so everyone is aware of potential vulnerabilities.</p>
<p>It’s also a good idea to establish protocols for immediate action if critical vulnerabilities are discovered.</p>
<p>By choosing scans based on your site’s specific needs and implementing a structured approach to monitoring results, you can ensure WPScan is used effectively. Also, make sure you tailor the tool to your risk profile, track vulnerabilities over time, and integrate its findings into a broader security strategy.</p>
<p>This approach not only improves your site’s security posture but also minimizes resource use and effort while delivering maximum protection.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>WPScan is an invaluable tool for anyone managing a WordPress site. It simplifies the process of identifying vulnerabilities and provides clear, actionable recommendations to strengthen your site’s security.</p>
<p>By integrating WPScan into your workflow and following best practices, you can reduce the risk of attacks and keep your WordPress site safe. Security is a continuous journey, and tools like WPScan make it easier to stay ahead of potential threats.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Generate Financial Press Reviews Using AI ]]>
                </title>
                <description>
                    <![CDATA[ In today’s fast-paced business environment, staying informed about the latest developments in your industry is crucial for making strategic decisions. Companies must know market trends, competitor activities, and potential risks to remain competitive... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-generate-financial-press-reviews-using-ai/</link>
                <guid isPermaLink="false">66c48e95681f6ee20ac8d7a5</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Tue, 20 Aug 2024 12:39:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724059022091/7ce2eba8-46ff-4d08-8e56-afa814cb68cc.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In today’s fast-paced business environment, staying informed about the latest developments in your industry is crucial for making strategic decisions. Companies must know market trends, competitor activities, and potential risks to remain competitive.</p>
<p>One effective way to achieve this is by generating comprehensive financial press reviews based on current news. This is where my Python script comes into play—a tool that automates gathering and analyzing news related to specific queries, enabling businesses to stay up-to-date with their niche and make informed decisions about their next steps. Of course, this script does not replace the work of experts who will then verify and deepen the information found.</p>
<p>This is what we'll cover:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-importance-of-staying-informed">The Importance of Staying Informed</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-overview-of-the-python-script">Overview of the Python Script</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-the-script-works">How the Script Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-1-how-to-set-up-the-environment">1. How to Set Up the Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-how-to-fetch-relevant-news">2. How to Fetch Relevant News</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-how-to-prepare-the-prompt-for-ai-analysis">3. How to Prepare the Prompt for AI Analysis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-how-to-generate-the-press-review">4. How to Generate the Press Review</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-how-to-save-the-report">5. How to Save the Report</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-error-handling-and-logging">Error Handling and Logging</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-the-importance-of-staying-informed"><strong>The Importance of Staying Informed</strong></h2>
<p>For any business, being informed about the latest news in their industry is more than just a good practice. It's a necessity. Key news events can impact markets, influence consumer behavior, and affect supply chains.</p>
<p>By regularly monitoring relevant news, businesses can:</p>
<ul>
<li><p><strong>Identify Emerging Trends:</strong> Spotting trends early can give a business a competitive edge, allowing it to adapt and capitalize on new opportunities.</p>
</li>
<li><p><strong>Monitor Competitors:</strong> Understanding what competitors are doing helps refine strategies and stay ahead in the market.</p>
</li>
<li><p><strong>Mitigate Risks:</strong> By staying informed about potential risks, such as regulatory changes or economic downturns, businesses can proactively adjust their operations to minimize impact.</p>
</li>
<li><p><strong>Plan Strategic Moves:</strong> With a clear understanding of the market landscape, businesses can plan their next steps with greater confidence.</p>
</li>
</ul>
<p>This Python script automates this process, allowing businesses to generate detailed financial press reviews based on specific queries, helping them to understand the market better and plan their next moves effectively.</p>
<h2 id="heading-overview-of-the-python-script">Overview of the Python Script</h2>
<p>This Python script is designed to fetch news articles from the web, analyze them using a large language model (LLM), and generate a structured press review that businesses can use to inform their strategies. The script is built using Python, leveraging two powerful libraries:</p>
<ol>
<li><p><strong>Requests Library</strong>: This is used to make HTTP requests to the News API, retrieving news articles based on the specified query.</p>
</li>
<li><p><strong>Anthropic Library</strong>: This library is used to interact with the Claude AI model, which processes the news data and generates a comprehensive analysis.</p>
</li>
</ol>
<p>The generated press reviews are then saved in a text file, which businesses can review at their convenience.</p>
<h2 id="heading-how-the-script-works">How the Script Works</h2>
<p>Let’s break down how the script operates, step by step:</p>
<h3 id="heading-1-how-to-set-up-the-environment">1. How to Set Up the Environment</h3>
<p>Before running the script, ensure that you have Python installed on your system. Additionally, you will need to install the necessary Python libraries:</p>
<pre><code class="lang-python">pip install requests anthropic
</code></pre>
<h3 id="heading-2-how-to-fetch-relevant-news">2. How to Fetch Relevant News</h3>
<p>The script starts by declaring the <code>generate_report</code> function. Inside the function, I made a GET request to the News API, using the <code>requests</code> library to retrieve the latest news articles related to a specific query. Here’s the relevant code snippet:</p>
<pre><code class="lang-python">response = requests.get(<span class="hljs-string">'https://newsapi.org/v2/everything?q='</span> + query + <span class="hljs-string">'&amp;apiKey=YOUR_API_KEY'</span>)
response_data = response.json()
</code></pre>
<p>In this part of the script:</p>
<ul>
<li><p><code>query</code>: This is the keyword or phrase related to the niche or topic you want to monitor. For example, a company might use the query <code>"finance"</code> to fetch news related to the finance industry.</p>
</li>
<li><p><code>response_data</code>: The news data is fetched in JSON format, which is then parsed into a Python dictionary for further processing.</p>
</li>
</ul>
<h3 id="heading-3-how-to-prepare-the-prompt-for-ai-analysis">3. How to Prepare the Prompt for AI Analysis</h3>
<p>Once the news data is retrieved, the script prepares a prompt to feed into the Claude AI model. The prompt is designed to instruct the model to generate a detailed press review focusing on the impact of the news on financial markets and specific industries. Here’s how the prompt is constructed:</p>
<pre><code class="lang-python">prompt = (
    <span class="hljs-string">"You are a senior financial journalist tasked with writing a comprehensive press review. "</span>
    <span class="hljs-string">"Focus on the key news provided and analyze their potential impact on the financial markets, "</span>
    <span class="hljs-string">"specific industries, or relevant companies. Ensure the press review is structured and concise. "</span>
    <span class="hljs-string">"Start the paragraph with the sentence 'This is the press review about "</span> + query + <span class="hljs-string">"'. "</span>
    <span class="hljs-string">"You'll find the key news in the following json file: "</span> + response_data_to_str
)
</code></pre>
<p>The prompt includes:</p>
<ul>
<li><p><strong>Role Specification</strong>: The AI is instructed to act as a senior financial journalist.</p>
</li>
<li><p><strong>Task Description</strong>: The AI is asked to analyze the news and its impact, ensuring the output is structured and concise.</p>
</li>
<li><p><strong>News Data</strong>: The retrieved news articles are passed to the AI in JSON format, providing the context needed for analysis.</p>
</li>
</ul>
<h3 id="heading-4-how-to-generate-the-press-review">4. How to Generate the Press Review</h3>
<p>With the prompt ready, the script interacts with the Anthropic Claude AI model to generate the press review. The <code>anthropic</code> library is used for this interaction:</p>
<pre><code class="lang-python">message = client.messages.create(
    model=<span class="hljs-string">"claude-3-5-sonnet-20240620"</span>,
    max_tokens=<span class="hljs-number">1000</span>,
    temperature=<span class="hljs-number">0</span>,
    system=<span class="hljs-string">"You are a senior financial journalist. Provide thorough insightful financial press review and advice. Use technical language where appropriate, and consider the broader economic context in your responses."</span>,
    messages=[
        {
            <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>,
            <span class="hljs-string">"content"</span>: [
                {
                    <span class="hljs-string">"type"</span>: <span class="hljs-string">"text"</span>,
                    <span class="hljs-string">"text"</span>: prompt
                }
            ]
        }
    ]
)
</code></pre>
<p>In this part of the script:</p>
<ul>
<li><p><code>client.messages.create</code>: This method sends the prompt to the AI model and retrieves the generated text.</p>
</li>
<li><p><code>plain_text</code>: The resulting press review is stored as plain text, ready to be saved or further processed.</p>
</li>
</ul>
<h3 id="heading-5-how-to-save-the-report">5. How to Save the Report</h3>
<p>Finally, the generated press review is saved to a text file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">with</span> open(<span class="hljs-string">"report.txt"</span>, <span class="hljs-string">"a"</span>) <span class="hljs-keyword">as</span> file:
    file.write(plain_text + <span class="hljs-string">"\n"</span>)
</code></pre>
<p>This ensures that each generated report is appended to the <strong>report.txt</strong> file, making it easy to access and review multiple reports over time.</p>
<h3 id="heading-error-handling-and-logging">Error Handling and Logging</h3>
<p>Robust error handling is crucial to ensure the application runs smoothly. The script includes basic error handling using <code>try-except</code> blocks to catch and log any errors that occur during execution:</p>
<pre><code class="lang-python"><span class="hljs-keyword">except</span> requests.exceptions.RequestException <span class="hljs-keyword">as</span> e:
    logging.error(<span class="hljs-string">f"An error occurred during the HTTP request: <span class="hljs-subst">{e}</span>"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    logging.error(<span class="hljs-string">f"An unexpected error occurred: <span class="hljs-subst">{e}</span>"</span>)
</code></pre>
<p>Errors are logged in an <strong>error.log</strong> file, which helps to fix issues without interrupting the main functionality of the script.</p>
<p>Don't forget to call the function, passing the topic you want information about as a parameter:</p>
<pre><code class="lang-python">generate_report(<span class="hljs-string">"finance"</span>)
</code></pre>
<p>And here's the full code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> anthropic
<span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Set up logging to capture errors in a file named "error.log"</span>
logging.basicConfig(filename=<span class="hljs-string">"error.log"</span>, level=logging.ERROR)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_report</span>(<span class="hljs-params">query</span>):</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Step 1: Make a GET request to the news API with the given query</span>
        response = requests.get(<span class="hljs-string">'https://newsapi.org/v2/everything?q='</span> + query + <span class="hljs-string">'&amp;apiKey=&lt;YOUR_API_KEY&gt;'</span>)

        <span class="hljs-comment"># Step 2: Parse the JSON response from the API into a Python dictionary</span>
        response_data = response.json()

        <span class="hljs-comment"># Convert the JSON data to a string format for use in the prompt</span>
        response_data_to_str = str(response_data)

        <span class="hljs-comment"># Step 3: Initialize the Anthropic client</span>
        client = anthropic.Anthropic()

        <span class="hljs-comment"># Step 4: Create a prompt for the AI model to generate a financial press review</span>
        prompt = (
            <span class="hljs-string">"You are a senior financial journalist tasked with writing a comprehensive press review. "</span>
            <span class="hljs-string">"Focus on the key news provided and analyze their potential impact on the financial markets, "</span>
            <span class="hljs-string">"specific industries, or relevant companies. Ensure the press review is structured, and concise. "</span>
            <span class="hljs-string">"Start the paragraph with the sentence 'This is the press review about "</span> + query + <span class="hljs-string">"'. "</span>
            <span class="hljs-string">"You'll find the key news in the following json file: "</span> + response_data_to_str
        )

        <span class="hljs-comment"># Step 5: Use the prompt to create a message with the AI model</span>
        message = client.messages.create(
            model=<span class="hljs-string">"claude-3-5-sonnet-20240620"</span>,
            max_tokens=<span class="hljs-number">1000</span>,
            temperature=<span class="hljs-number">0</span>,
            system=(
                <span class="hljs-string">"You are a senior financial journalist. Provide thorough insightful financial press review and advice. "</span>
                <span class="hljs-string">"Use technical language where appropriate, and consider the broader economic context in your responses."</span>
            ),
            messages=[
                {
                    <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>,
                    <span class="hljs-string">"content"</span>: [
                        {
                            <span class="hljs-string">"type"</span>: <span class="hljs-string">"text"</span>,
                            <span class="hljs-string">"text"</span>: prompt
                        }
                    ]
                }
            ]
        )

        <span class="hljs-comment"># Step 6: Extract the generated text from the message response</span>
        plain_text = message.content[<span class="hljs-number">0</span>].text

        <span class="hljs-comment"># Step 7: Append the generated report to a file named "report.txt"</span>
        <span class="hljs-keyword">with</span> open(<span class="hljs-string">"report.txt"</span>, <span class="hljs-string">"a"</span>) <span class="hljs-keyword">as</span> file:
            file.write(plain_text + <span class="hljs-string">"\n"</span>)

    <span class="hljs-keyword">except</span> requests.exceptions.RequestException <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># Log any HTTP request errors to "error.log"</span>
        logging.error(<span class="hljs-string">f"An error occurred during the HTTP request: <span class="hljs-subst">{e}</span>"</span>)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># Log any unexpected errors to "error.log"</span>
        logging.error(<span class="hljs-string">f"An unexpected error occurred: <span class="hljs-subst">{e}</span>"</span>)

<span class="hljs-comment"># Generate reports for the needed queries</span>
generate_report(<span class="hljs-string">"finance"</span>)
</code></pre>
<p>After running the script, you should get the <strong>report.txt</strong> file looking like this:</p>
<pre><code class="lang-plaintext">This is the press review about finance:

The financial markets are digesting several key developments this week:

1. Economic Data: The latest jobs report showed unemployment increased slightly, sending markets into a tailspin initially. However, experts caution against overreacting, noting the economy is not "falling off a cliff." The Federal Reserve is getting closer to cutting interest rates, with investors betting the first cut could come as soon as September if inflation continues moderating.

2. Corporate Earnings: Company XXX reported disappointing Q2 earnings, with losses more than tripling to $1.4 billion amid increased scrutiny of its safety and quality control. The Company YYY also named a new CEO who received early praise from key customers. Meanwhile, Company warned of slowing growth and weakening U.S. demand in its Q2 report.

3. Banking &amp; Fintech: Company ZZZ has become Europe's most valuable private tech company at a $45 billion valuation following an employee share sale. This intensifies the neobank challenge to traditional finance. The company also recently obtained its long-awaited UK banking license.

4. Regulatory Developments: The Central Bank is considering creating a strategic Bitcoin reserve, to be partly financed by revaluing gold certificates held. This represents a potential major shift in cryptocurrency policy.

5. Personal Finance: Experts continue to warn about common money mistakes, even among financially savvy individuals. These include waiting too long to start investing and not properly planning for retirement.

The overall market sentiment remains cautious amid mixed economic signals and geopolitical tensions. Investors are closely watching central bank policies and corporate earnings for further direction.
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In a business environment where staying informed is key to success, this Python script offers an automated solution to generate financial press reviews based on the latest news. By leveraging AI, businesses can quickly gain insights into market trends, monitor competitors, and make informed strategic decisions. While the script is already functional and useful, with further enhancements, it can evolve into a powerful tool for business intelligence, helping companies stay ahead in their industry.</p>
<p>By automating the process of news analysis, this script not only saves time but also provides a structured approach to understanding the ever-changing business landscape, empowering companies to take the next steps with confidence.</p>
<p>It is important to remember that this is a tool to support analysts who'll have to verify and evaluate the information available in the report.</p>
<p>If you liked this post, please star my <a target="_blank" href="https://github.com/mventuri/ai-powered-press-review">repo</a> here, can't wait to approve your PR!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Overcome Impostor Syndrome as a Developer ]]>
                </title>
                <description>
                    <![CDATA[ Impostor syndrome is a pervasive feeling of self-doubt and inadequacy that makes you believe you are a fraud despite your achievements and skills.  For new developers – and sometimes even seasoned professionals – this phenomenon can be particularly c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/overcome-impostor-syndrome-as-a-developer/</link>
                <guid isPermaLink="false">66bdff6c59aab25c721c070e</guid>
                
                    <category>
                        <![CDATA[ Imposter syndrome ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Fri, 26 Jul 2024 14:23:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/man-3483205_1280-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Impostor syndrome is a pervasive feeling of self-doubt and inadequacy that makes you believe you are a fraud despite your achievements and skills. </p>
<p>For new developers – and sometimes even seasoned professionals – this phenomenon can be particularly challenging as you navigate a fast-paced and ever-evolving industry. </p>
<p>But it's possible to overcome these feelings by building a strong support network, learning to accept compliments, and fostering a growth mindset. </p>
<p>In this guide, we'll go through these strategies with a positive attitude, aiming to help you embrace your true self and step into your power confidently.</p>
<h2 id="heading-my-story-from-marketing-and-sales-to-tech">My Story: From Marketing and Sales to Tech</h2>
<p>Before diving into the strategies, I want to share a bit of my journey. A while ago, I started my professional career in marketing and sales, a field quite different from tech. </p>
<p>After spending a few years in the job market, I decided to switch to tech, driven by my passion for technology and innovation. </p>
<p>The transition was not easy. There were countless moments when I felt like an impostor, doubting my skills and wondering if I had made the right choice. But through perseverance and the strategies I’m about to share, I learned to manage and eventually overcome these feelings.</p>
<p>This personal experience has deeply shaped my understanding of impostor syndrome and I want to share it with you. I hope it will help you face any imposter syndrome feelings you have and get the most from your career.</p>
<h2 id="heading-the-power-of-sharing-in-the-tech-world">The Power of Sharing in the Tech World</h2>
<p>As a new developer, the tech industry can often seem intimidating and competitive, which can increase feelings of impostor syndrome. One of the most effective ways to combat these feelings is to talk about them. Sharing your experiences and feelings with trusted colleagues or friends within the industry can provide immediate relief and validation.</p>
<p>Start by choosing the right people to trust: those who are supportive, empathetic, and likely to understand the unique pressures of the tech world. You may find that many of them have experienced similar thoughts and emotions. Knowing you are not alone can be incredibly comforting and empowering.</p>
<p>When you vocalize your self-doubts, you take the first step toward pulling down the isolation that impostor syndrome often brings. Your peers can offer new perspectives and constructive feedback, helping you see your achievements and potential more clearly. This collective support fosters a culture of openness and continuous learning, which is essential in the dynamic field of tech.</p>
<p>Turn this weakness into a strength for you and your team: opening up about your struggles with impostor syndrome not only helps you but also contributes to a more empathetic and supportive workplace for everyone.</p>
<h2 id="heading-mentors-can-help">Mentors Can Help</h2>
<p>A robust support network is a crucial asset in overcoming impostor syndrome, especially in the tech industry where collaboration and innovation are key. So it can help to create relationships with mentors who inspire and guide you. </p>
<p>In the tech world, mentors can offer valuable advice on career progression, skill development, and navigating workplace challenges. They can share their own experiences with impostor syndrome, providing a sense of relatability and encouragement. And they can help you set realistic goals and celebrate your progress, reinforcing your sense of competence and achievement.</p>
<p>Finding a mentor can be particularly impactful. Start by identifying individuals who inspire you—these could be senior colleagues, industry leaders, or even peers with specific expertise. </p>
<p>Look for mentors who are not only knowledgeable but also approachable and willing to share their experiences. You can find mentors through networking events, online communities, professional organizations, or social networks.</p>
<p>When you find a potential mentor, approach them respectfully and express your admiration for their work and your desire to learn. It’s important to be clear about what you hope to gain from the mentorship and be open to feedback. </p>
<p>Being a good mentee involves being proactive, respectful of your mentor’s time, and showing appreciation for their guidance. Keep the lines of communication open and seek their advice on specific issues or general career guidance. </p>
<p>Remember, mentorship is a two-way street: as you grow, find ways to give back, whether by offering your insights or mentoring others.</p>
<p>Maintaining and cultivating the relationship requires consistent effort. Regularly update your mentor on your progress, seek their advice on new challenges, and show gratitude for their support. This relationship can give you the confidence and knowledge to navigate your career path.</p>
<h2 id="heading-share-your-path-with-other-people">Share Your Path with Other People</h2>
<p>Join professional groups, online forums, or tech meetups where you can share your experiences and learn from others. Engaging with a community of like-minded individuals can provide a sense of belonging and mutual support. Platforms like GitHub, Stack Overflow, or local coding bootcamps can be great places to find this community.</p>
<p>When considering what to share, think about your career journey, the challenges you’ve faced, and your successes, no matter how small they may seem. Being open about your insecurities and the steps you’ve taken to overcome them can resonate with others who may feel similarly. </p>
<p>Just remember that it’s essential to find a balance between seeking support and being a supportive member of your community. Engage actively in discussions, offer constructive feedback, and encourage others to share their experiences as well. Make people feel comfortable and not judged while talking about their experiences. They'll do the same with you.</p>
<p>I've given talks at local tech meetups many times, it was always nerve-wracking but incredibly rewarding. Preparing for and delivering talks helped me consolidate my knowledge and communicate my passion for technology. It also provided a platform for networking and receiving positive feedback, which boosted my confidence.</p>
<p>Building a support network takes time and effort, but the benefits are immeasurable. When you know that others believe in you, it becomes easier to believe in yourself.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-50.png" alt="Image" width="600" height="400" loading="lazy">
<em>Me having a talk at a local meetup</em></p>
<h2 id="heading-accept-positive-feedback">Accept Positive Feedback</h2>
<p>Instead of deflecting praise, it’s essential to practice accepting it. Learning to embrace positive feedback is a critical step in recognizing your worth and achievements.</p>
<p>When someone compliments you on your coding skills, problem-solving abilities, or a successful project, resist the urge to downplay your accomplishments or attribute them to luck. Instead, just reply with a simple “thank you.” This acknowledgment not only shows appreciation but also helps internalize the positive reinforcement.</p>
<p>Accepting compliments can feel uncomfortable at first, but with practice, it becomes easier. Start by reflecting on the feedback you receive. Consider why the compliment was given and how it aligns with your efforts and skills. Over time, this practice helps to build a more accurate and positive self-perception.</p>
<p>In addition to verbal compliments, pay attention to other forms of positive feedback, such as positive code reviews, successful project completions, or praise from clients and managers. These are tangible reminders of your capabilities and contributions. Keep a journal or a digital folder of these affirmations and revisit them whenever self-doubt creeps in.</p>
<p>Remember, accepting compliments doesn’t mean you’re arrogant. It just means you’re recognizing your hard work and achievements. Embrace the positive feedback as a reflection of your true self.</p>
<h2 id="heading-focus-on-a-growth-mindset-and-dont-fear-mistakes">Focus on a Growth Mindset and Don't Fear Mistakes</h2>
<p>A growth mindset, a concept popularized by psychologist Carol Dweck, is the belief that abilities and intelligence can be developed through effort, learning, and perseverance. Adopting this mindset is a powerful tool in overcoming impostor syndrome, especially in the rapidly changing field of tech.</p>
<p>Instead of being obsessed with the fear of failure or the need for perfection, focus on your growth and development. View challenges as opportunities to learn and improve rather than threats to your competence. Embrace mistakes as part of the learning process: every setback is a step toward mastery.</p>
<p>To cultivate a growth mindset, start by setting realistic and attainable goals. Break down larger tasks into manageable steps, and celebrate your progress along the way. This approach not only makes goals more achievable but also reinforces a sense of accomplishment and progress.</p>
<p>Engage in continuous learning and self-improvement. Seek out new knowledge, skills, and experiences that align with your interests and career aspirations. This commitment to growth helps build confidence and resilience, reducing the impact of impostor syndrome. </p>
<p>You can also enroll in online courses, attend workshops, or participate in hackathons to enhance your skills and stay updated with industry trends.</p>
<p>Surround yourself with people who embody a growth mindset. Their positive attitudes and resilience can inspire and motivate you. Learn from their experiences and apply their strategies to your journey.</p>
<p>Also, don't forget that growth is a continuous process, and everyone’s journey is unique. Be kind to yourself and recognize that it’s okay not to have all the answers. What matters is your willingness to learn and improve.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Overcoming impostor syndrome as a developer is a journey that requires time, effort, and a lot of self-reflection. By talking about your feelings, building a support network, accepting compliments, and focusing on growth, you can gradually diminish self-doubt and embrace your true potential.</p>
<p>Remember, you are not alone in this struggle, and with the right strategies and support, you can overcome impostor syndrome and thrive in the tech industry. Embrace your journey, celebrate your progress, and believe in your ability to grow and succeed.</p>
<p>This article is a result of my own experiences transitioning from sales and marketing to tech. If you ever feel overwhelmed or feel the need for additional support, don't hesitate to talk to a specialist. Seeking professional help can provide personalized strategies to help you navigate and overcome impostor syndrome effectively.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Basic CMS with Google Sheets and React ]]>
                </title>
                <description>
                    <![CDATA[ In today's digital landscape, creating a content management system (CMS) that is both cost-effective and easy to maintain can be difficult, especially if you're operating on a tight budget.  This tutorial will show you a solution that leverages Googl... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-basic-cms-with-google-sheets-and-reactjs/</link>
                <guid isPermaLink="false">66bdff5a0b4523e3b8b99090</guid>
                
                    <category>
                        <![CDATA[ cms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Wed, 06 Mar 2024 17:55:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/--1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In today's digital landscape, creating a content management system (CMS) that is both cost-effective and easy to maintain can be difficult, especially if you're operating on a tight budget. </p>
<p>This tutorial will show you a solution that leverages Google Sheets as a makeshift database and React to build the frontend. This will let you effectively bypass the need for a dedicated server or traditional database system. </p>
<p>This approach not only reduces the overhead costs associated with web development, but also simplifies content updates and management. It's an ideal solution if you're looking to launch your own simple CMS without substantial investment.</p>
<p>This solution is suitable for freelancers at the beginning of their career and for clients who cannot invest much in their website.</p>
<h2 id="heading-why-google-sheets">Why Google Sheets?</h2>
<p>Opting for Google Sheets as the backbone of your CMS comes down to its simplicity, flexibility, and cost-effectiveness.</p>
<p>Traditional web development requires a backend server to process data, a database to store information, and a frontend to display content. But each layer adds complexity and cost. </p>
<p>Google Sheets, on the other hand, acts as a highly accessible and intuitive interface that eliminates the need for a server and a database. It lets your users update content in real-time, much like any CMS, but without the usual setup and maintenance costs. This makes it an excellent choice for individuals, small businesses, or anyone looking to deploy a web application quickly and with minimal expense. </p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>Before diving into the code, ensure you have Node.js and npm installed on your system. These tools will allow us to create a React application and manage its dependencies. </p>
<p>Let's start with Google Sheets now.</p>
<h3 id="heading-step-1-set-up-your-google-sheets">Step 1: Set Up Your Google Sheets</h3>
<ol>
<li>Go to your Google Sheets</li>
<li>Open the sheet you want to use or create a new one</li>
<li>Click on <code>Extensions</code> in the menu</li>
<li>Then click on <code>Apps Script</code></li>
</ol>
<p>In the Apps Script editor, you can write a script to serve as your endpoint. Here's a script that returns the contents of a Google Sheet in JSON format:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">convertRangeToJson</span>(<span class="hljs-params">data</span>) </span>{
  <span class="hljs-keyword">var</span> jsonArray = [];

  <span class="hljs-comment">// Check if data is empty or doesn't contain enough rows for headers and at least one data row</span>
  <span class="hljs-keyword">if</span> (!data || data.length &lt; <span class="hljs-number">2</span>) {
    <span class="hljs-comment">// Return an empty array or a meaningful message as needed</span>
    <span class="hljs-keyword">return</span> jsonArray; <span class="hljs-comment">// or return 'No data available';</span>
  }

  <span class="hljs-keyword">var</span> headers = data[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">1</span>, length = data.length; i &lt; length; i++) {
    <span class="hljs-keyword">var</span> row = data[i];
    <span class="hljs-keyword">var</span> record = {};

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = <span class="hljs-number">0</span>; j &lt; row.length; j++) {
      record[headers[j]] = row[j];
    }

    jsonArray.push(record);
  }

  <span class="hljs-keyword">return</span> jsonArray;
}
</code></pre>
<p>Then:</p>
<ol>
<li>Click <code>File</code> &gt; <code>Save</code>, and give your project a name</li>
<li>Click on <code>Deploy</code> &gt; <code>New deployment</code>.</li>
<li>Click on <code>Select type</code> and choose <code>Web app</code>.</li>
<li>Fill in the details for your deployment. Under <code>Execute as</code>, choose whether the script should run as your account or as the user accessing the web app. Under <code>Who has access</code>, choose who can access your web app.</li>
<li>Click <code>Deploy</code>.</li>
</ol>
<p>You may be asked to authorize the script to access your Google Sheets. Follow the prompts to do so.</p>
<p>After deploying, you'll be given a URL for your web app. This is your API endpoint.</p>
<p>To give you an idea of what you have done so far, this is your sheet structure:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Schermata-2024-03-04-alle-16.49.37.png" alt="Image" width="600" height="400" loading="lazy">
<em>How your sheet should currently look</em></p>
<p>And this is the JSON you get when you call the endpoint:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/postman_I.png" alt="Image" width="600" height="400" loading="lazy">
<em>JSON</em></p>
<h3 id="heading-step-2-create-your-react-app">Step 2: Create Your React App</h3>
<p>With your Google Sheets API ready, it's time to create the React app that will fetch and display this data.</p>
<p>First, go ahead and create a React app. Run the following command in your terminal to create a new React application:</p>
<pre><code class="lang-bash">npx create-react-app google-sheets-cards
<span class="hljs-built_in">cd</span> google-sheets-cards
npm start
</code></pre>
<p>You can also <a target="_blank" href="https://www.freecodecamp.org/news/get-started-with-vite/">use modern build tools like Vite</a> for this purpose, as CRA is no longer the recommended way of building a React app.</p>
<p>Next, create the card component. Inside the <code>src</code> directory, create a file named <code>Card.js</code>. This component will be responsible for displaying each data record:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// src/Card.js</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Card</span>(<span class="hljs-params">{ title, content }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Card;
</code></pre>
<p>Now it's time to fetch and display your data in App.js. Modify the <code>App.js</code> file to include logic for fetching the data from your Google Sheets API and using the Card component to display it:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// src/App.js</span>
<span class="hljs-keyword">import</span> React, { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> Card <span class="hljs-keyword">from</span> <span class="hljs-string">'./Card'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>; <span class="hljs-comment">// Make sure to create some basic styles for the cards in App.css</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [data, setData] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(<span class="hljs-string">'YOUR_ENDPOINT_URL'</span>) <span class="hljs-comment">// Replace with your actual endpoint URL</span>
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
      .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> setData(data))
      .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error fetching data:'</span>, error));
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Data from Google Sheets<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"cards-container"</span>&gt;</span>
        {data.map((item, index) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{item.Title}</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{item.Content}</span> /&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Next, you can style your cards. Go ahead and add the below CSS in <code>App.css</code> for basic card styling:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.card</span> {
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">4px</span> <span class="hljs-number">8px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">display</span>: inline-block;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#f9f9f9</span>;
}

<span class="hljs-selector-class">.cards-container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-wrap</span>: wrap;
  <span class="hljs-attribute">justify-content</span>: center;
}
</code></pre>
<h3 id="heading-step-3-run-your-react-app">Step 3: Run Your React App</h3>
<p>With everything set up, you can now run your React application and see the data from Google Sheets displayed in your browser. To do this, follow these steps:</p>
<p>First, start the React app. In your terminal, navigate to the root directory of your React app if you're not already there. Run the following command to start the development server:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>This command compiles your React application and opens it in your default web browser. You should see a webpage with a title "Data from Google Sheets", and below that, a series of cards, each displaying a title and content fetched from your Google Sheets data. </p>
<p>Here's, in fact, what we get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Schermata-2024-03-04-alle-16.52.22.png" alt="Image" width="600" height="400" loading="lazy">
<em>Data from Google Sheets and Card 1, Card 2, and Card 3 displayed on the screen</em></p>
<p>Now you can view your data. Each card on the page corresponds to a row in your Google Sheets, with the title and content fields displayed as specified in your Card component. If you make any updates to your Google Sheets data, you can refresh the web page to see the changes reflected immediately.</p>
<p>You can deploy your React app to one of the many services you can find online such as Github Actions or Netlify. This is a simple and effective way to host your frontend application for free with significant performance. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations! You've created a dynamic web application that fetches data from a Google Sheet and displays it using React. </p>
<p>This approach offers a flexible and straightforward way to manage your application's content without needing a backend server or database.</p>
<p>Google Sheets serves as an accessible and collaborative platform for managing data, while React allows you to build a responsive and interactive user interface. Together, they provide a powerful combination for creating web applications that can be quickly updated and easily maintained.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the WordPress Command Line Interface – WP-CLI Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ In the world of website development and content management, efficiency and automation are key. The WordPress Command Line Interface – or WP-CLI – is a powerful tool that can help you streamlines tasks and manage WordPress websites more effectively.  ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-wordpress-cli/</link>
                <guid isPermaLink="false">66bdff6a0b4523e3b8b99099</guid>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Fri, 11 Aug 2023 21:37:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/pexels-pixabay-207580.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In the world of website development and content management, efficiency and automation are key. The WordPress Command Line Interface – or WP-CLI – is a powerful tool that can help you streamlines tasks and manage WordPress websites more effectively. </p>
<p>This article provides an overview of WP-CLI, focusing on its capabilities to create, modify, and delete users, as well as handle plugins with ease. This article will show you how WP-CLI can significantly elevate your WordPress management experience.</p>
<h2 id="heading-what-is-wp-cli">What is WP-CLI?</h2>
<p>WP-CLI is a command-line tool designed for managing WordPress installations. It empowers developers, administrators, and site owners to interact with their websites directly from the command line, bypassing the need for manual interventions through the web interface. </p>
<p>It's built on PHP, and offers a wide range of commands that you can execute right from the terminal.</p>
<p>By using WP-CLI, you'll be able to manage your WordPress sites much more efficiently. Let's see a few examples of how WP-CLI commands can simplify your workflow:</p>
<h2 id="heading-wp-cli-commands">WP-CLI Commands</h2>
<h3 id="heading-site-information-retrieval">Site Information Retrieval</h3>
<p>The <code>wp site info</code> command provides a quick overview of your WordPress site's important details, including the site's URL, the number of posts and pages, the active theme, and more. </p>
<p>For instance, by running <code>wp site info</code>, you can promptly gather essential information about your site without navigating through the WordPress admin dashboard.</p>
<h3 id="heading-database-management">Database Management</h3>
<p>WP-CLI allows you to manage your WordPress database seamlessly. Use the <code>wp db export</code> command to create a database export file, ensuring a backup of your site's data. </p>
<p>If you need to import data, the <code>wp db import</code> command facilitates this process. For example, if you have a database backup named <code>backup.sql</code>, executing <code>wp db import backup.sql</code> restores the database to a previous state.</p>
<h3 id="heading-theme-manipulation">Theme Manipulation</h3>
<p>Manipulating themes is extremely efficient with WP-CLI. For example, the <code>wp theme install</code> command lets you install a theme directly from the official WordPress theme repository. To install the "Twenty Twenty-One" theme, you can use the command <code>wp theme install twentytwentyone</code>.</p>
<h3 id="heading-post-and-page-creation">Post and Page Creation</h3>
<p>Generating new content is made easier using WP-CLI. The <code>wp post create</code> and <code>wp post generate</code> commands enable you to create and populate posts and pages with content. </p>
<p>For example, <code>wp post create --post_type=post --post_title="New Post"</code> creates a new post with the specified title.</p>
<p>These examples illustrate the versatility and power of WP-CLI in managing various aspects of your WordPress site. By harnessing its capabilities, you can enhance your efficiency, reduce manual tasks, and gain greater control over your website's management.</p>
<h2 id="heading-how-to-install-wp-cli">How to Install WP-CLI</h2>
<p>Before diving into more features of WP-CLI, let's understand the installation process. </p>
<p>You can install WP-CLI globally on your system, making it accessible from any directory. </p>
<p>To install WP-CLI, make sure you have PHP installed, along with a compatible version of WordPress. Download the Phar archive, place it in a directory reachable through your system's PATH, and you're ready to go. </p>
<p>You can verify the installation by typing <code>wp --info</code> in your terminal. <a target="_blank" href="https://wp-cli.org">Here</a> you can find the doc with the URL to download WP-CLI with a wget.</p>
<h2 id="heading-how-to-manage-users-with-wp-cli">How to Manage Users with WP-CLI</h2>
<p>Managing users is a fundamental task when overseeing a WordPress site. WP-CLI simplifies user management with various commands that make creating, modifying, and deleting users much easier.</p>
<h3 id="heading-how-to-create-users">How to Create Users</h3>
<p>The <code>wp user create</code> command lets you quickly create users directly from the command line. </p>
<p>To illustrate, let's create a new user named "Alice" with the email address "alice@example.com" and the role of editor. Simply enter:</p>
<pre><code>wp user create alice alice@example.com --role=editor
</code></pre><h3 id="heading-how-to-modify-users">How to Modify Users</h3>
<p>WP-CLI also streamlines user modifications. Use the <code>wp user update</code> command to adjust a user's details. </p>
<p>For instance, let's change Alice's display name to "Alice Johnson" using the following command:</p>
<pre><code>wp user update <span class="hljs-number">123</span> --display_name=<span class="hljs-string">"Alice Johnson"</span>
</code></pre><p>In this example, "123" is Alice's ID.</p>
<h3 id="heading-how-to-delete-users">How to Delete Users</h3>
<p>When user accounts become obsolete or require removal for security reasons, WP-CLI simplifies the process. </p>
<p>To delete a user, use the <code>wp user delete</code> command. To remove Alice's account, simply execute:</p>
<pre><code>wp user <span class="hljs-keyword">delete</span> <span class="hljs-number">123</span> --reassign=<span class="hljs-number">567</span>
</code></pre><p>In this case, again "123" is Alice's ID and "567" is the ID of the user you want to assign Alice's content to (for example posts, pages, and so on).</p>
<h2 id="heading-how-to-manage-plugins-with-wp-cli">How to Manage Plugins with WP-CLI</h2>
<p>Plugins play a crucial role in enhancing WordPress websites. WP-CLI extends its capabilities to manage plugins, making tasks such as installation, activation, deactivation, and updates incredibly efficient.</p>
<h3 id="heading-how-to-install-plugins">How to Install Plugins</h3>
<p>Use the <code>wp plugin install</code> command to seamlessly install plugins from the WordPress repository. </p>
<p>For instance, let's install the "Akismet" anti-spam plugin:</p>
<pre><code>wp plugin install akismet
</code></pre><h3 id="heading-how-to-activate-and-deactivate-plugins">How to Activate and Deactivate Plugins</h3>
<p>Managing plugin status is quite easy with WP-CLI. Activate or deactivate plugins using the <code>wp plugin activate</code> and <code>wp plugin deactivate</code> commands respectively. </p>
<p>To activate the "Akismet" plugin, type the following command:</p>
<pre><code>wp plugin activate akismet
</code></pre><h3 id="heading-how-to-update-plugins">How to Update Plugins</h3>
<p>Keeping plugins up to date is vital for security and performance. The <code>wp plugin update</code> command makes updates hassle-free. </p>
<p>To update all installed plugins, simply run:</p>
<pre><code>wp plugin update --all
</code></pre><h3 id="heading-how-to-list-installed-plugins">How to List Installed Plugins</h3>
<p>WP-CLI offers an overview of installed plugins with the <code>wp plugin list</code> command. This provides a quick snapshot of each plugin's status, version, and available updates:</p>
<pre><code>wp plugin list
</code></pre><h2 id="heading-conclusion">Conclusion</h2>
<p>WP-CLI is an invaluable asset in the world of WordPress management. Its extensive command set helps you manage users and plugins – and much more – with remarkable ease. This saves you time and minimizes manual interventions. </p>
<p>By harnessing the power of WP-CLI, administrators and developers can streamline workflows, improve security, and ensure their WordPress websites operate seamlessly. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Cookies to Customize a Web Page's Content ]]>
                </title>
                <description>
                    <![CDATA[ If you develop websites or web apps, someday you’ll have to deal with cookies. That’s why I decided to write this tutorial on how to use cookies to customize a web page according to the previous web page the user comes from.  I wrote this tutorial us... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-cookies-to-customize-web-page-content/</link>
                <guid isPermaLink="false">66bdff670b4523e3b8b99097</guid>
                
                    <category>
                        <![CDATA[ cookies ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Tue, 30 May 2023 22:04:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/vyshnavi-bisani-z8kriatLFdA-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you develop websites or web apps, someday you’ll have to deal with cookies. That’s why I decided to write this tutorial on how to use cookies to customize a web page according to the previous web page the user comes from. </p>
<p>I wrote this tutorial using PHP, but you can set cookies also by using other popular programming languages such as Java, Python, and others.</p>
<p>Before going deep with the details, let's go through a brief introduction and some recommendations.</p>
<h2 id="heading-what-are-cookies">What are Cookies?</h2>
<p>Cookies play a vital role in how websites function. They can also enhance a user's browsing experience. </p>
<p>In simple terms, a cookie is a small file that websites store on a user's computer or device while they navigate through various web pages. These files contain data that are utilized by websites to remember certain information and settings, ultimately improving the performance and customization of the website for the user.</p>
<p>When a user visits a website, the site's server sends a cookie to the user's browser, which then stores it on their computer or device. The next time the user visits the same website, the browser sends the stored cookie back to the server. This enables the website to recognize the user, remember their preferences, and provide personalized content.</p>
<p>Cookies serve various functions, such as remembering login information, language preferences, and shopping cart contents. </p>
<p>For example, when you visit an online shopping website and add items to your cart, cookies help in retaining those items even if you navigate to other pages. Cookies can also remember your login details, so you don't have to re-enter them every time you visit a website.</p>
<p>Cookies can also be used for tracking user behavior and gathering information about website usage. This information is often anonymous and helps website owners analyze traffic patterns, identify popular pages, and improve their website's design and functionality. </p>
<p>Advertisers also use cookies to deliver targeted advertisements based on users' browsing habits and interests. This enables them to show relevant ads that are more likely to be of interest to the user.</p>
<h3 id="heading-a-note-about-cookies-and-user-privacy">A Note about Cookies and User Privacy</h3>
<p>Cookies are designed to be a tool for enhancing user experience and improving website functionality. But concerns about privacy and security have led to the development of regulations and guidelines for using cookies. Many websites now provide cookie consent notices, allowing users to choose whether they want to accept or reject cookies.</p>
<p>Over the past few decades, the use of cookies has been subject to extensive discussion by regulatory bodies, emphasizing the significance of ensuring users are fully informed about their implementation. </p>
<p>Progress has been made in this direction, including the introduction of the General Data Protection Regulation (GDPR) by the European Union (EU). For more comprehensive information, you can get detailed insights from the official web portal of the EU. </p>
<p>If you are considering the integration of cookies into your application, I highly recommend discussing the implications with the legal department of your company or consulting with legal professionals who possess expertise in this domain. By doing so, you can ensure compliance with the legal and regulatory frameworks governing the use of cookies, safeguarding user privacy in the process.</p>
<h2 id="heading-lets-get-started">Let’s Get Started</h2>
<p>Let’s assume I’m running a pet lovers e-commerce site, and I’m implementing a content marketing strategy to attract new customers. </p>
<p>I create one informational page for cats lovers and another one for dogs lovers. Both pages point to the same page where I give further details about having pets. </p>
<p>I want this page to show specific (targeted) ads according to the page the user comes from: if they visited the page about cats, I want them to see ads about cat food. If they visited the one about dogs, I want them to see ads about dog food.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-124.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-lets-code">Let’s Code</h2>
<p>I’m building three pages:</p>
<ol>
<li>Cat's lovers page: mainPageCat.php (screenshot below)</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-125.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="2">
<li>Dog's lover page: mainPageDog.php</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-126.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="3">
<li>The target page: cookieTest.php</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-127.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>While building pages 1 and 2, I set cookies using the PHP <code>setcookie()</code> function. For the page about cats, I pass the function these parameters:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
$cookie_name = <span class="hljs-string">"cat"</span>;
$cookie_value = <span class="hljs-string">"catFoodAds"</span>;
setcookie($cookie_name, $cookie_value, time() + (<span class="hljs-number">86400</span> * <span class="hljs-number">30</span>), <span class="hljs-string">"/"</span>); <span class="hljs-comment">// 86400 = 1 day</span>
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>For the page about dogs, I pass these parameters:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
$cookie_name = <span class="hljs-string">"dog"</span>;
$cookie_value = <span class="hljs-string">"dogFoodAds"</span>;
setcookie($cookie_name, $cookie_value, time() + (<span class="hljs-number">86400</span> * <span class="hljs-number">30</span>), <span class="hljs-string">"/"</span>); <span class="hljs-comment">// 86400 = 1 day</span>
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>For the “further information” page I add some logic. If the cat cookie is stored, I add a CSS class to the dog ads card to hide it. I do the same with the cat ads card if the cookie stored is the one from the dog page.</p>
<pre><code class="lang-php">&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">row</span>"&gt;
            &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">col</span>-<span class="hljs-title">md</span>-3"&gt;
                &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span> &lt;?<span class="hljs-title">php</span> <span class="hljs-title">if</span>(<span class="hljs-title">isset</span>($<span class="hljs-title">_COOKIE</span>['<span class="hljs-title">dog</span>'])) <span class="hljs-title">echo</span> ' <span class="hljs-title">cookieClass</span>'; ?&gt;" <span class="hljs-title">style</span>="<span class="hljs-title">width</span>: 18<span class="hljs-title">rem</span>;"&gt;
                    &lt;<span class="hljs-title">img</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">img</span>-<span class="hljs-title">top</span>" <span class="hljs-title">src</span>="<span class="hljs-title">https</span>://<span class="hljs-title">images</span>.<span class="hljs-title">unsplash</span>.<span class="hljs-title">com</span>/<span class="hljs-title">photo</span>-1518791841217-8<span class="hljs-title">f162f1e1131</span>?<span class="hljs-title">ixlib</span>=<span class="hljs-title">rb</span>-1.2.1&amp;<span class="hljs-title">ixid</span>=<span class="hljs-title">MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDl8fHxlbnwwfHx8fA</span>%3<span class="hljs-title">D</span>%3<span class="hljs-title">D</span>&amp;<span class="hljs-title">w</span>=1000&amp;<span class="hljs-title">q</span>=80" <span class="hljs-title">alt</span>="<span class="hljs-title">Card</span> <span class="hljs-title">image</span> <span class="hljs-title">cap</span>"&gt;
                    &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">body</span>"&gt;
                        &lt;<span class="hljs-title">h5</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">title</span>"&gt;<span class="hljs-title">Buy</span> <span class="hljs-title">Food</span> <span class="hljs-title">for</span> <span class="hljs-title">Cats</span>&lt;/<span class="hljs-title">h5</span>&gt;
                        &lt;<span class="hljs-title">h6</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">subtitle</span> <span class="hljs-title">mb</span>-2 <span class="hljs-title">text</span>-<span class="hljs-title">muted</span>"&gt;<span class="hljs-title">Excellent</span> <span class="hljs-title">Food</span>&lt;/<span class="hljs-title">h6</span>&gt;
                        &lt;<span class="hljs-title">p</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">text</span>"&gt;<span class="hljs-title">Don</span>'<span class="hljs-title">t</span> <span class="hljs-title">know</span> <span class="hljs-title">what</span> <span class="hljs-title">else</span> <span class="hljs-title">I</span> <span class="hljs-title">could</span> <span class="hljs-title">say</span> <span class="hljs-title">about</span> <span class="hljs-title">cat</span> <span class="hljs-title">food</span>.&lt;/<span class="hljs-title">p</span>&gt;
                        &lt;<span class="hljs-title">a</span> <span class="hljs-title">href</span>="#" <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">link</span>"&gt;<span class="hljs-title">Buy</span>&lt;/<span class="hljs-title">a</span>&gt;
                    &lt;/<span class="hljs-title">div</span>&gt;
                &lt;/<span class="hljs-title">div</span>&gt;
            &lt;/<span class="hljs-title">div</span>&gt;
            &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">col</span>-<span class="hljs-title">md</span>-3"&gt;
                &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span> <span class="hljs-title">ml</span>-5 &lt;?<span class="hljs-title">php</span> <span class="hljs-title">if</span>(<span class="hljs-title">isset</span>($<span class="hljs-title">_COOKIE</span>['<span class="hljs-title">cat</span>'])) <span class="hljs-title">echo</span> ' <span class="hljs-title">cookieClass</span>'; ?&gt;" <span class="hljs-title">style</span>="<span class="hljs-title">width</span>: 18<span class="hljs-title">rem</span>;"&gt;
                    &lt;<span class="hljs-title">img</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">img</span>-<span class="hljs-title">top</span>" <span class="hljs-title">src</span>="<span class="hljs-title">https</span>://<span class="hljs-title">images</span>.<span class="hljs-title">unsplash</span>.<span class="hljs-title">com</span>/<span class="hljs-title">photo</span>-1561037404-61<span class="hljs-title">cd46aa615b</span>?<span class="hljs-title">ixlib</span>=<span class="hljs-title">rb</span>-1.2.1&amp;<span class="hljs-title">ixid</span>=<span class="hljs-title">MnwxMjA3fDB8MHxjb2xsZWN0aW9uLXBhZ2V8MXwxMTU1Mjc2N3x8ZW58MHx8fHw</span>%3<span class="hljs-title">D</span>&amp;<span class="hljs-title">w</span>=1000&amp;<span class="hljs-title">q</span>=80" <span class="hljs-title">alt</span>="<span class="hljs-title">Card</span> <span class="hljs-title">image</span> <span class="hljs-title">cap</span>"&gt;    
                    &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">body</span>"&gt;
                        &lt;<span class="hljs-title">h5</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">title</span>"&gt;<span class="hljs-title">Buy</span> <span class="hljs-title">Food</span> <span class="hljs-title">for</span> <span class="hljs-title">Dogs</span>&lt;/<span class="hljs-title">h5</span>&gt;
                        &lt;<span class="hljs-title">h6</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">subtitle</span> <span class="hljs-title">mb</span>-2 <span class="hljs-title">text</span>-<span class="hljs-title">muted</span>"&gt;<span class="hljs-title">Excellent</span> <span class="hljs-title">Food</span>&lt;/<span class="hljs-title">h6</span>&gt;
                        &lt;<span class="hljs-title">p</span> <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">text</span>"&gt;<span class="hljs-title">Don</span>'<span class="hljs-title">t</span> <span class="hljs-title">know</span> <span class="hljs-title">what</span> <span class="hljs-title">else</span> <span class="hljs-title">I</span> <span class="hljs-title">could</span> <span class="hljs-title">say</span> <span class="hljs-title">about</span> <span class="hljs-title">dog</span> <span class="hljs-title">food</span>.&lt;/<span class="hljs-title">p</span>&gt;
                        &lt;<span class="hljs-title">a</span> <span class="hljs-title">href</span>="#" <span class="hljs-title">class</span>="<span class="hljs-title">card</span>-<span class="hljs-title">link</span>"&gt;<span class="hljs-title">Buy</span>&lt;/<span class="hljs-title">a</span>&gt;
                    &lt;/<span class="hljs-title">div</span>&gt;
                &lt;/<span class="hljs-title">div</span>&gt;
            &lt;/<span class="hljs-title">div</span>&gt;
        &lt;/<span class="hljs-title">div</span>&gt;</span>
</code></pre>
<h2 id="heading-lets-see-how-it-works">Let’s see how it works</h2>
<p>I test the flow as a user who wants to visit the page about cats. I type in my browser URL bar:</p>
<p>https:///mainPageCat.php</p>
<p>As you can see, I see the page I built and the cookie is stored in my browser</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-128.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If I click the call to action (blue button), I see the further details page with cat food ads only:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-129.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let’s now test the flow for dog lovers. First I delete cookies from my browser (or use the incognito mode) and then I visit this URL:</p>
<p>https:///mainPageDog.php</p>
<p>This is what I see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-130.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As we can see again, I see the page I built and the cookie is stored in my browser</p>
<p>If I click the call to action (blue button), I see the further details page with dog food ads only.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-131.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Done! This is a simple and quick example of how you can use cookies to customize the content of your web pages. You can find the Github repo <a target="_blank" href="https://github.com/mventuri/cookiesPhp">here</a> with the full code.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Automate Your Business Strategy with Python and APIs ]]>
                </title>
                <description>
                    <![CDATA[ When you work in e-commerce operations, you'll have to perform many tasks daily to implement your company's business strategies.  But these often repetitive tasks can be time-consuming and leave room for errors. Some of these errors can cost your com... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-automate-e-commerce-operations-with-python/</link>
                <guid isPermaLink="false">66bdff5399b6d009225ad10a</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Tue, 06 Dec 2022 18:11:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/cover-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you work in e-commerce operations, you'll have to perform many tasks daily to implement your company's business strategies. </p>
<p>But these often repetitive tasks can be time-consuming and leave room for errors. Some of these errors can cost your company money, reputation, and time. </p>
<p>Luckily, Python and APIs can help you prevent such mistakes as well as save time and money. Your team can then invest that time and money in other activities like developing new strategies or methods to be more efficient.</p>
<h2 id="heading-you-may-have-heard-of-apis-before">You May Have Heard of APIs Before</h2>
<p>If you work in the tech industry, you've likely heard of APIs at least once in your life. If you have never heard of it, don't worry – I'll give you a brief explanation here.</p>
<p><strong>"API"</strong> stands for <strong>Application Programming Interface</strong>. They help services or applications communicate with each other. </p>
<p>Just to give you an example, if you are a frontend developer you'll be asked to call a backend service via its API to retrieve the information you want to print on the screen. This is how the backend and the frontend send and receive data. When you call an API you get a JSON or XML file as a response.</p>
<p>APIs can be also <strong>"RESTful"</strong>, which stands for <strong>Representational State Transfer</strong>. Rest is a set of architectural constraints that help you design efficient and safe APIs. </p>
<p>If you'd like to know more about REST APIs, I recommend that you <a target="_blank" href="https://www.freecodecamp.org/news/what-is-rest-rest-api-definition-for-beginners/">read this article by Ihechikara</a> here on freeCodeCamp's publication.</p>
<h2 id="heading-how-can-apis-help-you-get-work-done">How Can APIs Help You Get Work Done?</h2>
<p>As I said, APIs are about exchanging information. Even if you're not developing a frontend application, you can retrieve the data you need and manipulate or handle them to get the information you need. Then you can ask another service to perform the action you want it to perform.</p>
<p>I'll give you an everyday-life example to show you how you can use APIs to automate tasks to help implement your business strategy.</p>
<h3 id="heading-api-use-case-example">API Use Case Example</h3>
<p>Let's say our company sells umbrellas and we want to update our price list according to the weather of the city where our store is located. When it rains, we want the umbrellas' price to be raised, while we want it to decrease when the weather is good. In any other case, we want to leave the price as it is.</p>
<p>Of course, this is an over-simplified scenario, but I think it is a good fit to show how powerful APIs can be to help you automate your business strategies online.</p>
<p>Without any automation, you would have to check the weather forecasts every day and manually update the item's price. As I said at the beginning of this article, this type of manual process can be time-consuming and leave room for errors. Also, don't forget you would need somebody to perform these tasks 365 days a year.</p>
<p>Thankfully, we can automate this process. This is what we need:</p>
<ul>
<li>Python (3.10 and above)</li>
<li>A CMS/e-commerce exposing APIs (I'm using Woocommerce for this tutorial)</li>
<li>Weather forecast APIs</li>
</ul>
<h3 id="heading-how-to-use-python-and-apis-to-automate-updates">How to Use Python and APIs to Automate Updates</h3>
<p>We'll implement a batch written in Python – that executes every 24 hours – to update the price of the umbrellas according to the response of a weather forecast API we call.</p>
<p>Let's dive into the script and analyze it step by step. </p>
<p>First of all, I declare environment variables. This is the list:</p>
<pre><code class="lang-python">API_BASEURL <span class="hljs-comment">#The baseurl of the weather forecast service I'm calling</span>

API_CITY <span class="hljs-comment">#The city I want to get weather information about</span>

API_COUNTRY <span class="hljs-comment">#The country where API_CITY is located </span>

API_KEY <span class="hljs-comment"># The secret Key I must pass to retrieve the weather information</span>

CONSUMER_KEY <span class="hljs-comment">#The key I need to work with Woocommerce APIs </span>

CONSUMER_SECRET <span class="hljs-comment">#The secret I need to work with Woocommerce APIs</span>

DOMAIN <span class="hljs-comment">#The domain of my ecommerce</span>
</code></pre>
<p>Then, I start importing the libraries I need:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
</code></pre>
<p>I import <strong>os</strong> and I also import <strong>load_dotenv</strong> to work with environment variables.</p>
<p>Then I import requests and JSON to handle the API's response.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> json
</code></pre>
<p>Then I import the API module from Woocommerce Python library. You can find more information in its rich <a target="_blank" href="https://woocommerce.github.io/woocommerce-rest-api-docs/?python#libraries-and-tools">documentation</a>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> woocommerce <span class="hljs-keyword">import</span> API
</code></pre>
<p>Once I imported all the libraries and modules I need, I'll instantiate the variables I'll use on my script:</p>
<pre><code class="lang-python">load_dotenv()
product_to_sell_id = <span class="hljs-string">"1736"</span> <span class="hljs-comment">#The Id related to umbrellas in my e-commerce</span>
raised_price = <span class="hljs-string">"12"</span> <span class="hljs-comment">#The price I want to set when it rains</span>
lowered_price = <span class="hljs-string">"8"</span> <span class="hljs-comment">#The price I want to set when weather is good</span>
regular_price = <span class="hljs-string">"10"</span> <span class="hljs-comment">#The regular price of the item</span>
</code></pre>
<p>Then I declare the <strong>changePrice</strong> function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">changePrice</span>(<span class="hljs-params">price, idProduct</span>):</span>

    wcapi = API(
        url= os.getenv(<span class="hljs-string">'DOMAIN'</span>), 
        consumer_key= os.getenv(<span class="hljs-string">'CONSUMER_KEY'</span>), 
        consumer_secret= os.getenv(<span class="hljs-string">'CONSUMER_SECRET'</span>), 
        wp_api=<span class="hljs-literal">True</span>, 
        version=<span class="hljs-string">"wc/v3"</span> 
    )

    data = {
        <span class="hljs-string">"regular_price"</span>: price
    }

    wcapi.put(<span class="hljs-string">"products/"</span> + idProduct, data).json()

    print(<span class="hljs-string">"New price set to "</span> + data[<span class="hljs-string">"regular_price"</span>])
</code></pre>
<p>The function has two arguments: the price I want to set (price) and the id of the product I want to update (idProduct).</p>
<p>Inside the function I store in the <strong>wcapi</strong> variable the API method with the information I need to reach my e-commerce (baseurl, consumer key, and secret).</p>
<p>I store in the <strong>data</strong> variable the payload I want to pass: I want to update the value of the key "regular_price" with the value of the argument "price".</p>
<p>After that, I update the e-commerce database with the PUT method by passing the path of the product I want to update (it's a concatenation of the string "products/" and the value of the argument "idProduct") and the data variable value.</p>
<p>In the end, I print a success message.</p>
<p>Once the <strong>changePrice</strong> function is ready, I need to define a new one to make the script work. But before we go ahead, we need to see the data we get from our API call.</p>
<p>The JSON file we get back as a response returns a lot of information. But, as I said at the beginning, we just want to know what the weather is like. </p>
<p>We get this data with the "code" key. Every weather status is associated with a number. In our case, we focus on these two codes: </p>
<pre><code class="lang-python"><span class="hljs-number">502</span> <span class="hljs-comment">#rainy</span>
<span class="hljs-number">800</span> <span class="hljs-comment">#sunny</span>
</code></pre>
<p>Now that we have what we need, we define the <strong>getWeather</strong> function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getWeather</span>():</span>

    url = os.getenv(<span class="hljs-string">'API_BASEURL'</span>)

    headers = {
    <span class="hljs-string">"Accept"</span>: <span class="hljs-string">"application/json"</span>
    }

    payload = {
    <span class="hljs-string">"key"</span>: os.getenv(<span class="hljs-string">'API_KEY'</span>),
    <span class="hljs-string">"city"</span>: os.getenv(<span class="hljs-string">'API_CITY'</span>),
    <span class="hljs-string">"country"</span>: os.getenv(<span class="hljs-string">'API_COUNTRY'</span>)
    }


    response = requests.request(
    <span class="hljs-string">"GET"</span>,
    url,
    params=payload,
    headers=headers  
    )

    data = response.text

    parse_json = json.loads(data)

    get_parse_result = parse_json[<span class="hljs-string">"data"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"weather"</span>][<span class="hljs-string">"code"</span>]

    match get_parse_result:
        case <span class="hljs-number">502</span>:
            changePrice(raised_price, product_to_sell_id)

        case <span class="hljs-number">800</span>:
            changePrice(lowered_price, product_to_sell_id)

        case _:
            changePrice(regular_price, product_to_sell_id)
</code></pre>
<p>In the <strong>url</strong> variable we define the base URL of the API we're calling. In the payload variable I pass our secret key, the city, and the country I want to get the weather about.</p>
<p>I perform my GET request by passing the URL, payload, and headers. Once I get the response, I parse it, and implement a switch statement with 3 cases:</p>
<ul>
<li><strong>get_parse_result</strong> equals 502: we call the changePrice function passing as first argument the raised_price variable to increase the product price</li>
<li><strong>get_parse_result</strong> equals 800: we call the changePrice function passing as first argument the lowered_price variable to decrease the product price</li>
<li><strong>get_parse_result</strong> has a different value: we call the changePrice function passing as first argument the regular_price variable to keep the product price as it is</li>
</ul>
<p>A the end of the script, I call the getWeather function:</p>
<pre><code class="lang-python">getWeather()
</code></pre>
<p>And there you go – the prices will be automatically updated thanks to a little code.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>So, this is just a quick example of how you can use APIs to automate your business strategies, save time, and avoid mistakes that can cost your company money. </p>
<p>It's a pretty basic example but I think it shows the potential of APIs and their benefits. Here you can find my <a target="_blank" href="https://github.com/mventuri/automate-ecom-prices">repo</a> with the full script.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Generate WordPress Posts Automatically with Python ]]>
                </title>
                <description>
                    <![CDATA[ If you run a website, you are aware of the importance of content. It's important for your web presence, to help you be recognized as a leader in your field, to improve your SEO ranking, to increase your audience, and more. WordPress is one of the mos... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-generate-wordpress-posts-automatically/</link>
                <guid isPermaLink="false">66bdff602c7c89a851b3762e</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Mon, 22 Aug 2022 20:55:16 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you run a website, you are aware of the importance of content. It's important for your web presence, to help you be recognized as a leader in your field, to improve your SEO ranking, to increase your audience, and more.</p>
<p>WordPress is one of the most popular and widely-used tools to create blogs, e-commerce platforms, and websites.</p>
<p>In this article, I'll show you how to create content automatically and push it to your WordPress website with Python. </p>
<p>This is how it works:</p>
<ul>
<li>We'll get content from our source (for example, another website we run)</li>
<li>We'll translate it into our language</li>
<li>We'll choose a featured image already available on our website and finally publish it to our WordPress instance as a post.</li>
</ul>
<p>The script we're about to develop can be useful if you want to create content in another language in a quick way to expand your audience. </p>
<p>Let's say you have a webzine with content written in English and you want Spanish-speaking users to start reading your posts. You can create a new blog and run your script to get your posts translated into Spanish and ready to read by your users.</p>
<h2 id="heading-lets-get-started">Let's Get Started</h2>
<p>This is the script we'll develop by the end of this article:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">import</span> random
<span class="hljs-keyword">from</span> googletrans <span class="hljs-keyword">import</span> Translator
<span class="hljs-keyword">from</span> requests.auth <span class="hljs-keyword">import</span> HTTPBasicAuth

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post_creator</span>(<span class="hljs-params">sourceURL, wpBaseURL, sourceLang, targetLang, postStatus</span>):</span>
    response_API = requests.get(sourceURL)
    data = response_API.text
    parse_json = json.loads(data)
    get_article_title = parse_json[<span class="hljs-string">'title'</span>]
    get_article_content = parse_json[<span class="hljs-string">'body'</span>]
    image_list = [<span class="hljs-string">"1689"</span>,<span class="hljs-string">"1594"</span>,<span class="hljs-string">"1612"</span>]

    translator = Translator()

    title_translation = translator.translate(get_article_title, src=sourceLang, dest=targetLang)
    title_translation_text = title_translation.text 

    content_translation = translator.translate(get_article_content, src=sourceLang, dest=targetLang)
    content_translation_text = content_translation.text 

    random_image_list = random.choice(image_list)

    WP_url = wpBaseURL + <span class="hljs-string">"/wp-json/wp/v2/posts"</span>

    auth = HTTPBasicAuth(&lt;USERNAME&gt;, &lt;PASSWORD&gt;)

    headers = {
    <span class="hljs-string">"Accept"</span>: <span class="hljs-string">"application/json"</span>,
    <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>
    }

    payload = json.dumps({ 
        <span class="hljs-string">"status"</span>:postStatus,
        <span class="hljs-string">"title"</span>: title_translation_text,
        <span class="hljs-string">"content"</span>: content_translation_text,
        <span class="hljs-string">"featured_media"</span>: random_image_list
    })

    response = requests.request(
    <span class="hljs-string">"POST"</span>,
    WP_url,
    data=payload,
    headers=headers,
    auth=auth
    )

    print(response)
    print(random_image_list)


post_creator(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts/5"</span>, <span class="hljs-string">"&lt;BASE_URL&gt;"</span>, <span class="hljs-string">"la"</span>, <span class="hljs-string">"en"</span>, <span class="hljs-string">"publish"</span>)
</code></pre>
<p>We'll break it into single parts and see, step by step, what we need to do. </p>
<p>Before that, we need to go to the dashboard of our WordPress website and create a new application password. We'll use it to build our basic authentication when pushing posts to our website. </p>
<p>If you've never done it before, you can check WordPress official <a target="_blank" href="https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/">documentation</a> on how to do it. Once you'll create it, you'll see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/0-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Don't forget to save it, this is the only chance to get it!</p>
<h2 id="heading-time-to-code">Time to Code</h2>
<p>Let's start checking out our code from the libraries we need. We'll use the googletrans library to translate our content with Google translate APIs. So, from the command line, I move to my project directory and type:</p>
<pre><code class="lang-python">pip install googletrans
</code></pre>
<p>You could encounter this error when you run the script:</p>
<pre><code class="lang-cmd">AttributeError: 'NoneType' object has no attribute 'group'
</code></pre>
<p>If you see this message error, you should install this version:</p>
<pre><code class="lang-cmd">pip install googletrans==4.0.0-rc1
</code></pre>
<p>I found it on <a target="_blank" href="https://stackoverflow.com/questions/52455774/googletrans-stopped-working-with-error-nonetype-object-has-no-attribute-group">this</a> StackOverflow article. If you want to know more about it, just have a look!</p>
<h2 id="heading-how-to-get-the-content-translated">How to Get the Content Translated</h2>
<p>Once we install googletrans, we define a new function and call it "post_creator":</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post_creator</span>(<span class="hljs-params">sourceURL, wpBaseURL, sourceLang, targetLang, postStatus</span>):</span>
</code></pre>
<p>We pass this function five arguments:</p>
<ul>
<li><code>sourceURL</code>: the URL of the website you get content from</li>
<li><code>wpBaseURL</code>: the URL of your new website where you want to import translated content</li>
<li><code>sourceLang</code>: the original language of the content</li>
<li><code>targetLang</code>: the language you want your content to be translated into</li>
<li><code>postStatus</code>: the status of your WordPress post: for example "draft", "published", and so on.</li>
</ul>
<p>Inside the function, we declare six variables. Let's see them.</p>
<p>We use the GET method to call an API to get the content we want to translate: </p>
<pre><code class="lang-python">response_API = requests.get(sourceURL)
</code></pre>
<p>Then we store in the "data" variable the text of the request:</p>
<pre><code class="lang-python">data = response_API.text
</code></pre>
<p>We parse the JSON with the ".loads()" method to convert it into a Python dictionary:</p>
<pre><code class="lang-python">parse_json = json.loads(data)
</code></pre>
<p>Then we store the value of the JSON key "title":</p>
<pre><code class="lang-python">get_article_title = parse_json[<span class="hljs-string">'title'</span>]
</code></pre>
<p>We do the same with the "body" key:</p>
<pre><code class="lang-python">get_article_content = parse_json[<span class="hljs-string">'body'</span>]
</code></pre>
<p>Finally, we store in a variable a list where we have the IDs of the media we want to use as "featured image": </p>
<pre><code class="lang-python">image_list = [<span class="hljs-string">"1689"</span>,<span class="hljs-string">"1594"</span>,<span class="hljs-string">"1612"</span>]
</code></pre>
<p>After we created the above variables, we instantiate Translator():</p>
<pre><code class="lang-python">translator = Translator()
</code></pre>
<p>Now we can start translating content. We translate the title of the article we got from the previous API call and store it in the "title_translation" variable. We then get its text and store it in the "title_translation_text" variable:</p>
<pre><code class="lang-python">title_translation = translator.translate(get_article_title, src=sourceLang, dest=targetLang)
title_translation_text = title_translation.text
</code></pre>
<p>We do the same with the content of the article:</p>
<pre><code class="lang-python">content_translation = translator.translate(get_article_content, src=sourceLang, dest=targetLang)
content_translation_text = content_translation.text
</code></pre>
<p>We get a random image from the image IDs list we created before. Images must be already available in our WordPress instance. Then we pick one just by specifying its ID:</p>
<pre><code class="lang-python">random_image_list = random.choice(image_list)
</code></pre>
<h2 id="heading-how-to-create-our-wordpress-blog-post">How to Create Our WordPress Blog Post</h2>
<p>Now we set things up to push the content we have to our WordPress website. First, we store the URL we're calling to push the content in a variable: </p>
<pre><code class="lang-python">WP_url = wpBaseUrl + <span class="hljs-string">"/wp-json/wp/v2/posts"</span>
</code></pre>
<p>We store in a variable the credentials for our basic authentication: the username and the application password we created before. We use "HTTPBasicAuth" to handle our authentication:</p>
<pre><code class="lang-python">auth = HTTPBasicAuth(&lt;USERNAME&gt;, &lt;PASSWORD&gt;)
</code></pre>
<p>We store in a variable the headers we want to pass. We set the output type to JSON and indicate that the request body format is JSON:</p>
<pre><code class="lang-python">headers = {
    <span class="hljs-string">"Accept"</span>: <span class="hljs-string">"application/json"</span>,
    <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>
    }
</code></pre>
<p>Time to define the payload. We use the dumps() function to convert the Python object we created into a JSON string and then we pass the data we need to create the blog post: </p>
<pre><code class="lang-python">payload = json.dumps({ 
        <span class="hljs-string">"status"</span>:postStatus,
        <span class="hljs-string">"title"</span>: title_translation_text,
        <span class="hljs-string">"content"</span>: content_translation_text,
        <span class="hljs-string">"featured_media"</span>: random_image_list
    })
</code></pre>
<p>Then we use the request() method to make our API call:</p>
<pre><code class="lang-python">response = requests.request(
    <span class="hljs-string">"POST"</span>,
    WP_url,
    data=payload,
    headers=headers,
    auth=auth
    )
</code></pre>
<p>At the end of the function, we print the response of the POST call and the ID of the media we'll use as the featured image:</p>
<pre><code class="lang-python">print(response)
print(random_image_list)
</code></pre>
<p>Once we've completed our function, it's time to call it and pass the correct arguments:</p>
<pre><code class="lang-python">post_creator(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts/5"</span>, &lt;BASEURL&gt;, <span class="hljs-string">"la"</span>, <span class="hljs-string">"en"</span>, <span class="hljs-string">"publish"</span>)
</code></pre>
<ul>
<li><code>https://jsonplaceholder.typicode.com/posts/5</code>: the URL we call to get the content we want to translate</li>
<li><code>&lt;BASEURL&gt;</code>: the base URL of our WordPress website</li>
<li><code>la</code>: the language code of the content we get from our API call. In this case, it is "Lorem Ipsum" content, so we set it to Latin</li>
<li><code>en</code>: the language code we want to translate our content into. We set it to English.</li>
<li><code>publish</code>: the status of the WordPress post we are creating</li>
</ul>
<p>If we run the script via the command line, we see this message:</p>
<pre><code class="lang-cmd">&lt;Response [201]&gt; 
1594
</code></pre>
<p>And if you visit the website, you can see the post:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/1-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Just to give you a complete overview, this is the JSON we got content from:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>In this article, we saw how to automate posts in a few lines of code with Python. It can be run as a batch or when necessary. </p>
<p>Content is always a key point when you manage a website. I hope this article will help you translate content quickly and grow your audience even faster. <a target="_blank" href="https://github.com/mventuri/python-wordpress-blog-post">Here</a> you can find the repo on GitHub. </p>
<p>Enjoy and keep coding! :) </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Azure Static Web Apps to Deploy an Angular App ]]>
                </title>
                <description>
                    <![CDATA[ CI/CD has changed the way IT teams release new software versions.  In this tutorial I'll share my experience with Azure Static Web Apps – Azure's PaaS solution. I'll show you how you can take advantage of its flexibility to deploy an Angular App just... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-azure-static-web-apps-to-deploy-angular-app/</link>
                <guid isPermaLink="false">66bdff650b4523e3b8b99095</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Azure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Thu, 14 Apr 2022 23:42:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/cover_2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>CI/CD has changed the way IT teams release new software versions. </p>
<p>In this tutorial I'll share my experience with Azure Static Web Apps – Azure's PaaS solution. I'll show you how you can take advantage of its flexibility to deploy an Angular App just by pushing your code to a Git repository.</p>
<p>There’s a lot of literature about CI/CD on the web, and in this article, I want to focus on Azure Web Apps to show you how it can dramatically simplify your workflow. </p>
<p>If you want to know more about CI/CD, Atlassian’s <a target="_blank" href="https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment">blog</a> has some good info. And here's a helpful in-depth and <a target="_blank" href="https://www.freecodecamp.org/news/how-to-setup-a-ci-cd-pipeline-with-github-actions-and-aws/">project-based guide on the subject</a>.</p>
<h2 id="heading-what-do-we-need-for-this-project">What do we need for this project?</h2>
<p>During this tutorial, we'll use the following technologies and tools:</p>
<ul>
<li>A GitHub account </li>
<li>Node.js (you can download it <a target="_blank" href="https://nodejs.org/en/download/">here</a>)</li>
<li>Npm (Node.js package manager. Included with Node installation.)</li>
<li>Angular CLI (a command-line interface tool to create, develop and maintain your Angular app. You can download it <a target="_blank" href="https://angular.io/cli">here</a>.)</li>
<li>Azure account (you can start for free by creating your account <a target="_blank" href="https://azure.microsoft.com/en-us/free/">here</a>. Once your free trial expires, have a look at the costs you are incurring. Cloud technologies are very powerful and can make your life easier. But they can be expansive if not well managed.)</li>
</ul>
<p>If you want to follow along with me during this article and replicate what I’m building, you need to be all set with these tools.</p>
<h2 id="heading-what-well-build-here-the-big-picture">What We'll Build Here – the Big Picture</h2>
<p>Let’s see how to create our Angular App and deploy it with Azure Web App. We'll create our Angular app locally and push it to a GitHub repository we specifically create for this project. </p>
<p>The repository will have two branches: “main” and “develop”. We'll create a static web app on Azure and connect it to the “main” branch of the repository. </p>
<p>Back to your machine, edit the code and push it to the “develop” branch. Then you merge the “develop” branch with the “main” one and see the new version of your app online.</p>
<p>Just to be clearer, I think a quick list will help us recap every single step:</p>
<ul>
<li>You'll create your Angular app locally with Angular CLI</li>
<li>You'll push it to a GitHub repository</li>
<li>You’ll create a static web app on Azure and connect it to the “main” branch of the project’s repository</li>
<li>You’ll create a “develop” repository</li>
<li>You’ll edit the app code locally and push it to the “develop” repository</li>
<li>You’ll create a pull request on your GitHub project from “develop” to “main” and merge it</li>
<li>You’ll check if the new app version is available on the web app</li>
</ul>
<h2 id="heading-step-1-create-the-angular-app-locally">Step 1 – Create the Angular App Locally</h2>
<p>First, let's create a specific directory on your computer and move into it. I’m on Mac, so I'll open my terminal and type:</p>
<pre><code>mkdir angular_azure
cd angular azure
</code></pre><p>Once there, create your new Angular app called “angular_app”:</p>
<pre><code>ng <span class="hljs-keyword">new</span> angular_app
</code></pre><p>Angular CLI asks you a few questions:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/0.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We want to add Angular router and we also want to use CSS for styling the app. Once you receive positive feedback from Angular CLI, start your app locally to see if everything is working fine:</p>
<pre><code>ng serve —-open
</code></pre><p>The option “--open” tells Angular CLI that you want to open the application with your default browser. This means that you don’t need to copy and paste the URL into your browser’s address bar. So, this is what you should see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Looks like everything is working fine. You can stop the application (Ctrl + C) and move to the next step</p>
<h2 id="heading-step-2-push-the-angular-app-to-your-github-repository">Step 2 – Push the Angular App to Your GitHub Repository</h2>
<p>You should have created a new repository on your GitHub account dedicated to this project. I called mine “angular-app-with-azure”. If you don’t know how to create a new repository, you can <a target="_blank" href="https://docs.github.com/en/get-started/quickstart/create-a-repo">read more about that here</a>.</p>
<p>Once the repository is ready, push your Angular app from your machine to your repository. If you don’t add a README file when creating your repo, you should see the instructions on how to push your code directly on your repository page. However, I'll repeat these instructions also here:</p>
<pre><code>git init
git add .
git commit -m <span class="hljs-string">"first commit"</span>
git branch -M main
git remote add origin https:<span class="hljs-comment">//github.com/&lt;REPO&gt;.git</span>
git push -u origin main
</code></pre><p>Once you run these commands successfully, you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/4-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let’s go ahead now.</p>
<h2 id="heading-step-3-time-to-switch-to-azure">Step 3 – Time to Switch to Azure</h2>
<p>Now you'll create a brand new Azure Static Web App and connect it to your repository. First of all, enter the Azure portal <a target="_blank" href="https://portal.azure.com">here</a>, and go to your Resource Group. Then you'll see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/5-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Hit “create” and you'll see the list of resources available on Azure. Filter resources by “Static Web App” and select it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/6.a.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then move to Azure’s wizard to create the resource. Let’s see how you should fill it out.</p>
<p>First of all, choose the subscription and resource group. Then go with the Static Web App details: choose the name – “angular-app” – and stick with the Free plan. Then select your region – mine is “Central US”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/6-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then go ahead with a few more pieces of information:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/7-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can synch your GitHub account in the “Deployment Details” section, and then specify the Organization, Repository, and branch you'll get your codebase from. </p>
<p>As I said at the beginning of this tutorial, I choose the “main” branch as the production one. </p>
<p>Now let’s focus on the “Build Details”. You'll choose “Angular” as “Build Presets”, and specify that the App is located at the root directory on “App Location”. </p>
<p>Then you'll type the path of the output location (“dist” directory plus name-of-project directory. In my case, it's “dist/angular-app”. This is where Angular CLI locates the build of your project. I spent a lot of time looking for this info and I think it’s good to share it with you).</p>
<p>So, now you're ready to create your Static Web App. Hit “create” and see what happens. This is the overview of my app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/555-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, hit the “URL” link and this is what you should see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-ia"> </h2>
<p>Step 4 – Create a New Branch </p>
<p>So now you'll go back to your codebase locally and create your “develop” branch and check it out:</p>
<pre><code>git checkout -b develop
</code></pre><p>Then go to:</p>
<pre><code>src/app/app.component.html
</code></pre><p>Edit the code like this:</p>
<pre><code>&lt;p&gt;Pushed to develop&lt;/p&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">router-outlet</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-outlet</span>&gt;</span></span>
</code></pre><p>And then push the new branch to the remote repository:</p>
<pre><code>git push origin develop
</code></pre><h2 id="heading-step-5-time-to-merge">Step 5 – Time to Merge</h2>
<p>Your angular App is still online with the old version. You need to merge your "develop" branch to "main" to see the changes online.</p>
<p>Create a pull request on GitHub and merge it. This is what you should see at the end:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/999.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Wait a couple of minutes and then you'll see the new version of your app online:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/888-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-a-quick-recap-and-useful-resources">A Quick Recap and Useful Resources</h2>
<p>I hope this tutorial showed you how you can easily deploy your code to a production environment with CI/CD and Azure Static Web App. </p>
<p>While practicing with these technologies, I found a lot of interesting content on the web about them. I thought it would be good for you to have all of them in one place:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/what-is-git-learn-git-version-control/">What is Git? A beginner's guide to Git version control</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/practical-git-and-git-workflows/">How to use Git and Git Workflows – a practical guide</a></li>
<li><a target="_blank" href="https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions">GitHub Actions docs</a></li>
<li><a target="_blank" href="https://angular.io/">Angular docs</a></li>
<li><a target="_blank" href="https://github.com/mventuri/angular-app-with-azure">My repo on GitHub</a></li>
</ul>
<p>And don't forget... Keep learning, and keep coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Custom Dashboard with WordPress APIs and React ]]>
                </title>
                <description>
                    <![CDATA[ When you manage websites, it is all about data: views, response time, users, bounce rate, and so on. And, if you manage websites, you've likely had to deal with a WordPress instance at least once.  There are hundreds – or maybe thousands – of WordPre... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-custom-dashboard-with-wordpress-apis-and-react/</link>
                <guid isPermaLink="false">66bdff4f0b4523e3b8b9908c</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Fri, 18 Feb 2022 15:59:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/stephen-dawson-qwtCeJ5cLYs-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you manage websites, it is all about data: views, response time, users, bounce rate, and so on. And, if you manage websites, you've likely had to deal with a WordPress instance at least once. </p>
<p>There are hundreds – or maybe thousands – of WordPress plugins to retrieve and show data. But WordPress APIs can give us a hand if we want to build a custom dashboard with some specific information we want to get. </p>
<p>That's why today I want to share with you how to build a service that retrieves data from our WordPress instance and shows them on a table. To be more specific, I want to know the number the plugins I'm using and what plugins I've installed previously that I'm not using anymore. </p>
<h2 id="heading-why-should-i-know-what-wordpress-plugins-im-using">Why should I know what WordPress plugins I'm using?</h2>
<p>I always found this information to be very important. Especially at the beginning of your journey with WordPress, you might be tempted to install a plugin for every single functionality you want your websites to have. </p>
<p>Well, plugins may be easy to install but they also have some potential drawbacks:</p>
<ul>
<li>If not updated often, they can expose your website to attacks and vulnerabilities</li>
<li>They can make the loading time of your website much longer than it should be</li>
<li>Some of the plugins might conflict with each other</li>
</ul>
<p>I'm not saying you shouldn't use or trust plugins. But it is something you have to pay attention to. So let's see how we can have some useful information about our plugins at our fingertips.</p>
<h3 id="heading-what-tools-ill-be-using">What tools I'll be using</h3>
<ul>
<li>WordPress APIs – I'll work with the "plugins" endpoint.</li>
<li>React – I'll create a component to display data. </li>
<li>Axios – I'll use it to call APIs easily.</li>
<li>React-Bootstrap – I chose this library just to get a nice and easy-to-use table component quickly.</li>
<li>Postman – This is the tool I always use to test APIs.</li>
<li>Npm – I'll use it to create a React app and install packages.</li>
</ul>
<h2 id="heading-wordpress-apis">WordPress APIs</h2>
<p>As I said at the beginning of this article, I want to call a specific endpoint to get JSON with the information about the plugins I've installed on my instance. Precisely, I want to count the plugins I currently use ("active") and the plugins I don't use ("inactive"). </p>
<p>The <a target="_blank" href="https://developer.wordpress.org/rest-api/">documentation</a> about the APIs is very detailed and full of useful information and concepts. So I hit "Endpoint reference" on the sidebar and scroll to click on "Plugins". </p>
<p>Let's focus now on the "Schema" section. Here I find all the fields that exist in a plugin record. The list is quite long, but I need just one of these fields: "status". The documentation says it returns me a string with two possible values: "inactive" or "active". </p>
<p>So this is the API I'll call to retrieve the necessary data:</p>
<pre><code>https:<span class="hljs-comment">//&lt;BASE_URL&gt;/wp-json/wp/v2/plugins</span>
</code></pre><p>So far so good. There's one more thing we need to take into consideration. Some endpoints require basic authentication to return data. Our endpoint is one of those. Starting version 5.6, you can pass a username and an application password to call this endpoint. </p>
<p>If you want to know more about application passwords and how to generate them, I recommend you to check this <a target="_blank" href="https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/">article</a> written by the WordPress community.</p>
<h3 id="heading-time-to-test-the-api">Time to Test the API</h3>
<p>Once I know what endpoint I need to call and I generate my application password, I'm ready to test my API call with Postman. This is what I get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/postman.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, I get a JSON with the information I'm looking for: the "status" key. Now we are ready to create our React app!</p>
<h2 id="heading-lets-code-the-react-app">Let's Code the React App</h2>
<p>It's now time to create the front-end of our application. As I said before, I'll use React because of its flexibility, Axios to call APIs easily, and React-Bootstrap to get ready-to-use components with a nice design. </p>
<p>Before I start writing code, let's recap what I want to achieve: I want my front-end application to retrieve data from my WordPress instance about the status – active or inactive – of the plugins installed by calling the "Plugins" endpoint. </p>
<p>To do so, I want my script to perform the following actions:</p>
<ol>
<li>Create variables to store the count of active and inactive plugins</li>
<li>Call the endpoint by an API call</li>
<li>Iterate through the JSON – the API call returns with the following logic: If the object key "status" equals "active" increase the related count by one, otherwise increase the count related to the inactive plugins by 1. Update the related states - previously defined in the constructor - accordingly</li>
<li>Render the table by using the "Table" component from React-Bootstrap and pass the states into the table component where I want data to be displayed with the count of active and inactive plugins</li>
</ol>
<p>Enough talking. Time to code! :)</p>
<p>First things first, I create my React app like this:</p>
<pre><code>npx create-react-app report
</code></pre><p>Then I install Axios and React-Bootstrap:</p>
<pre><code>npm install axios
npm install react-bootstrap bootstrap@<span class="hljs-number">5.1</span><span class="hljs-number">.3</span>
</code></pre><p>All set. Now, in my React app, I move to the /src directory and I create a new directory called "components":</p>
<pre><code>/src/components
</code></pre><p>Then I move to the components folder and I create a "Report.jsx" file. This is how the file looks now:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> Table <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap/Table'</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Report</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{ 
  <span class="hljs-keyword">constructor</span>(props) { 
      <span class="hljs-built_in">super</span>(props); 
      <span class="hljs-built_in">this</span>.state = { <span class="hljs-attr">countActiveState</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">countInactiveState</span>: <span class="hljs-number">0</span>, };
  } 

  componentDidMount() {
  <span class="hljs-keyword">let</span> countActive  = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">let</span> countInactive = <span class="hljs-number">0</span>;

  axios.get(<span class="hljs-string">"https://&lt;BASE_URL&gt;/wp-json/wp/v2/plugins"</span>, {
    <span class="hljs-attr">auth</span>: {
      <span class="hljs-attr">username</span>: process.env.REACT_APP_USERNAME,
      <span class="hljs-attr">password</span>: process.env.REACT_APP_CLIENT_SECRET
    }
  })
  .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
      <span class="hljs-keyword">const</span> plugins = res.data;
      <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> key <span class="hljs-keyword">in</span> plugins) {
        <span class="hljs-keyword">if</span>(plugins[key].status === <span class="hljs-string">"active"</span>) {
          countActive++;
          <span class="hljs-built_in">this</span>.setState({<span class="hljs-attr">countActiveState</span>: countActive}); 
        }
        <span class="hljs-keyword">else</span>{
          countInactive++;
          <span class="hljs-built_in">this</span>.setState({<span class="hljs-attr">countInactiveState</span>: countInactive}); 
        }
    }
    })
    .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
      alert(<span class="hljs-string">"Something went wrong. Try again later."</span>);
      <span class="hljs-built_in">console</span>.log(error);
   })
  }

  render() { 
      <span class="hljs-keyword">return</span> ( 
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Table</span> <span class="hljs-attr">striped</span> <span class="hljs-attr">bordered</span> <span class="hljs-attr">hover</span> &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Status<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Plugin Amount<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Active<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{this.state.countActiveState}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Inactive<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{this.state.countInactiveState}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Table</span>&gt;</span></span>
      ); 
  } 
} 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Report;
</code></pre>
<p>Let's break it into smaller pieces and see what is going on:</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> Table <span class="hljs-keyword">from</span> <span class="hljs-string">'react-bootstrap/Table'</span>
</code></pre><p>I import Axios and the component "Table" from the React-bootstrap library.</p>
<pre><code><span class="hljs-keyword">constructor</span>(props) { 
      <span class="hljs-built_in">super</span>(props); 
      <span class="hljs-built_in">this</span>.state = { <span class="hljs-attr">countActiveState</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">countInactiveState</span>: <span class="hljs-number">0</span>, };
  }
</code></pre><p>In the constructor I define two states: countActiveState and countInactiveState. I set both of them to 0.</p>
<pre><code class="lang-jsx">componentDidMount() {
    <span class="hljs-keyword">let</span> countActive  = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">let</span> countInactive = <span class="hljs-number">0</span>;
</code></pre>
<p>I declare two variables and set them equal to 0: <code>countActive</code> to store the active plugin count and <code>countInactive</code> to store the inactive plugin count.</p>
<pre><code class="lang-jsx">axios.get(<span class="hljs-string">"https://&lt;BASE_URL&gt;/wp-json/wp/v2/plugins"</span>, {
      <span class="hljs-attr">auth</span>: {
        <span class="hljs-attr">username</span>: process.env.REACT_APP_USERNAME,
        <span class="hljs-attr">password</span>: process.env.REACT_APP_CLIENT_SECRET
      }
    })
</code></pre>
<p>I use Axios to perform a GET call to the "Plugins" endpoint. I also pass the credentials for the basic auth.</p>
<pre><code class="lang-jsx">.then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
      <span class="hljs-keyword">const</span> plugins = res.data;
      <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> key <span class="hljs-keyword">in</span> plugins) {
        <span class="hljs-keyword">if</span>(plugins[key].status === <span class="hljs-string">"active"</span>) {
          countActive++;
          <span class="hljs-built_in">this</span>.setState({<span class="hljs-attr">countActiveState</span>: countActive}); 
        }
        <span class="hljs-keyword">else</span>{
          countInactive++;
          <span class="hljs-built_in">this</span>.setState({<span class="hljs-attr">countInactiveState</span>: countInactive}); 
        }
    }
    })
    .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
      alert(<span class="hljs-string">"Something went wrong. Try again later."</span>);
      <span class="hljs-built_in">console</span>.log(error);
   })
  }
</code></pre>
<p>Then, after storing the response data in a variable called "plugins", I iterate through the JSON and say: "for each JSON object, check if the key "status" is equal to "active". If so, increase the countActive variable by 1 and set the countActiveState equal to countActive, else increase the countInactive variable by 1 and set the countInactiveState equal to countInactive".</p>
<pre><code class="lang-jsx">render() { 
      <span class="hljs-keyword">return</span> ( 
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Table</span> <span class="hljs-attr">striped</span> <span class="hljs-attr">bordered</span> <span class="hljs-attr">hover</span> &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Status<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Plugin Amount<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Active<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{this.state.countActiveState}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Inactive<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{this.state.countInactiveState}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Table</span>&gt;</span></span>
      ); 
  } 
} 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Report;
</code></pre>
<p>Then I render the Table component and I pass the countActiveState and countInactiveState where I want data to be displayed.</p>
<p>Lastly, I go to the App.js file and I add the Report component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> Report <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Report'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>WordPress Stats Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Report</span>/&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>I start the app:</p>
<pre><code>npm start
</code></pre><p>And the magic happens! :)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/frontend.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-and-there-you-have-it">And there you have it!</h3>
<p>So, this is just a quick example of how you can easily build your custom dashboard to retrieve and visualize data from your WordPress instance. </p>
<p>You can use any type of graphical data representation, such as bar or pie chart. It's all up to you! </p>
<p>Don't forget to have a look at my <a target="_blank" href="https://github.com/mventuri/react-dashboard-wordpress-api">repo</a> on GitHub. Feel free to share this article and your feedback. :)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Automate Tasks with Azure Webjobs ]]>
                </title>
                <description>
                    <![CDATA[ When you work in IT operations, automation is a key part of your job.  You'll have various repetitive tasks you have to deal with, and you don’t want to waste your time doing something that can be done by a script.  Here are some great reasons to aut... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-automate-tasks-with-azure-webjobs/</link>
                <guid isPermaLink="false">66bdff5699b6d009225ad10c</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Azure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Tue, 21 Dec 2021 16:33:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/cover.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you work in IT operations, automation is a key part of your job. </p>
<p>You'll have various repetitive tasks you have to deal with, and you don’t want to waste your time doing something that can be done by a script. </p>
<p>Here are some great reasons to automate repetitive tasks:</p>
<ul>
<li>doing repetitive tasks doesn't help your career or develop your skillset at all</li>
<li>there’s plenty of room for mistakes</li>
<li>as I said before, you feel you’re wasting your time. And if you just asked someone else to do these tasks, so would they. </li>
</ul>
<h2 id="heading-when-is-it-time-to-automate-a-task">When is it time to automate a task?</h2>
<p>Well, the more you advance along your career path, the more you'll understand when you can try to automate a process. </p>
<p>Based on my personal experience, you need to be able to answer these three questions:</p>
<h3 id="heading-1-how-often-do-you-perform-this-task">1. How often do you perform this task?</h3>
<p>Keep track of how many times you've performed the task during the last month. If it needs to be done every week or less, you should try to automate it</p>
<h3 id="heading-2-how-long-does-this-process-take">2. How long does this process take?</h3>
<p>Try to estimate the average time you need to complete the task. If it is equal to or more than 30 minutes, I think it is worth thinking about how to automate it. </p>
<p>Just to give you an idea, let’s say you perform the task every day and it takes 30 minutes. That's 2.5 hours a week and 10 hours a month. Assuming you work eight hours per day you spend more than a day per month dealing with that task. When it comes to budgeting, that's a lot of money</p>
<h3 id="heading-3-how-much-does-automation-cost">3. How much does automation cost?</h3>
<p>You need a cost estimation: how many hours do you need to develop the script? Do you need to use any third party services such as libraries, cloud services, and so on? </p>
<p>If you decide that the development is quick and not expensive, you can consider going ahead with the implementation.</p>
<h2 id="heading-how-to-automate-tasks">How to Automate Tasks</h2>
<p>Ok, let’s see now how you can automate a simple but frequent task. </p>
<p>When you work in IT operations, you'll need to generate reports or files with updated information for other departments quite often. Let’s say you’re asked to generate a file with some information about a specific GitHub profile.</p>
<p>GitHub offers APIs where you can get information about a single profile:</p>
<p><a target="_blank" href="https://api.github.com/users">https://api.github.com/users</a>/</p>
<p>We can write a quick script with Node.js and Axios to call the endpoint, get the information we need, and create a text file to store it in a specific directory.</p>
<p>This is our script:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> axios = <span class="hljs-built_in">require</span>(<span class="hljs-string">'axios'</span>);
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);

axios.get(<span class="hljs-string">'https://api.github.com/users/&lt;USERNAME&gt;'</span>)
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> file_text = response.data.login + <span class="hljs-string">" "</span> + response.data.name
    <span class="hljs-keyword">const</span> nome = <span class="hljs-built_in">Date</span>.now()
    <span class="hljs-built_in">console</span>.log(response.data.login);
    <span class="hljs-built_in">console</span>.log(response.data.name);
    fs.writeFile(<span class="hljs-string">'./fileCreated/'</span> + nome + <span class="hljs-string">'.txt'</span>, file_text, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
      <span class="hljs-keyword">if</span> (err) {
        <span class="hljs-built_in">console</span>.error(err)
        <span class="hljs-keyword">return</span>
      }
    })

  })
  .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(error);
  });
</code></pre>
<p>As you can see, once we call the endpoint, we log the username and name to the console. Then we print this information in a text file named by the timestamp, and save in a directory called “fileCreated”.</p>
<h3 id="heading-how-to-run-the-script-periodically">How to run the script periodically</h3>
<p>There are tons of tools that help you run a script at any given time. For this tutorial, I decided to use Azure WebJobs. </p>
<p>It is a service included in Azure’s Pass solution, “Web App”, and it allows you to run scripts, manually or periodically, written with the world’s most popular languages such as Java, Python, .NET, and, of course, NodeJs. </p>
<p>You can find the full list <a target="_blank" href="https://docs.microsoft.com/en-us/azure/app-service/webjobs-create">here</a>.</p>
<h3 id="heading-how-to-use-azure-webjobs">How to use Azure WebJobs</h3>
<p>I assume you already created your Web App. Just consider that, at the time I’m writing this tutorial, Webjobs are available only on Windows Web Apps. </p>
<p>If you need help getting started, I suggest you check out this <a target="_blank" href="https://azure.microsoft.com/en-us/get-started/web-app/">tutorial</a> by Microsoft.</p>
<p>On the WebApp menu (left sidebar) I filtered options by typing “WebJobs” and clicking on it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/0.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once on the WebJobs panel, I clicked “Add” to add my script (I zipped my file with all its dependencies and called it “axiosexample”). Then,</p>
<ul>
<li>I entered the name</li>
<li>I uploaded the zipped file</li>
<li>I chose “triggered” since I don’t want this task to be performed continuously</li>
</ul>
<p>On the “Triggers” option, I chose “Manual” because I wanted to run it now to show you the result for this tutorial. But you can schedule the WebJobs by choosing “Scheduled” and specifying the CRON expression. Check out <a target="_blank" href="https://docs.microsoft.com/en-us/azure/app-service/webjobs-create#CreateScheduledCRON">this</a> tutorial by Microsoft to see how to write a CRON expression. </p>
<p>If you want to learn more about CRON expressions, the internet is full of literature about it. You can simply start from the Wikipedia <a target="_blank" href="https://en.wikipedia.org/wiki/Cron">page</a>, check out <a target="_blank" href="https://www.freecodecamp.org/news/cron-jobs-in-linux/">this tutorial on freeCodeCamp</a>, and then continue with other useful content such as <a target="_blank" href="https://crontab.guru/">Cronitor</a>.</p>
<p>Next, click “Ok”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once saved, hit “Run” to perform the task immediately. Then click “Logs” to see the results of our WebJobs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once on the “Logs” page, hit webjobs to get further details:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next let's set the “Timing” of our WebJobs:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And we see the log messages, like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, by using the “Kudu” service available in our Web App, go to the directory where you saved your file via Powershell. </p>
<p>“Kudu” is a very useful service available on Azure’s Web Apps that allows you to get a lot of information about the Web App itself such as App settings, Run Commands, and much more. You can see the full list <a target="_blank" href="https://docs.microsoft.com/en-us/azure/app-service/resources-kudu">here</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You'll reach the directory you created. The path is:</p>
<pre><code class="lang-cmd">\home\site\wwwroot\App_Data\jobs\triggered\webjob\axiosexample\fileCreated
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once you reach the file, just open it and this is what you should see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>So, this is a quick example of how you can simply automate a task with a few lines of JavaScript and Azure Webjobs. </p>
<p>Just look around you and see what you find repetitive and time consuming. Then, think how you could put those actions into a script and that's it! </p>
<p>Automation is all around you! 😀 Don't forget: the more you automate, the more time you have to think about more automations... Feel free to have a look at my <a target="_blank" href="https://github.com/mventuri/How-to-Automate-Tasks-with-Azure-Webjobs">repo</a> on GitHub.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate a Static Website with WordPress ]]>
                </title>
                <description>
                    <![CDATA[ Lots of people still use static websites, from family-run businesses who don't need to update information that often, to large teams who need to release something quickly without spending too much time and effort on it.  You might also want a static ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-integrate-a-static-website-with-wordpress/</link>
                <guid isPermaLink="false">66bdff620b4523e3b8b99093</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Tue, 26 Oct 2021 17:09:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Lots of people still use static websites, from family-run businesses who don't need to update information that often, to large teams who need to release something quickly without spending too much time and effort on it. </p>
<p>You might also want a static website for these reasons:</p>
<ol>
<li>Speed: pages load quickly</li>
<li>Minimal skills required: Web developers who don't have much experience can easily work on the project</li>
<li>Hosting is easy: today's market offers a variety of options to host your static website (like AWS S3, Azure Storage, Netlify, and others)</li>
</ol>
<p>So far we've talked about why you might choose a static website and what they're good at. </p>
<p>But what if you want to add content quickly to your website or update just a section of it? What if you want to add a blog to your website to get new visitors?</p>
<p>That's an issue I've had to deal with in the past several times: clients asked me to add dynamic content to their websites and they had no budget or time to create a new project. Fortunately, WordPress helped me find a solution. Let's see how.</p>
<h2 id="heading-how-wordpress-helped-me">How WordPress helped me</h2>
<p>WordPress is the standard in the Industry for blogging and publishing content quickly. The dashboard is intuitive and easy to use. Admins can also add new users and specify – by selecting the appropriate role – their permissions.</p>
<p>WordPress exposes Rest APIs to help developers build integrations with WordPress itself and third parties services.</p>
<p>So I decided to integrate a WordPress blog with my client's static website by calling the <code>/wp/v2/posts</code> endpoint provided by WordPress APIs. In the next steps, I'll explain how I did it and why.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>First of all, I want to share the website I'll work on during this article. Nothing too fancy: I picked this Bootstrap static template:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/bootstrap_template.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we can divide the page into three different main sections:</p>
<ol>
<li>Company's presentation (image + tagline)</li>
<li>A call to action card (the grey area in the middle)</li>
<li>A row with three cards</li>
</ol>
<p>I'll integrate our WordPress blog in the third section.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/bootstrap_template_card.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Every post will be represented by a card, where users will be able to read the post title, the excerpt, and go to the post content by clicking the blue button "Read more". The button will open a modal where the post content will be displayed.</p>
<h2 id="heading-lets-see-how-our-wordpress-instance-works">Let's see how our WordPress instance works</h2>
<p>Let's have a look at our WordPress instance and see what we have. If I log into the dashboard and go to the posts section, I see that I've published three posts: Post No. 1, Post No. 2, and Post No. 3. </p>
<p>Every article has some "Lorem ipsum" content. So, at the end of this article, I expect these posts to be displayed in three different cards as mentioned above.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/elenco_post_wp.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-work-with-wordpress-apis">How to work with WordPress APIs</h2>
<p>WordPress APIs are well <a target="_blank" href="https://developer.wordpress.org/rest-api/">documented</a> and maintained by a huge and enthusiastic community. Let's see how I can handle posts with the APIs available. </p>
<p>So, once on the documentation page, I hit "Endpoint Reference" and then "posts". As I said before, I want to retrieve all the posts I published on my instance. I go to the "List Posts" and read "Query this endpoint to retrieve a collection of posts. The response you receive can be controlled and filtered using the URL query parameters below." </p>
<p>Sounds like this is what I'm looking for. According to the documentation, this is the request:</p>
<pre><code class="lang-terminal">https://&lt;BASE_URL&gt;/wp-json/wp/v2/posts
</code></pre>
<p>Before starting the implementation, I test it using Postman. This is what I get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/postman.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As expected, I get a JSON with the information related to the posts I created on my WordPress instance. </p>
<h2 id="heading-time-to-code">Time to Code</h2>
<p>To complete this implementation, I'll edit index.html and I'll create a new file called blog.js.</p>
<p>In index.html, I'll remove the static cards, add a loader to make it appear while waiting for the API call response and, and add an id – "wrapper" – to the DOM element I want the posts' cards to appear in. It looks like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"wrapper"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row gx-4 gx-lg-5"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">spinner</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"spinner-grow spinner-grow-lg"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"visually-hidden"</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>In the blog.js file I fetch the URL and the first <code>.then()</code> checks if the response is ok:</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">'https://&lt;BASE_URL&gt;/wp-json/wp/v2/posts'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) </span>{
    <span class="hljs-keyword">if</span> (response.ok) {
        <span class="hljs-keyword">return</span> response.json();
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.reject(response);
    }
})
</code></pre>
<p>using a second <code>then()</code> I remove from the DOM the spinner and map both the card and the modal for each post I find in the JSON. I choose to display just the latest three articles of the blog. It looks like this:</p>
<pre><code class="lang-javascript">.then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">data</span>) </span>{
    spinner.remove()
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {

        cardCreation = <span class="hljs-string">'&lt;div class="col-md-4 mb-5"&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;div class="card h-100"&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;div class="card-body"&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;h2 id="test" class="card-title"&gt;'</span> + data[i].title.rendered + <span class="hljs-string">'&lt;/h2&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;p class="card-text"&gt;'</span> + data[i].excerpt.rendered + <span class="hljs-string">'&lt;/p&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;/div&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;div class="card-footer"&gt;&lt;button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#modal-'</span> + data[i].id + <span class="hljs-string">'"&gt;Read More&lt;/button&gt;&lt;/div&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;/div&gt;'</span>
        cardCreation += <span class="hljs-string">'&lt;/div&gt;'</span>

        modalCreation = <span class="hljs-string">'&lt;div class="modal fade" id="modal-'</span> + data[i].id +<span class="hljs-string">'" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true"&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;div class="modal-dialog" role="document"&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;div class="modal-content"&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;div class="modal-header"&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;h5 class="modal-title" id="exampleModalLongTitle"&gt;'</span> + data[i].title.rendered + <span class="hljs-string">'&lt;/h5&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;/div&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;div class="modal-body"&gt;'</span> + data[i].content.rendered + <span class="hljs-string">'&lt;/div&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;div class="modal-footer"&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;button type="button" class="btn btn-secondary" data-dismiss="modal"&gt;Close&lt;/button&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;/div&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;/div&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;/div&gt;'</span>
        modalCreation += <span class="hljs-string">'&lt;/div&gt;'</span>

        <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#wrapper"</span>).insertAdjacentHTML(<span class="hljs-string">"beforeend"</span>,cardCreation)
        <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#wrapper"</span>).insertAdjacentHTML(<span class="hljs-string">"beforeend"</span>,modalCreation)
      }
})
</code></pre>
<p>In the end, I use the <code>catch()</code> method to handle errors. I decided to add a Bootstrap danger banner where I explain something went wrong and add a link to resources that users can find useful:</p>
<pre><code class="lang-javascript">.catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
    spinner.remove();
    errorMsg = <span class="hljs-string">'&lt;div class="alert alert-danger" role="alert"&gt;'</span>
    errorMsg += <span class="hljs-string">'Sorry, we can\'t retrieve posts at the moment. Please visit www.ourblog.com'</span>
    errorMsg += <span class="hljs-string">'&lt;/div&gt;'</span>

    <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#wrapper"</span>).insertAdjacentHTML(<span class="hljs-string">"beforeend"</span>,errorMsg)

    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">'Something went wrong.'</span>, err);
});
</code></pre>
<p>I open the index.html file with my browser and now I see the cards displaying the posts from my WordPress blog</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/bottstrap_con_post_wp.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To test if everything is working fine, I add a new post to my blog. This is what I see on my static website:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/4posts.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And if I hit "Read more", I see the full content of the post in a modal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/modal.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is how I integrated a static website and a WordPress blog. You can find the full code <a target="_blank" href="https://github.com/mventuri/How-to-integrate-a-static-website-with-WordPress">here</a>. I hope you found this article useful. Feel free to share it! 😀</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create an Excel File that Pulls Customer Data with WooCommerce and Python ]]>
                </title>
                <description>
                    <![CDATA[ “Hey, could you please send me our customers' emails? We’re about to launch a new marketing campaign and…we need them ASAP.” If you work in the Web department on a corporate level, you've probably heard this sentence hundreds of times. So, today I wa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-an-excel-file-with-customers-data-with-woocommerce-and-python/</link>
                <guid isPermaLink="false">66bdff5c7cdf166e835fce67</guid>
                
                    <category>
                        <![CDATA[ ecommerce ]]>
                    </category>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Fri, 08 Oct 2021 15:15:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/cover-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>“Hey, could you please send me our customers' emails? We’re about to launch a new marketing campaign and…we need them ASAP.”</p>
<p>If you work in the Web department on a corporate level, you've probably heard this sentence hundreds of times. So, today I want to share how I solved this issue for a company I worked at.</p>
<h2 id="heading-what-was-the-request">What Was the Request?</h2>
<p>We had an e-commerce app built with WooCommerce, that got thousands of orders every day worldwide. To register, users had to add their first name, last name, and email address. </p>
<p>Our marketing department asked my team to provide them with the email address and first names of all our customers to launch a new campaign. </p>
<p>I expected them to ask for a CSV file to upload contacts massively to their marketing platform. Instead, they told me they needed an Excel file since they had to edit it before going ahead with the campaign launch. </p>
<p>Once they assigned me the Jira issue, I was ready to start.</p>
<h2 id="heading-analyzing-the-problem">Analyzing the Problem</h2>
<p>WooCommerce provides users with the export functionality to get customers' data but it doesn’t generate an Excel file. It generates a CSV or an XML file.</p>
<p>When you work with a tool like WordPress, the first option you think about is using a plugin and get what you need. </p>
<p>I found a few options on the WordPress plugin directory, but there is a lot to consider every time you install a new plugin in your instance. You have to think about maintenance costs (consider every time a developer works on it, they log hours that affect your budget), security vulnerabilities, and – last but not the least – purchase approval can take a long time.  </p>
<p>I also considered a second option: downloading the CSV via the user interface and turning it into an Excel file by using one of the thousand services you can find online. </p>
<p>But using third parties services could break critical security and privacy policies and the final result is not always reliable. So I decided to go no further in this direction.</p>
<p>In the end, I thought developing a script was the best and fastest option to solve this task.  </p>
<p>WordPress provides developers with APIs. Many other plugins from the WordPress system provide APIs as well, and WooCommerce is not an exception. The <a target="_blank" href="https://docs.woocommerce.com/document/woocommerce-rest-api/">documentation</a> is robust and it offers links to libraries for the most used languages such as Node.js, Python, PHP, and Ruby.</p>
<p>I decided to go with Python and use this technology to develop a script that generates an Excel file with the following structure:</p>
<ul>
<li>Two columns: first name and email</li>
<li>One row per customer</li>
</ul>
<p>I chose Python for several reasons: there are hundreds of libraries that can help you get get the job done, it is flexible, and it is very useful when it comes to handling data.</p>
<p>I also decided to use Pandas and Openpyxl to handle data and create the Excel file.</p>
<h2 id="heading-before-coding-lets-get-what-we-need">Before coding, let’s get what we need</h2>
<p>To work with the WooCommerce API, I need to generate the APIs keys to work with. You can get more info on WooCommerce official <a target="_blank" href="https://docs.woocommerce.com/document/woocommerce-rest-api/">documentation</a>. </p>
<p>First, you need to log into your WooCommerce instance, and then go to WooCommerce &gt; Settings &gt; Advanced &gt; REST API.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/0-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then I'll give it a brief description, choose the user I want to generate the API for, choose the permissions granted (Read/Write or both), and then hit “Generate API key”.</p>
<p>Next, I’ll get the Consumer Key and the Consumer Secret:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/screencapture-marcoventuritest-it-wooTest-wp-admin-admin-php-2021-10-06-17_19_38.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-prepare-the-environment">How to Prepare the Environment</h2>
<p>The very first thing I did was add the necessary libraries to develop my script. I started with the Python library for WooCommerce. To install it, I ran this command:</p>
<pre><code class="lang-python">pip install woocommerce
</code></pre>
<p>Good. Now I'll go ahead and install Pandas, a data analysis and manipulation tool for Python:</p>
<pre><code class="lang-python">pip install pandas
</code></pre>
<p>After that, I installed Openpyxl, a Python library to read and write Excel files:</p>
<pre><code class="lang-python">pip install openpyxl
</code></pre>
<h2 id="heading-lets-code">Let’s code</h2>
<p>I made the API call using the API function provided by the WooCommerce Python library and I stored it in a variable. Then I passed the function the base URL of my WooCommerce website, the consumer key, the consumer secret, and the version.</p>
<pre><code class="lang-python">wcdata = API(
    url=<span class="hljs-string">'&lt;BASE_URL&gt;'</span>,
    consumer_key=<span class="hljs-string">'ck_XXXXXXXXXXXXXXXXXXXX'</span>,
    consumer_secret=<span class="hljs-string">'cs_XXXXXXXXXXXXXXXXXXXX'</span>,
    version=<span class="hljs-string">'wc/v3'</span>
)
</code></pre>
<p>Then I used the GET function to call the "customers" endpoint and I created locally a JSON file (“contacts.json”) with the data I got from the endpoint I called right before:</p>
<pre><code class="lang-python">newJson = wcdata.get(<span class="hljs-string">'customers'</span>).json()
<span class="hljs-keyword">with</span> open(<span class="hljs-string">'contacts.json'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> f:
    json.dump(newJson, f, ensure_ascii=<span class="hljs-literal">False</span>, indent=<span class="hljs-number">4</span>)
</code></pre>
<p>I converted it to a Pandas object and stored it in the "df_json" variable:</p>
<pre><code class="lang-python">df_json = pd.read_json(<span class="hljs-string">'contacts.json'</span>)
</code></pre>
<p>I used the <code>to_excel()</code> function to turn the object into an Excel file. I passed the function three arguments:</p>
<ul>
<li>The name of the file I was about to create</li>
<li>The index, set to “false” since I didn't want the record id to be printed on my file</li>
<li>The columns I wanted to print on my file (first_name and email)</li>
</ul>
<pre><code class="lang-python">df_json.to_excel(<span class="hljs-string">'customers_contacts.xlsx'</span>, index=<span class="hljs-literal">False</span>, columns=(<span class="hljs-string">'first_name'</span>, <span class="hljs-string">'email'</span>))
</code></pre>
<p>I ran the script and I got this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/6bis.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>That’s it. This is how I created an Excel file with customers' emails and first names with WooCommerce APIs and Python in less than 20 lines of code. </p>
<p>Of course, it is a script you can run via the command line when needed or you can also automate it to regularly generate reports about the e-commerce you and your team are running.</p>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>I also wanted to share some other content I found on the web while studying to develop this script. </p>
<p>The first one is a Stack Overflow <a target="_blank" href="https://stackoverflow.com/questions/12309269/how-do-i-write-json-data-to-a-file">question</a>. It helped me optimize my code while creating the JSON file. I really appreciated the chosen question, especially when it suggested how you can write a "nicer" JSON file on a modern system. </p>
<p>The second one is about Pandas. If you write Python code, one day or another, you'll have to deal with data and their manipulation. This <a target="_blank" href="https://www.marsja.se/how-to-convert-json-to-excel-python-pandas/">article</a> by Erik Marsja explains really well how you can convert your JSON file to Excel with Pandas. It provides readers with several tips on how they can use this powerful library to display the data they want in an efficient and effective way.</p>
<p>Feel free to share this post if you found it useful! You can also find the full code on this Github <a target="_blank" href="https://github.com/mventuri/-woocommerce-to-excel-python">repo</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
