Reminder: v201611 will be sunset on November 30, 2017.

DFP Sales Manager Workflows

This guide explains ‘what a workflow request is,‘ what the two different kinds of workflow requests are, and walks through the creation of WorkflowApprovalRequest and WorkflowExternalConditionRequest objects in the API.

Primer

Workflows in DFP Sales Manager are sets of rules a proposal must pass through to be sold. For example, if the publisher requires all proposals reserving more than 1000 impressions to be approved by someone in their company, they would define a WorkflowRequest in the DFP Sales Manager UI to provide that validation.

There are two types of WorkflowRequests:

  • WorkflowApprovalRequest objects will require an approval action, either by a frontend user or an API request, before they will continue in the workflow chain.
  • WorkflowExternalConditionRequest objects will remain pending until an external system performs some logic outside of DFP to decide whether to trigger or skip the next action in the workflow chain. This type of request is for use with publisher workflows that are too complex to be defined using system-only rules.
Workflows are associated with RateCard objects and impose their rules on all proposals that use that rate card.

Fetching workflow requests

In most cases, when interacting with workflow requests, you will fetch and run through the validation of specific workflow requests belonging to a single proposal. Since a workflow might include both approval and external condition type requests, the type must be passed into the query statement.

To see all pending workflow external condition requests on a proposal, instantiate the WorkflowRequestServiceInterface:

Java

  // Get the WorkflowRequestService.
  WorkflowRequestServiceInterface workflowRequestService =
      dfpServices.get(session, WorkflowRequestServiceInterface.class);
    

For workflow approval requests, filter on WORKFLOW_APPROVAL_REQUEST type, on entity type PROPOSAL, and on an ID of a particular Proposal that is in PENDING_APPROVAL approvalStatus.

Java

  // Create a statement to select workflow approval requests for a proposal.
  StatementBuilder statementBuilder = new StatementBuilder()
      .where("WHERE entityId = :entityId and entityType = :entityType "
          + "and type = :type and approvalStatus = :approvalStatus")
      .orderBy("id ASC")
      .limit(StatementBuilder.SUGGESTED_PAGE_LIMIT)
      .withBindVariableValue("entityId", proposalId)
      .withBindVariableValue("entityType", WorkflowEntityType.PROPOSAL.toString())
      .withBindVariableValue("approvalStatus",
          WorkflowApprovalRequestStatus.PENDING_APPROVAL.toString())
      .withBindVariableValue("type", WorkflowRequestType.WORKFLOW_APPROVAL_REQUEST.toString());
    

For workflow external condition requests, filter on WORKFLOW_EXTERNAL_CONDITION_REQUEST type, on entity type PROPOSAL, and on an ID of a particular Proposal that is in PENDING conditionStatus.

Java

  // Create a statement to select workflow external condition requests for a proposal.
  StatementBuilder statementBuilder = new StatementBuilder()
      .where("WHERE entityId = :entityId and entityType = :entityType "
          + "and type = :type and conditionStatus = :conditionStatus")
      .orderBy("id ASC")
      .limit(StatementBuilder.SUGGESTED_PAGE_LIMIT)
      .withBindVariableValue("entityId", proposalId)
      .withBindVariableValue("entityType", WorkflowEntityType.PROPOSAL.toString())
      .withBindVariableValue("conditionStatus",
          WorkflowEvaluationStatus.PENDING.toString())
      .withBindVariableValue("type",
          WorkflowRequestType.WORKFLOW_EXTERNAL_CONDITION_REQUEST.toString());
    

Passing the two filter statements into the getWorkflowRequestsByStatement call will yield any pending workflow requests, by type, on the proposal:

Java

  // Get workflow requests by statement.
  WorkflowRequestPage page = workflowRequestService.getWorkflowRequestsByStatement(
      statementBuilder.toStatement());
    

Approving workflow approval requests

Since workflow approval requests are system-defined actions, they can be approved directly by the user without any further action. As the filter statement for workflow approval requests will yield only the approval requests in a pending state, you can pass the existing filter statement into an action call for WorkflowRequestService for approval.

Java

  // Create action.
  com.google.api.ads.dfp.axis.v201702.ApproveWorkflowApprovalRequests action =
      new com.google.api.ads.dfp.axis.v201702.ApproveWorkflowApprovalRequests();


  // Perform action.
  UpdateResult result =
      workflowRequestService.performWorkflowRequestAction(
          action, statementBuilder.toStatement());
    

Triggering workflow external condition requests

Workflow external condition requests are intended for use when the publisher’s workflow has actions that are more complex than the DFP / Sales Manager’s predefined actions. An example would be if there’s an external pricing engine or if the publisher used their own inventory forecasting methods prior to reserving inventory. Say for instance you have a rule defined called ‘Check Inventory External,’ you might then want to run your system’s inventory check on all the ProposalLineItems and if it fails the external check, would trigger the ‘Request Approval’ step:

Java

  Set<Long> workflowIdsToTrigger = Sets.newHashSet();
  Set<Long> workflowIdsToSkip = Sets.newHashSet();

  ProposalLineItemServiceInterface proposalLineItemService = dfpServices.get(
          session, ProposalLineItemServiceInterface.class);


  for (WorkflowRequest workflowRequest : page.getResults()) {
    if (workflowRequest.getWorkflowRuleName().equals(“Check Inventory External”)) {
      // Query for the ProposalLineItems belonging to the
      // Proposal via workflowRequest.getEntityId()
      StatementBuilder proposalLineItemStatementBuilder =
          new StatementBuilder()
              .where("proposalId = :proposalId")
              .orderBy("id ASC")
              .limit(StatementBuilder.SUGGESTED_PAGE_LIMIT)
              .withBindVariableValue("proposalId",
                  workflowRequest.getEntityId());

      // Get proposal line items by statement.
      ProposalLineItemPage proposalLineItemPage =
           proposalLineItemService.getProposalLineItemsByStatement(
               statementBuilder.toStatement());

      for (ProposalLineItem proposalLineItem : proposalLineItemPage.getResults()) {
        // Assume your external forecast returns true if overbooking.
        if (externalSystem.runExternalForcast(proposalLineItem)) {
            workflowIdsToTrigger.add(workflowRequest.getId());
            // In the example above, only one proposal line item failing to book
            // inventory is needed to trigger.
            break;
        }
      }

      if (!workflowIdsToTrigger.contains(workflowRequest.getId()){
        workflowIdsToSkip.add(workflowRequest.getId());
      }
    }
  }
    

These requests would stay in a PENDING state until some action occurred outside of DFP / Sales Manager, at which time the decision is made to either TRIGGER or SKIP the action defined in the rule. For the example above, we want to trigger the list of workflow requests in workflowIdsToTrigger with the TriggerWorkflowExternalConditionRequest action and to skip the workflow requests in workflowIdsToSkip:

Java

  // Create actions.
  TriggerWorkflowExternalConditionRequests triggerAction =
      new TriggerWorkflowExternalConditionRequests();

  SkipWorkflowExternalConditionRequests skipAction =
      new SkipWorkflowExternalConditionRequests();

  // Perform action to selectively trigger workflow requests.
    StatementBuilder triggerStatementBuilder = new StatementBuilder()
      .where("id IN (" + Joiner.on(",").join(workflowIdsToTrigger, ‘,’) + ")");

  UpdateResult triggerResult =
      workflowRequestService.performWorkflowRequestAction(
          triggerAction, triggerStatementBuilder.toStatement());

  // Perform action to selectively skip workflow requests.
    StatementBuilder skipStatementBuilder = new StatementBuilder()
      .where("id IN (" + Joiner.on(",").join(workflowIdsToSkip, ‘,’) + ")");

  UpdateResult skipResult =
      workflowRequestService.performWorkflowRequestAction(
          skipAction, skipStatementBuilder.toStatement());
    

Once the proposal no longer has any pending requests, it can be fully submitted to DFP and sent to trafficking.

Send feedback about...

DoubleClick for Publishers
DoubleClick for Publishers
Need help? Visit our support page.