From c8fc9c9d581bd3c8e36ffa559feca1cacdfded64 Mon Sep 17 00:00:00 2001 From: Aashish John Date: Sat, 24 Sep 2022 19:27:31 -0400 Subject: [PATCH 1/2] feat(script editor): add opt out language warning --- src/components/ScriptEditor.tsx | 30 +++++++++++++++++++ src/components/forms/GSScriptOptionsField.jsx | 3 ++ .../components/InteractionStepCard.tsx | 1 + 3 files changed, 34 insertions(+) diff --git a/src/components/ScriptEditor.tsx b/src/components/ScriptEditor.tsx index b18b5457a..63d706744 100644 --- a/src/components/ScriptEditor.tsx +++ b/src/components/ScriptEditor.tsx @@ -119,6 +119,7 @@ interface Props { scriptText: string; scriptFields: string[]; campaignVariables: CampaignVariable[]; + isRootStep: boolean; integrationSourced: boolean; onChange: (value: string) => Promise | void; receiveFocus?: boolean; @@ -320,6 +321,34 @@ class ScriptEditor extends React.Component { } } + renderOptOutLanguageWarning() { + const text = this.state.editorState + .getCurrentContent() + .getPlainText() + .toLowerCase(); + + // 2022-09-24 - stop as a separate word is best for avoiding spam blocks + if (this.props.isRootStep && text.length > 0 && !text.includes(" stop ")) + return ( +
+
+ WARNING! This script does not include opt out language. You must let + the recipient know they can opt out of receiving future texts, or your + messages are very likely to be blocked as spam. We recommend a phrase + with the individual word STOP, such as "Reply STOP to quit." Please + see our{" "} + + deliverability checklist + {" "} + for other best practices for improving deliverability. +
+ ); + } + renderCustomFields() { const { scriptFields, campaignVariables } = this.props; return ( @@ -376,6 +405,7 @@ class ScriptEditor extends React.Component { {this.renderCustomFields()}
{this.renderAttachmentWarning()} + {this.renderOptOutLanguageWarning()}
Estimated Segments: {info.msgCount}
Characters left in current segment:{" "} diff --git a/src/components/forms/GSScriptOptionsField.jsx b/src/components/forms/GSScriptOptionsField.jsx index b40bb1cda..d1c4829bd 100644 --- a/src/components/forms/GSScriptOptionsField.jsx +++ b/src/components/forms/GSScriptOptionsField.jsx @@ -96,6 +96,7 @@ class GSScriptOptionsField extends GSFormField { name, customFields, campaignVariables, + isRootStep, value: scriptVersions, integrationSourced, orgSettings @@ -154,6 +155,7 @@ class GSScriptOptionsField extends GSFormField { scriptFields={scriptFields} campaignVariables={campaignVariables} integrationSourced={integrationSourced} + isRootStep={isRootStep} receiveFocus expandable onChange={(val) => this.setState({ scriptDraft: val.trim() })} @@ -230,6 +232,7 @@ GSScriptOptionsField.propTypes = { value: PropTypes.string }) ).isRequired, + isRootStep: PropTypes.bool.isRequired, name: PropTypes.string, className: PropTypes.string, hintText: PropTypes.string, diff --git a/src/containers/AdminCampaignEdit/sections/CampaignInteractionStepsForm/components/InteractionStepCard.tsx b/src/containers/AdminCampaignEdit/sections/CampaignInteractionStepsForm/components/InteractionStepCard.tsx index 981e5cf76..af01d3406 100644 --- a/src/containers/AdminCampaignEdit/sections/CampaignInteractionStepsForm/components/InteractionStepCard.tsx +++ b/src/containers/AdminCampaignEdit/sections/CampaignInteractionStepsForm/components/InteractionStepCard.tsx @@ -245,6 +245,7 @@ export const InteractionStepCard: React.FC = (props) => { hintText="This is what your texters will send to your contacts. E.g. Hi, {firstName}. It's {texterFirstName} here." customFields={customFields} campaignVariables={campaignVariables} + isRootStep={isRootStep} integrationSourced={integrationSourced} fullWidth multiLine From c235b9c3267d3022d7382f59afada7f719fd32a0 Mon Sep 17 00:00:00 2001 From: Aashish John Date: Mon, 26 Sep 2022 12:37:53 -0400 Subject: [PATCH 2/2] fix: look for stop with trailing space --- src/components/ScriptEditor.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/ScriptEditor.tsx b/src/components/ScriptEditor.tsx index 63d706744..8d2bbb96c 100644 --- a/src/components/ScriptEditor.tsx +++ b/src/components/ScriptEditor.tsx @@ -322,13 +322,17 @@ class ScriptEditor extends React.Component { } renderOptOutLanguageWarning() { - const text = this.state.editorState + const lowercaseText = this.state.editorState .getCurrentContent() .getPlainText() .toLowerCase(); // 2022-09-24 - stop as a separate word is best for avoiding spam blocks - if (this.props.isRootStep && text.length > 0 && !text.includes(" stop ")) + if ( + this.props.isRootStep && + lowercaseText.length > 0 && + !lowercaseText.includes("stop ") + ) return (