Skip to main content

Command Palette

Search for a command to run...

Auto-Create Jira Tickets from Google Sheets

This tutorial walks you through building an automated workflow using n8n that reads contact data from a Google Sheets spreadsheet and automatically creates tickets in Jira Work Management — without duplication.

Updated
7 min read
Auto-Create Jira Tickets from Google Sheets
Y
I believe the best way to learn is by building, breaking, and documenting the process. Here, I share my journey and practical lessons along the way.

What You Will Build

  • A scheduled n8n workflow that runs automatically

  • Reads data from Google Sheets

  • Filters only new rows that haven't been processed yet

  • Creates Jira tickets with all required fields

  • Logs processed tickets to a tracking sheet to prevent duplicates

Prerequisites

  • Access to n8n (self-hosted or cloud)

  • Google Sheets

  • Jira Work Management account with API token

  • Project Key in Jira (in this example: TPSCI)

Step 1: Prepare Your Google Sheets

You need two sheets inside your Google Sheets document:

Sheet 1 — Form Responses 1

This is your main data source. Make sure it contains these columns:

Column Description
Timestamp Auto-filled by Google Forms
Email Address Respondent's email
Company Name Third-party company name
Full Name Contact person's full name
Start-date Contract start date
End-date Contract end date
Project Name Name of the project
Describe about the project Project description

Sheet 2 — to Jira

Create a new sheet named 'to Jira' inside the same document. Add these headers in Row 1:

A: Email Address B: Row Number C: Jira Ticket ID D: Created At E: Status

Tip: This sheet acts as a log of all processed rows. n8n will check this sheet before creating new tickets to avoid duplicates.

Step 2: Set Up n8n Workflow

Node 1 — Schedule Trigger

This node triggers the workflow automatically on a schedule.

  • Click + to add a node → search Schedule Trigger

  • Set your preferred interval (e.g., every 1 hour or every day)

Node 2 — Form Response1 (Google Sheets)

Reads all rows from your main data sheet.

  • Add node: Google Sheets

  • Operation: Get Row(s)

  • Document: Select your spreadsheet

  • Sheet: Form Responses 1

  • Rename this node to: Form Response1

Node 3 — to Jira (Google Sheets)

Reads already-processed rows from the tracking sheet.

  • Add another Google Sheets node

  • Operation: Get Row(s)

  • Document: Same spreadsheet

  • Sheet: to Jira

  • Rename this node to: to Jira

Note: Both Google Sheets nodes should be connected from the Schedule Trigger as parallel branches.

Step 3: Add Merge Node

The Merge node ensures both Google Sheets nodes finish before proceeding.

  • Add node: Merge

  • Connect Form Response1 → Input 1 of Merge

  • Connect to Jira → Input 2 of Merge

Merge Node Configuration

Setting Value
Mode Combine
Combine By Position
Number of Inputs 2
Include Any Unpaired Items ON (toggle enabled)

Tip: 'Include Any Unpaired Items' must be ON — this allows the workflow to continue even when the 'to Jira' sheet is empty.

Step 4: Add Code Node (Filter & Convert)

This JavaScript node filters out already-processed rows and converts date formats.

  • Add node: Code

  • Mode: Run Once for All Items

  • Language: JavaScript

JavaScript Code

// Data dari Form Responses 1
const allRows = $('Form Response1').all();


// Row numbers already processed (from 'to Jira' sheet)
let processedRows = [];
try {
  processedRows = $('to Jira').all()
    .map(item => Number(item.json['Row Number']))
    .filter(r => r);
} catch (e) {
  processedRows = [];
}


// Convert date format M/D/YYYY → YYYY-MM-DD
const convertDate = (dateStr) => {
  if (!dateStr) return '';
  const d = new Date(dateStr);
  if (isNaN(d)) return '';
  return d.toISOString().split('T')[0];
};


// Filter new rows + convert dates
const newRows = allRows
  .filter(item => !processedRows.includes(Number(item.json['row_number'])))
  .map(item => ({
    json: {
      ...item.json,
      'Start-date': convertDate(
        item.json['Start-date']),
      'End-date': convertDate(
        item.json['End-date'])
    }
  }));


return newRows;

Tip: This code uses Row Number (not Email Address) as the unique identifier, since one person can submit multiple forms for different projects.

Step 5: Set Up Jira Credential

Before adding the Jira node, set up your credential.

Create Jira API Token

  1. Go to https://id.atlassian.com/manage-profile/security/api-tokens

  2. Log in with your Jira service account

  3. Click Create API token

  4. Copy the generated token

Add Credential in n8n

  1. In the Jira node, click Create new credential

  2. Fill in the fields:

Field Value
Email (your email account)
API Token Paste your API token here
Domain (your jira instance)

Note: Make sure the domain includes https:// — without it, you will get an 'Invalid URL' error.

Step 6: Configure Jira Node — Create Issue

Add a Jira Software node after the Code node.

  • Resource: Issue

  • Operation: Create

Basic Parameters

Field Value
Project TPSCI (select from list)
Issue Type Task
Summary {{$json["Project Name"]}}
Description {{$json["Describe about the project in PT Krom Bank Tbk"]}}

Custom Fields

Click Add Field → Custom Fields, then add each field below:

Custom Field Value Expression
Company Name {{ $json['Company Name'] }}
Email Address {{ $json['Email Address'] }}
Full Name {{ $json['Full Name'] }}
Start date {{ $json['Start-date'] }}
End date {{ $json['End-date'] }}
Project Name {{ $json['Project Name'] }}

Note: Start date and End date must be in YYYY-MM-DD format. The Code node in Step 4 handles this conversion automatically.

Step 7: Append Processed Rows to 'to Jira' Sheet

After creating the Jira ticket, log the result to prevent duplicate creation on the next run.

  • Add node: Google Sheets

  • Operation: Append Row

  • Document: Same spreadsheet

  • Sheet: to Jira

Column Mapping

Column Value Expression
Email Address {{ $('Code in JavaScript').item.json['Email Address'] }}
Row Number {{ $('Code in JavaScript').item.json.row_number }}
Jira Ticket ID {{ $json.key }}
Created At {{ $now }}
Status Done

Tip: \(json.key gives you the Jira ticket key (e.g., TPSCI-1), while \)json.id gives the numeric ID. Always use key for readability.

Step 8: Final Workflow Overview

Your complete workflow should look like this:

# Node Purpose
1 Schedule Trigger Triggers workflow on schedule
2 Form Response1 (Google Sheets) Reads all rows from main data sheet
3 to Jira (Google Sheets) Reads already-processed rows
4 Merge (Combine + Position) Waits for both sheets to load
5 Code in JavaScript Filters new rows + converts dates
6 Create an issue (Jira) Creates ticket in Jira project TPSCI
7 Append row in sheet Logs processed rows to prevent duplicates

Step 9: Testing the Workflow

Follow these steps to test your workflow before activating it.

First Run (Fresh Start)

  1. Make sure the 'to Jira' sheet is empty (only header row)

  2. Click 'Test Workflow' or 'Execute Workflow' in n8n

  3. Verify that all rows are processed and tickets appear in Jira

  4. Check that the 'to Jira' sheet is now populated with ticket IDs

Second Run (Duplicate Check)

  1. Run the workflow again without adding new data

  2. Expected result: 0 new tickets created (all rows already in 'to Jira')

  3. The Code node should output 0 items

Adding New Data

  1. Add a new row to Form Responses 1 sheet

  2. Run the workflow

  3. Expected result: Only 1 new ticket created for the new row

Tip: Always test with a small dataset first. Once confirmed working, activate the Schedule Trigger to run automatically.

1 views