Skip to main content

We are configuring the Productboard integration within Gainsight CS to allow for us to use the product feature requests. We have imported and mapped all of the companies and now need to import the list of notes so we have historical information. The instructions (https://support.gainsight.com/gainsight_nxt/Product_Requests/Product_Requests_-_Productboard_Integration/Configure_Product_Requests#Productboard_Data_Management) advise to log a support ticket with Productboard which I didn’t want to do.

Instead, I wrote a PowerShell script to pull the data I need, and export it as a CSV which I can import into Gainsight. I thought the script could be useful for someone else in the future, so here it is:

 

# Set the API endpoint and headers
$apiUrl = "https://api.productboard.com/notes"
$headers = @{
'X-Version' = '1'
'accept' = 'application/json'
'authorization' = 'Bearer token' # Replace 'token' with your actual token
}

# Set the output CSV file path
$outputCsv = "ProductboardNotes.csv"

# Initialize a counter for processed notes
$processedNotes = 0

# Function to handle pagination and data extraction
function Get-NotesData {
param (
string]$apiUrl,
string]$pageCursor = $null,
int]$totalNotes = 0
)

# Create query parameters with the cursor if available
$queryParams = @{}
if ($pageCursor) {
$queryParams = @{
cursor = $pageCursor
}
}

# Make the API request
$response = Invoke-RestMethod -Uri $apiUrl -Headers $headers -Method Get -Body $queryParams

# Get the total number of notes (for progress display)
if ($totalNotes -eq 0 -and $response.totalResults) {
$totalNotes = $response.totalResults
}

# Process each note in the response
foreach ($note in $response.data) {
# Extract all fields from the note
$createdByName = if ($note.createdBy -and $note.createdBy.name) { $note.createdBy.name } else { $null }
$createdByEmail = if ($note.createdBy -and $note.createdBy.email) { $note.createdBy.email } else { $null }
$companyId = if ($note.company) { $note.company.id } else { $null }
$tags = if ($note.tags) { ($note.tags -join ", ") } else { $null }
$features = if ($note.features) { ($note.features -join ", ") } else { $null }
$followers = if ($note.followers) { ($note.followers -join ", ") } else { $null }

$noteObject = pscustomobject]@{
'ID' = $note.id
'Title' = $note.title
'Content' = $note.content
'Created At' = $note.createdAt
'Updated At' = $note.updatedAt
'State' = $note.state
'Display URL' = $note.displayUrl
'External Display URL' = $note.externalDisplayUrl
'Source Origin' = $note.source.origin
'Source Record ID' = $note.source.record_id
'Company ID' = $companyId
'Tags' = $tags
'Features' = $features
'Followers' = $followers
'Created By Name' = $createdByName
'Created By Email' = $createdByEmail
}

# Write the note to the CSV (append mode)
$noteObject | Export-Csv -Path $outputCsv -Append -NoTypeInformation

# Increment processed notes counter and show progress
$processedNotes++
Write-Progress -Activity "Processing notes" -Status "$processedNotes of $totalNotes processed" -PercentComplete (($processedNotes / $totalNotes) * 100)
}

# Check if there's a next page and continue fetching data
if ($response.pageCursor) {
Get-NotesData -apiUrl $apiUrl -pageCursor $response.pageCursor -totalNotes $totalNotes
}
}

# Prepare the CSV file by writing the header (if the file doesn't exist)
if (-not (Test-Path $outputCsv)) {
$header = pscustomobject]@{
'ID' = ""
'Title' = ""
'Content' = ""
'Created At' = ""
'Updated At' = ""
'State' = ""
'Display URL' = ""
'External Display URL' = ""
'Source Origin' = ""
'Source Record ID' = ""
'Company ID' = ""
'Tags' = ""
'Features' = ""
'Followers' = ""
'Created By Name' = ""
'Created By Email' = ""
}
$header | Export-Csv -Path $outputCsv -NoTypeInformation
}

# Call the function to get all notes
Get-NotesData -apiUrl $apiUrl

Write-Host "Data export completed. Check the file: $outputCsv"

Hope it helps!

Be the first to reply!

Reply