<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Omer Lahav</title>
    <description>The latest articles on DEV Community by Omer Lahav (@omerlahav).</description>
    <link>https://dev.to/omerlahav</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F232921%2Feddd317d-5b8b-46ad-8752-6d1c6611b191.jpeg</url>
      <title>DEV Community: Omer Lahav</title>
      <link>https://dev.to/omerlahav</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omerlahav"/>
    <language>en</language>
    <item>
      <title>Submit a Form to a Google Spreadsheet</title>
      <dc:creator>Omer Lahav</dc:creator>
      <pubDate>Thu, 30 Jan 2020 12:23:09 +0000</pubDate>
      <link>https://dev.to/omerlahav/submit-a-form-to-a-google-spreadsheet-1bia</link>
      <guid>https://dev.to/omerlahav/submit-a-form-to-a-google-spreadsheet-1bia</guid>
      <description>&lt;p&gt;Lately, I created an HTML form where the results are sent to a Google spreadsheet. I used it for analytics purposes, but it's useful even just for keeping track of the form's results. After trying all kinds of solutions and even searching beyond the 2nd page on Google, I found something that worked for me and I thought worth sharing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; HTML and basic JavaScript knowledge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The credit for this solution goes to &lt;a href="https://github.com/jamiewilson" rel="noopener noreferrer"&gt;Jamie Wilson&lt;/a&gt; who created and uploaded it to &lt;a href="https://github.com/jamiewilson/form-to-google-sheets" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  First, Create the Spreadsheet
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://docs.google.com/spreadsheets" rel="noopener noreferrer"&gt;Google Sheets&lt;/a&gt; and &lt;code&gt;Start a new spreadsheet&lt;/code&gt; with the &lt;code&gt;Blank&lt;/code&gt; template.
Disclaimer: It doesn't really matter how you name the file.&lt;/li&gt;
&lt;li&gt;On the first row, write &lt;strong&gt;timestamp&lt;/strong&gt; on the first column and &lt;strong&gt;email&lt;/strong&gt; on the second column.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create a Google Apps Script
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click on &lt;code&gt;Tools &amp;gt; Script Editor…&lt;/code&gt; which should open a new tab.&lt;/li&gt;
&lt;li&gt;Name the script &lt;code&gt;Submit Form to Google Sheets&lt;/code&gt; or however you want for you to remember what the script does.&lt;/li&gt;
&lt;li&gt;Delete the &lt;code&gt;function myFunction() {}&lt;/code&gt; block withing the &lt;code&gt;Code.gs&lt;/code&gt; tab.&lt;/li&gt;
&lt;li&gt;Paste the following script in its place and &lt;code&gt;File &amp;gt; Save&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sheetName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sheet1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;scriptProp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PropertiesService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getScriptProperties&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;intialSetup&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;activeSpreadsheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SpreadsheetApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getActiveSpreadsheet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;scriptProp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;activeSpreadsheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;doPost&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LockService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getScriptLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tryLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SpreadsheetApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptProp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSheetByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sheetName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastColumn&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;getValues&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;nextRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextRow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setValues&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;newRow&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextRow&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMimeType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ContentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMimeType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ContentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;releaseLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you want to better understand what this script is doing, check out the &lt;a href="https://github.com/jamiewilson/form-to-google-sheets/blob/master/form-script-commented.js" rel="noopener noreferrer"&gt;&lt;code&gt;form-script-commented.js&lt;/code&gt;&lt;/a&gt; file in the repo for a detailed explanation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Run the setup function
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Now, go to &lt;code&gt;Run &amp;gt; Run Function &amp;gt; initialSetup&lt;/code&gt; to run this function.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;Authorization Required&lt;/code&gt; dialog, click on &lt;code&gt;Review Permissions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sign in or pick the Google account associated with this project.&lt;/li&gt;
&lt;li&gt;You should see a dialog that says &lt;code&gt;Hi {Your Name}, Submit Form to Google Sheets wants to...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then click &lt;code&gt;Allow&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Add a new project trigger
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click on &lt;code&gt;Edit &amp;gt; Current project’s triggers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the dialog click &lt;code&gt;No triggers set up. Click here to add one now&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the dropdowns select &lt;code&gt;doPost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set the events fields to &lt;code&gt;From spreadsheet&lt;/code&gt; and &lt;code&gt;On form submit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then click &lt;code&gt;Save&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Publish the project as a web app
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click on &lt;code&gt;Publish &amp;gt; Deploy as web app…&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;Project Version&lt;/code&gt; to &lt;code&gt;New&lt;/code&gt; and put &lt;code&gt;initial version&lt;/code&gt; in the input field below.&lt;/li&gt;
&lt;li&gt;Leave &lt;code&gt;Execute the app as:&lt;/code&gt; set to &lt;code&gt;Me(your@address.com)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;Who has access to the app:&lt;/code&gt; select &lt;code&gt;Anyone, even anonymous&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Deploy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the popup, copy the &lt;code&gt;Current web app URL&lt;/code&gt; from the dialog.&lt;/li&gt;
&lt;li&gt;And click &lt;code&gt;OK&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT!&lt;/strong&gt; If you have a custom domain with Gmail, you &lt;em&gt;might&lt;/em&gt; need to click &lt;strong&gt;OK&lt;/strong&gt;, refresh the page, and then go to &lt;code&gt;Publish &amp;gt; Deploy as web app…&lt;/code&gt; again to get the proper web app URL. It should look something like &lt;code&gt;https://script.google.com/a/yourdomain.com/macros/s/XXXX…&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Input your web app URL
&lt;/h3&gt;

&lt;p&gt;Open the file named &lt;code&gt;index.html&lt;/code&gt;. On line 7 replace &lt;code&gt;&amp;lt;SCRIPT URL&amp;gt;&lt;/code&gt; with your script url:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"submit-to-google-sheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;SCRIPT URL&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit-to-google-sheet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Success!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this script uses the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;Fetch API&lt;/a&gt;, a fairly new promise-based mechanism for making web requests. It makes a "POST" request to your script URL and uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData" rel="noopener noreferrer"&gt;FormData&lt;/a&gt; to pass in our data as URL parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding additional form data
&lt;/h3&gt;

&lt;p&gt;To capture additional data, you'll just need to create new columns with titles matching exactly the &lt;code&gt;name&lt;/code&gt; values from your form inputs. For example, if you want to add first and last name inputs, you'd give them &lt;code&gt;name&lt;/code&gt; values like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"submit-to-google-sheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"firstName"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"First Name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Last Name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can create new headers with the exact, case-sensitive &lt;code&gt;name&lt;/code&gt; values. Just go to the spreadsheet and add the names to the first row, each &lt;em&gt;name&lt;/em&gt; in a different column.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Polyfills
&lt;/h3&gt;

&lt;p&gt;Some of this stuff is not yet fully supported by browsers or doesn't work on older ones. Here are some polyfill options to use for better support.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/taylorhakes/promise-polyfill" rel="noopener noreferrer"&gt;Promise Polyfill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/github/fetch" rel="noopener noreferrer"&gt;Fetch Polyfill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jimmywarting/FormData" rel="noopener noreferrer"&gt;FormData Polyfill&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since the FormData polyfill is published as a Node package and needs to be compiled for browsers to work with, a good option for including these is using &lt;a href="https://wzrd.in/" rel="noopener noreferrer"&gt;Browserify's CDN called wzrd.in&lt;/a&gt;. This service compiles, minifies and serves the latest version of these scripts for us.&lt;/p&gt;

&lt;p&gt;You'll want to make sure these load before the main script handling the form submission. e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://wzrd.in/standalone/formdata-polyfill"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://wzrd.in/standalone/promise-polyfill@latest"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://wzrd.in/standalone/whatwg-fetch@latest"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;SCRIPT URL&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit-to-google-sheet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And... Yep, this is it.&lt;br&gt;
After trying several different methods to do this "simple" action, that's the only one that worked for me - so I hope it helps. Feel free to share it/save it for future use and feel free to comment in case you have ideas to improve it!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>google</category>
    </item>
    <item>
      <title>5 Things I've Learned From One WordPress Calculator Plugin</title>
      <dc:creator>Omer Lahav</dc:creator>
      <pubDate>Mon, 16 Dec 2019 16:56:26 +0000</pubDate>
      <link>https://dev.to/omerlahav/5-things-i-ve-learned-from-one-wordpress-calculator-plugin-55og</link>
      <guid>https://dev.to/omerlahav/5-things-i-ve-learned-from-one-wordpress-calculator-plugin-55og</guid>
      <description>&lt;p&gt;I work for the largest online tech magazine in Israel as a full-stack developer. The fun part is that we always try to go the extra mile as part of our agenda. So when one of our partners reached out and said they'd like to implement a salary calculator in our WordPress based website, we said "sure!". They get exposure, our readers get value - everyone's happy. The really fun part? They got the data, and they wanted &lt;strong&gt;me&lt;/strong&gt; to build it.&lt;/p&gt;

&lt;p&gt;The thing is... I've started playing with software development ever since middle school. Yet, I started doing it professionally only a year and a half ago, when I graduated college - so I'm dealing with a lot of new problems. Therefore, I decided to write this article to help beginners like me with how they approach problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Plan ahead. It will save you more time than you think
&lt;/h3&gt;

&lt;p&gt;The data I got from our clients was given to me in an Excel spreadsheet. Different categories, different titles, different conditions for display - &lt;em&gt;All in one spreadsheet of one file.&lt;/em&gt; Dealing with Excel files isn't my first priority, so I've started thinking about how should I manage the data in order to easily use it in the plugin. In one of my last projects, I imported data from an external JSON file so I decided to play a bit more with this familiar format.&lt;/p&gt;

&lt;p&gt;The problem was the need to rearrange everything in a proper way in order to differentiate the different categories and conditions for a certain salary. So I asked my developers friends &lt;a href="https://twitter.com/OmerLahav/status/1173574852374147073?s=20" rel="noopener noreferrer"&gt;on Twitter&lt;/a&gt; and from seriously thinking about creating a 3-dimensional array in JSON, I figured an easier more logical way to arrange all the data. I even wrote part of the JSON file I plan to have in a notebook I have, just to be sure - and writing it manually actually made me find a mistake in the excel file.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The internet is full of shortcuts. &lt;em&gt;Use them!&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;It will probably be the most obvious part of this article, but nowadays - we have online tools for everything. You don't necessarily have to install an add-on in your local software, nor install something completely new - there's probably something online that does exactly what you want. After I looked for a proper tool on the first two pages of Google, I found this open-source &lt;a href="https://kinoar.github.io/xlsx-to-json/" rel="noopener noreferrer"&gt;XLSX-TO-JSON&lt;/a&gt; converter that's hosted on Github. It doesn't look anything fancy or requires any installment in your computer - but it definitely gets the job done.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Divide and conquer your plugin directory
&lt;/h3&gt;

&lt;p&gt;I've seen two main work methods when it comes to software development. Some developers try to gather all of their code into the least amount of files and folders as possible.&lt;/p&gt;

&lt;p&gt;I belong to the group that does the opposite.&lt;/p&gt;

&lt;p&gt;I built this calculator as a Wordpress plugin that creates a Wordpress' shortcode of the calculator that I can place wherever I want. The layout I used was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assets folder&lt;/strong&gt; - A folder that contains all CSS, JavaScript and the JSON files (including any related images) of the project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;config.php&lt;/strong&gt; - A file that contains constant variables relevant to the plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scriptsenqueue.php&lt;/strong&gt; - A file that enqueues all the CSS &amp;amp; JavaScript files that are relevant to this plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;main-plugin-file.php&lt;/strong&gt; - The main file of the plugins, that contains the relevant comments for a Wordpress plugin, and import all the other files in the folder. In this case, I put the shortcode content in this file, even though I could split it to another file as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why such division is necessary? Even with such a small feature, there might be problems in different places like the shortcode's content, the CSS settings, the JavaScript's logic... No matter what's the problem, you'll know exactly where to find it.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Accept any small feature as a challenge
&lt;/h3&gt;

&lt;p&gt;In the beginning, the initial request was: "Make us a salary calculator". They haven't told us anything besides they have the data for us, but they want us to develop it for them since it's our website and we're familiar with its infrastructure. I sent them the first draft of how the calculator would be - and I got gazillion other requests in return. From "make it look more like this other calculator", to "add an icon to make it pretty and make it spin!" and even "add a statistics feature to it!" after it was already uploaded to production (I'm not kidding).&lt;/p&gt;

&lt;p&gt;Nonetheless, because of this one plugin - I've dealt with CSS' animations, integration to a Google spreadsheet, Wordpress shortcode &amp;amp; plugin creation, and JSON files related functions in jQuery. No matter which assignment you're asked to do - take it, because you might learn from it more than you think.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Dealing with clients is sometimes just part of the job
&lt;/h3&gt;

&lt;p&gt;Depends on your workplace, you won't always have to deal with clients. Sometimes you will get requirements from your project/product manager, and sometimes you'll have to talk to the clients directly. Talking to someone who's not necessarily technical might be a bit challenging, but that's a skill you should have sooner or later.&lt;/p&gt;

&lt;p&gt;Whether you'll begin to work freelance, become a product/project manager or even just a senior developer - having the skill of talking to clients can help you deal better with people, and knowing how such people think can help you define your problems and needs better, and because of that - create better products.&lt;/p&gt;

&lt;h4&gt;
  
  
  Take as many opportunities
&lt;/h4&gt;

&lt;p&gt;Like plenty of other junior developers, I'm familiar with the thirst for developing gigantic stuff. My humble recommendation for any other junior developer - enjoy those small projects. They most definitely will help you in the long term.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credit:&lt;/strong&gt; And as a living proof for lesson #2 of this article, how do you think I made this article's banner? A small hint:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/christopherkade" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55600%2Fba50a666-cf29-4825-b3ff-ba6467b492de.jpeg" alt="christopherkade"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/christopherkade/introducing-a-banner-generator-for-your-articles-on-dev-353a" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Introducing a banner generator for your articles on DEV&lt;/h2&gt;
      &lt;h3&gt;Christopher Kade ・ May 31 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#meta&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;What do you guys think? Would you recommend anything differently, or do you have anything else to add for beginners?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
