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.

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
Go to https://id.atlassian.com/manage-profile/security/api-tokens
Log in with your Jira service account
Click Create API token
Copy the generated token
Add Credential in n8n
In the Jira node, click Create new credential
Fill in the fields:
| Field | Value |
|---|---|
| (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)
Make sure the 'to Jira' sheet is empty (only header row)
Click 'Test Workflow' or 'Execute Workflow' in n8n
Verify that all rows are processed and tickets appear in Jira
Check that the 'to Jira' sheet is now populated with ticket IDs
Second Run (Duplicate Check)
Run the workflow again without adding new data
Expected result: 0 new tickets created (all rows already in 'to Jira')
The Code node should output 0 items
Adding New Data
Add a new row to Form Responses 1 sheet
Run the workflow
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.



