If you’ve ever imported a spreadsheet into HubSpot and watched a value like 34.55 turn into 3,455%, you’re not alone. This happens specifically with Percentage properties because HubSpot’s internal expectations don’t match how many spreadsheets store percent-like numbers.
1) The Issue: Mismatched Expectations for Percentage Fields
HubSpot Percentage properties expect the stored value to be a decimal between 0 and 1, and HubSpot displays it as a percentage by multiplying by 100.
Example:
- To display 34.55%, HubSpot expects you to store 0.3455.
- If you import 34.55 into a Percentage property, HubSpot treats it as 34.55 (decimal) and displays it as 3455%.
In other words, the spreadsheet value 34.55 often represents “34.55%” in a human sense, but HubSpot interprets it as the decimal value 34.55 and converts it to percent for display.
2) Prevent It Before Import
The easiest solution is to transform your spreadsheet values into the decimal form HubSpot expects before importing.
If your spreadsheet has a column where 34.55 is meant to represent 34.55%, create a helper column and divide by 100.
Excel / Google Sheets formula:
=B2/100
This converts:
- 34.55 → 0.3455 (HubSpot will display 34.55%)
- 11 → 0.11 (HubSpot will display 11%)
Import steps:
- Add the formula down the entire column.
- Copy the results.
- Paste as values (so you aren’t importing formulas).
- Import into HubSpot, mapping the converted column to your Percentage property.
3) Fix It After It’s Already Imported
If the data is already in HubSpot and showing inflated percentages (like 3,455%), you have a few clean options. Which one is best depends on whether you want to preserve the original value and how much data you need to fix.
Option A: Create a Calculated/Helper Field, Then Copy Back
If you want a safer fix (especially for larger datasets), create a new helper property and calculate the corrected value, then copy it back over.
Approach:
- Create a new property (for example:
percent_of_something_fixed). - Populate it with the corrected decimal value (divide the “bad” value by 100).
- Once verified, either:
- Replace the original value (by importing the fixed values and mapping back), or
- Rename fields so the fixed property becomes your primary field.
This approach makes it easy to validate your corrected numbers before overwriting anything important.
Option B: Rename Fields and Move Forward
If you don’t want to overwrite the original imported data, you can:
- Create a new “correct” Percentage property,
- Populate it correctly, and
- Update your lists, reports, and workflows to use the new property.
This preserves the original dataset for reference, while allowing you to standardize going forward.
Option C: Fix In-Place With a Workflow and Custom Coded Action
If you want HubSpot to correct the value automatically (especially across many records), you can use a workflow with a Custom Coded Action that rewrites the property in the correct format.
High-level logic:
- If the value is > 1, treat it like a human percent (34.55) and divide by 100 to get 0.3455.
- If the value is between 0 and 1, assume it’s already correct and leave it alone.
Setup pointers
- Create a HubSpot Private App (for API access).
- In HubSpot: Settings → Integrations → Private Apps
- Create an app and copy the access token.
- Make sure the app has permission to edit contacts (or the relevant object type).
- Create a contact-based workflow (or company/deal workflow if needed).
- Enrollment criteria (recommended): enroll only records where the bad import is likely:
percent_of_somethingis knownpercent_of_somethingis greater than 1
- Add a Custom Coded Action to the workflow.
- Add your Private App token as a Secret in the coded action.
- Create a Secret named
HS_PRIVATE_TOKEN(or update the code to match your secret name).
- Create a Secret named
- Most important step: add the relevant properties to the coded action’s Input fields.
- Add
hs_object_id - Add
percent_of_something(must be the internal name)
- Add
Custom coded action example (Node.js)
const hubspot = require("@hubspot/api-client");
exports.main = async (event, callback) => {
const token = process.env.HS_PRIVATE_TOKEN; // Secret name must match exactly
const propName = "percent_of_something"; // Must be internal name
const contactId =
event.inputFields?.hs_object_id ||
event.object?.objectId ||
event.objectId;
if (!token) {
return callback({ outputFields: { status: "error", error: "Missing HS_PRIVATE_TOKEN secret" } });
}
if (!contactId) {
return callback({ outputFields: { status: "error", error: "Missing contactId" } });
}
const hubspotClient = new hubspot.Client({ accessToken: token });
// NOTE: Requires propName to be included in "Input fields" for the coded action
const raw = event.inputFields?.[propName];
if (raw === null || raw === undefined || raw === "") {
return callback({ outputFields: { status: "no_value" } });
}
const asString = String(raw).trim().replace("%", "");
const num = Number(asString);
if (!Number.isFinite(num)) {
return callback({ outputFields: { status: "not_a_number", raw: String(raw) } });
}
// Convert 34.55 -> 0.3455, leave 0.3455 unchanged
let fixed = num > 1 ? num / 100 : num;
fixed = Math.round(fixed * 1e6) / 1e6;
await hubspotClient.crm.contacts.basicApi.update(contactId, {
properties: { [propName]: String(fixed) },
});
return callback({
outputFields: {
status: "updated",
from: String(raw),
to: String(fixed),
contactId: String(contactId),
},
});
};
Notes:
- Confirm the property’s internal name in: Settings → Properties → open the property → Internal name
- In workflow history, check the coded action output to confirm updates and troubleshoot errors.
Summary
- HubSpot Percentage properties store values as decimals (0–1) and display them as percent (×100).
- Prevent the issue by dividing spreadsheet values by 100 before import.
- If it’s already imported incorrectly, fix it with a helper/calculated field, field renaming, or a workflow with a custom coded action.
