CRM

Nick_Trendline
Contributor

Workflow for First Deal Closed Date

SOLVE

Hi HS Community,

 

Does anyone know if a workflow could accomplish the following by auto-populating a custom property on the Company object?

 

The close date of the first deal for a company.

 

Thanks.
Nick

2 Accepted solutions
MFrankJohnson
Solution
Thought Leader

Workflow for First Deal Closed Date

SOLVE

Probably best to use the API endpoints to get the data and determine which associated deal is ... first! This would be the best method for both current and past deals, and could be built to manage company objects for which there were multiple associated deals. (important)


Otherwise, we'd need to use at least two workflows ... GOING FORWARD.

  • a company workflow to identify when a company had precisely 1 associated deal.
  • a custom deal property to FLAG that first deal.
  • a deal workflow to copy the associated FIRST deal close date to the company.


The proposed two-workflow solution above would NOT work for companies that have multiple deals. In the case of companies with more than one deal, don't see a way (in workflows) to iterate through all deals for that specific company within the same workflow enrollment.


Interested to hear feedback from others. Good luck with your project.

 

Note: Please search for recent posts as HubSpot evolves to be the #1 CRM platform of choice world-wide.

 

Hope that helps.

 

Be well,
Frank


www.mfrankjohnson.com

View solution in original post

joshm
Solution
Participant

Workflow for First Deal Closed Date

SOLVE

Hi @Nick_Trendline, I wanted to provide the solution I set up for finding a Company's first deal details. Hopefully, others who are still searching for a solution will find this useful. I created a script that finds the first Deal and adds key properties to corresponding properties for the Company. It does require Ops Hub so you can use a Custom Code action in the workflow. You will also need to create a private app (super easy). The one limitation is setting the first deal for companies that have an excessive (thousands) of Deals where API limits will be hit.

 

Here are the steps:

 

  1. Set up private app
  2. Create Company workflow using a Custom Code action

Go to Settings, Integrations, Private Apps, and create a private app. These are the scopes I used for the Private App.

joshm_0-1744040719624.png

 

This is my setup for the custom code action. Define the properties you include in the code:

joshm_1-1744040901432.png

 

Next, add the code. I've pasted it below. You only need to update it to use your private app secret and the properties to get on the Deal and copy to on the Company. (All the Deal properties are HubSpot properties except product_line.)

 

Custom code:

const hubspot = require('@hubspot/api-client');

exports.main = async (event) => {
  const hubspotClient = new hubspot.Client({
    accessToken: process.env.[your_private_app_secret], // set your private app secret here
  });

  const companyId = event.inputFields['hs_object_id'];

  try {
    let after = undefined;
    const associationPageLimit = 100; // Keep under HubSpot batch limit
    let firstClosedDeal = null;

    while (!firstClosedDeal) {
      const associationsResponse = await hubspotClient.crm.associations.v4.basicApi.getPage(
        'companies',
        companyId,
        'deals',
        associationPageLimit,
        after
      );

      const associatedDealIds = associationsResponse.results.map(r => r.toObjectId);

      if (associatedDealIds.length === 0) break;

      // Ensure we never send more than 100 deals per batch read
      const safeChunks = [];
      while (associatedDealIds.length) {
        safeChunks.push(associatedDealIds.splice(0, 100));
      }

      for (const chunk of safeChunks) {
        const batchReadInput = {
          properties: ['closedate', 'amount_in_home_currency', 'hs_deal_stage_probability', 'createdate', 'product_line'],
          inputs: chunk.map(id => ({ id })),
        };

        const batchResponse = await hubspotClient.crm.deals.batchApi.read(batchReadInput);
        const deals = batchResponse.results;

        const closedDeals = deals
          .filter((deal) => {
            const probability = parseFloat(deal.properties.hs_deal_stage_probability);
            return probability === 1 || probability === 100;
          })
          .sort((a, b) => new Date(a.properties.createdate) - new Date(b.properties.createdate));

        if (closedDeals.length > 0) {
          firstClosedDeal = closedDeals[0];
          break;
        }
      }

      if (firstClosedDeal) break;

      // Handle pagination
      if (associationsResponse.paging?.next?.after) {
        after = associationsResponse.paging.next.after;
      } else {
        break;
      }
    }

    if (!firstClosedDeal) {
      console.log('No 100% probability deals found.');
      return;
    }

    const firstDealDate = firstClosedDeal.properties.closedate;
    const firstDealAmount = firstClosedDeal.properties.amount_in_home_currency;
	const firstDealProduct = firstClosedDeal.properties.product_line;

    console.log(`First closed deal: ${firstDealDate} | Amount: ${firstDealAmount} | Product: ${firstDealProduct}`);

    // Update the first closed deal to set the checkbox property 'first_deal' to true
    await hubspotClient.crm.deals.basicApi.update(firstClosedDeal.id, {
      properties: {
        first_deal: 'true'
      },
    });

    console.log(`First closed deal ${firstClosedDeal.id} updated with first_deal = true.`);

    await hubspotClient.crm.companies.basicApi.update(companyId, {
      properties: {
        first_deal_date: firstDealDate,
        first_deal_amount: firstDealAmount,
        first_deal_product: firstDealProduct,
      },
    });

    console.log('Company updated successfully.');
  } catch (error) {
    console.error('Error occurred:', error.message || JSON.stringify(error));
  }
};

 

View solution in original post

9 Replies 9
joshm
Solution
Participant

Workflow for First Deal Closed Date

SOLVE

Hi @Nick_Trendline, I wanted to provide the solution I set up for finding a Company's first deal details. Hopefully, others who are still searching for a solution will find this useful. I created a script that finds the first Deal and adds key properties to corresponding properties for the Company. It does require Ops Hub so you can use a Custom Code action in the workflow. You will also need to create a private app (super easy). The one limitation is setting the first deal for companies that have an excessive (thousands) of Deals where API limits will be hit.

 

Here are the steps:

 

  1. Set up private app
  2. Create Company workflow using a Custom Code action

Go to Settings, Integrations, Private Apps, and create a private app. These are the scopes I used for the Private App.

joshm_0-1744040719624.png

 

This is my setup for the custom code action. Define the properties you include in the code:

joshm_1-1744040901432.png

 

Next, add the code. I've pasted it below. You only need to update it to use your private app secret and the properties to get on the Deal and copy to on the Company. (All the Deal properties are HubSpot properties except product_line.)

 

Custom code:

const hubspot = require('@hubspot/api-client');

exports.main = async (event) => {
  const hubspotClient = new hubspot.Client({
    accessToken: process.env.[your_private_app_secret], // set your private app secret here
  });

  const companyId = event.inputFields['hs_object_id'];

  try {
    let after = undefined;
    const associationPageLimit = 100; // Keep under HubSpot batch limit
    let firstClosedDeal = null;

    while (!firstClosedDeal) {
      const associationsResponse = await hubspotClient.crm.associations.v4.basicApi.getPage(
        'companies',
        companyId,
        'deals',
        associationPageLimit,
        after
      );

      const associatedDealIds = associationsResponse.results.map(r => r.toObjectId);

      if (associatedDealIds.length === 0) break;

      // Ensure we never send more than 100 deals per batch read
      const safeChunks = [];
      while (associatedDealIds.length) {
        safeChunks.push(associatedDealIds.splice(0, 100));
      }

      for (const chunk of safeChunks) {
        const batchReadInput = {
          properties: ['closedate', 'amount_in_home_currency', 'hs_deal_stage_probability', 'createdate', 'product_line'],
          inputs: chunk.map(id => ({ id })),
        };

        const batchResponse = await hubspotClient.crm.deals.batchApi.read(batchReadInput);
        const deals = batchResponse.results;

        const closedDeals = deals
          .filter((deal) => {
            const probability = parseFloat(deal.properties.hs_deal_stage_probability);
            return probability === 1 || probability === 100;
          })
          .sort((a, b) => new Date(a.properties.createdate) - new Date(b.properties.createdate));

        if (closedDeals.length > 0) {
          firstClosedDeal = closedDeals[0];
          break;
        }
      }

      if (firstClosedDeal) break;

      // Handle pagination
      if (associationsResponse.paging?.next?.after) {
        after = associationsResponse.paging.next.after;
      } else {
        break;
      }
    }

    if (!firstClosedDeal) {
      console.log('No 100% probability deals found.');
      return;
    }

    const firstDealDate = firstClosedDeal.properties.closedate;
    const firstDealAmount = firstClosedDeal.properties.amount_in_home_currency;
	const firstDealProduct = firstClosedDeal.properties.product_line;

    console.log(`First closed deal: ${firstDealDate} | Amount: ${firstDealAmount} | Product: ${firstDealProduct}`);

    // Update the first closed deal to set the checkbox property 'first_deal' to true
    await hubspotClient.crm.deals.basicApi.update(firstClosedDeal.id, {
      properties: {
        first_deal: 'true'
      },
    });

    console.log(`First closed deal ${firstClosedDeal.id} updated with first_deal = true.`);

    await hubspotClient.crm.companies.basicApi.update(companyId, {
      properties: {
        first_deal_date: firstDealDate,
        first_deal_amount: firstDealAmount,
        first_deal_product: firstDealProduct,
      },
    });

    console.log('Company updated successfully.');
  } catch (error) {
    console.error('Error occurred:', error.message || JSON.stringify(error));
  }
};

 

Lucinda
Contributor

Workflow for First Deal Closed Date

SOLVE

I would really like to see HubSpot come up with a first deal won date property. We have multiple business units on one instance of HubSpot and I want to be able to report on Companies that are completely new to the Group e.g. a list of Companies that had their first deal won within a specific timeframe. 

0 Upvotes
HakonXL
Participant

Workflow for First Deal Closed Date

SOLVE

Hi, I recently had this problem and found that there is a property for this. Under company there is a property called "Closed date". It will be automatically set when the first deal is closed won for that company.

0 Upvotes
DianaGomez
Community Manager
Community Manager

Workflow for First Deal Closed Date

SOLVE

Hi @Lucinda hope you are doing well!

 

I encourage you to create the idea here in our ideas' forum, this way it will have more chances to be implemented in the future. 

 

Best,

Diana


loop Loop Marketing is a new four-stage approach that combines AI efficiency and human authenticity to drive growth.
Learn More

0 Upvotes
Nick_Trendline
Contributor

Workflow for First Deal Closed Date

SOLVE

Hi @kelseyingram392  - we didn't end up implementing anything (yet).  Without using the API solution, it looks as though the result would be manual entry in a new custom property.

kelseyingram392
Contributor | Platinum Partner
Contributor | Platinum Partner

Workflow for First Deal Closed Date

SOLVE

Wild that this functionality doesn't exist natively. HubSpot please please figure this out! This is standard functionality if you want to compete with other CRMs. 

kelseyingram392
Contributor | Platinum Partner
Contributor | Platinum Partner

Workflow for First Deal Closed Date

SOLVE

@Nick_Trendline what solution did you end up going with for this requirement? 

0 Upvotes
MFrankJohnson
Solution
Thought Leader

Workflow for First Deal Closed Date

SOLVE

Probably best to use the API endpoints to get the data and determine which associated deal is ... first! This would be the best method for both current and past deals, and could be built to manage company objects for which there were multiple associated deals. (important)


Otherwise, we'd need to use at least two workflows ... GOING FORWARD.

  • a company workflow to identify when a company had precisely 1 associated deal.
  • a custom deal property to FLAG that first deal.
  • a deal workflow to copy the associated FIRST deal close date to the company.


The proposed two-workflow solution above would NOT work for companies that have multiple deals. In the case of companies with more than one deal, don't see a way (in workflows) to iterate through all deals for that specific company within the same workflow enrollment.


Interested to hear feedback from others. Good luck with your project.

 

Note: Please search for recent posts as HubSpot evolves to be the #1 CRM platform of choice world-wide.

 

Hope that helps.

 

Be well,
Frank


www.mfrankjohnson.com
Nick_Trendline
Contributor

Workflow for First Deal Closed Date

SOLVE

Thanks for this, Frank.  Interesting suggestions.  Not sure we want to put the effort forth for an API at this point, and it's likely we'll have multiple deals for a company.  I'll ponder these a bit longer.  
Thanks again.
Nick