function printWarning()

in src/utils/reportUtils.js [333:605]


function printWarning(
  stream: WriteStream,
  warning: TestUploadWarning,
  level: string,
) {
  if (warning.type === 'no-events-accepted') {
    printHeader(stream, `[${level}] No Sample Events Were Accepted`);
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `We did not find any acceptable events after sampling your file.
      We predict that low-to-no events will be uploaded.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Review the data preparation best practices (${DATA_PREPARE_URL}).
      If your data meets these guidelines, please check the data mapping
      and try again.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'low-match-rate') {
    printHeader(stream, `[${level}] Low match rate`);
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `Your match rate is lower than the average for offline
      events. This typically occurs because the data you've
      provided has too few identifiers to match your customers to
      people on Facebook.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Review your mapping to make sure you've successfully mapped
      as many customer identifiers as possible. You can also edit
      the file to include additional customer data. Note that even
      with your current match rate, you can still upload your data
      to Facebook.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'low-pii-rate') {
    printHeader(
      stream,
      `[${level}] Some of Your Events Do Not Have Valid Customer Identifiers`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `Some of your events are either missing or have no valid
      customer identifiers. These are needed to match your
      customers to people on Facebook and thus in turn be used for
      attribution.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Review your mapping to make sure you've successfully mapped
      customer identifiers. Also review the file to correct any
      invalid customer data and include customer data where it's
      missing. Note that you can still upload your data to
      Facebook.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'not-assigned-to-account') {
    printHeader(
      stream,
      `[${level}] Your Offline Event Set is Not Assigned to an Ad Account`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `Without an assigned ad account, you won't be able to
      attribute any of these events to active ad campaigns.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Contact your business admin to assign an ad account to
      this offline events set.
      Note that you won't be able to attribute any events to ads
      that were running prior to assigning the ad account. You can
      still upload these events and use them for lift tests,
      custom audiences and analytics.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'events-lagged-90d') {
    printHeader(
      stream,
      `[${level}] ${warning.count} Events Occurred More Than 90 Days Ago`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `Facebook can't attribute events that occurred more than 90
      days ago to a Facebook ad campaign.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Upload your events more frequently. We recommend automating
      the upload process using the Facebook SDK or offline events
      API. Note that you can still upload these events, and use
      them for lift tests, custom audiences and analytics.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'events-lagged-2d') {
    printHeader(
      stream,
      `[${level}] ${warning.count} Events Occurred More Than 48 Hours Ago`,
    );
    printLine(stream, 'ISSUE:');
    printLine(stream,
      `Only events occurring within the last 48 hours are eligible
      for offline optimization.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Upload your events more frequently. We recommend automating
      the upload process using the Facebook SDK or offline events
      API. Note that you can still upload these events and use
      them for attribution, lift tests, custom audiences and
      analytics.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'inaccurate-event-time') {
    printHeader(
      stream,
      `[${level}] Some of Your Timestamps are Inaccurate`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `A significant number of your events are using the same
      timestamp. This may cause these events to be counted as
      duplicates, which will negatively impact attribution.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `For future uploads, add timestamps that are accurate to the
      minute or second.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'same-value') {
    printHeader(
      stream,
      `[${level}] All Sample Events Have the Same Value`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `All the events in your sample are showing the same value. If
      these numbers are inaccurate, they will reduce the accuracy
      of your reporting, and may affect value-based lookalike
      audiences.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Update your event values with accurate numbers. You may need
      to update your file, or use a new file.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'events-before-ad-account-assignment') {
    printHeader(
      stream,
      `[${level}] ${warning.count} Events ` +
      'Occurred Prior to an Ad Account Being Assigned',
    );
    printLine(stream, 'ISSUE:');
    const time = (new Date(warning.assignTime * 1000)).toISOString();
    printLine(
      stream,
      `The offline event set was assigned to ${warning.accountName}
      (${warning.accountID}) on ${time}.
      Any events that occurred prior to this date
      will not be attributed to ads created by this ad account.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Events occurring prior to an account being assigned will not
      be attributed, but can still be used for lift tests, custom
      audiences and analytics.`
    );
    stream.write(EOL + EOL);
  }

  if (warning.type === 'events-rejected') {
    printHeader(
      stream,
      `[${level}] ${warning.count} Events Were Not Accepted`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `${warning.count} events will not be uploaded due to invalid or missing
      data.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Review your data mapping. You may need to update your data
      and upload a new file. See samples of rejected events at the bottom of
      the file.`
    );
    warning.summary.forEach(s => {
      printLine(
        stream,
        `${s.count} events have invalid or missing ${s.propPath}.`,
        4,
      );
    });
    stream.write(EOL + EOL);
  }

  if (warning.type === 'events-incomplete') {
    printHeader(
      stream,
      `[${level}] ${warning.count} Events Have Invalid Fields`,
    );
    printLine(stream, 'ISSUE:');
    printLine(
      stream,
      `${warning.count} events have invalid fields. Invalid fields will be
      dropped during upload, which may impact your overall match rate.`
    );
    stream.write(SINGLE_LINE_SEPARATOR);
    printLine(stream, 'SOLUTION:');
    printLine(
      stream,
      `Check to see if you may have data mapping or formatting errors.
      See samples of events with invalid fields at the bottom of the file.`
    );
    warning.summary.forEach(s => {
      printLine(
        stream,
        `${s.count} events have invalid ${s.mapping} at column
        ${s.columnIndex}.`,
        4
      );
    });
    stream.write(EOL + EOL);
  }
}