@followgate/js 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -225,6 +225,47 @@ FollowGate.getUnlockStatus();
225
225
  // }
226
226
  ```
227
227
 
228
+ ### Server-Side Verification
229
+
230
+ When `userId` is set, completions are automatically saved to the server. You can verify users from your backend:
231
+
232
+ ```typescript
233
+ // Check if user is verified (server-side)
234
+ const isVerified = await FollowGate.isVerified();
235
+ // Returns: true | false
236
+
237
+ // Get full verification status
238
+ const status = await FollowGate.getVerificationStatus();
239
+ // Returns: {
240
+ // verified: boolean,
241
+ // userId: string,
242
+ // completedAt?: string, // ISO date string
243
+ // actions?: [{ action: 'follow', target: 'lukasvanuden' }, ...]
244
+ // }
245
+ ```
246
+
247
+ **Use Case: Conditional Features**
248
+
249
+ ```typescript
250
+ // In your app (e.g., Chrome extension, Electron app)
251
+ FollowGate.init({
252
+ appId: 'your-app-id',
253
+ apiKey: 'fg_live_xxx',
254
+ userId: clerkUserId,
255
+ twitter: { handle: 'lukasvanuden' },
256
+ });
257
+
258
+ const isVerified = await FollowGate.isVerified();
259
+
260
+ if (isVerified) {
261
+ // User completed FollowGate → Full access
262
+ enableAllFeatures();
263
+ } else {
264
+ // User hasn't completed → Limited access
265
+ enableTrialMode();
266
+ }
267
+ ```
268
+
228
269
  ### Event Listeners
229
270
 
230
271
  ```typescript
@@ -339,6 +380,7 @@ import type {
339
380
  CompleteOptions,
340
381
  UserInfo,
341
382
  UnlockStatus,
383
+ VerificationStatus,
342
384
  } from '@followgate/js';
343
385
  ```
344
386
 
package/dist/index.d.mts CHANGED
@@ -66,6 +66,18 @@ interface UnlockStatus {
66
66
  username?: string;
67
67
  completedActions?: CompleteOptions[];
68
68
  }
69
+ /**
70
+ * Server-side verification status
71
+ */
72
+ interface VerificationStatus {
73
+ verified: boolean;
74
+ userId: string;
75
+ completedAt?: string;
76
+ actions?: Array<{
77
+ action: string;
78
+ target: string;
79
+ }>;
80
+ }
69
81
  /**
70
82
  * FollowGate SDK Client
71
83
  */
@@ -130,6 +142,18 @@ declare class FollowGateClient {
130
142
  isUnlocked(): boolean;
131
143
  getUnlockStatus(): UnlockStatus;
132
144
  getCompletedActions(): CompleteOptions[];
145
+ /**
146
+ * Check if user is verified server-side
147
+ * Requires userId to be set in config
148
+ * @returns Promise<boolean> - true if verified, false otherwise
149
+ */
150
+ isVerified(): Promise<boolean>;
151
+ /**
152
+ * Get full verification status from server
153
+ * Requires userId to be set in config
154
+ * @returns Promise<VerificationStatus> - full verification details
155
+ */
156
+ getVerificationStatus(): Promise<VerificationStatus>;
133
157
  on(event: EventType, callback: EventCallback): void;
134
158
  off(event: EventType, callback: EventCallback): void;
135
159
  /**
@@ -139,6 +163,11 @@ declare class FollowGateClient {
139
163
  private getStorageKey;
140
164
  private restoreSession;
141
165
  private saveCompletedActions;
166
+ /**
167
+ * Save completion to server for verification
168
+ * Only works if userId is set in config
169
+ */
170
+ private saveCompletion;
142
171
  private buildIntentUrl;
143
172
  private buildTwitterUrl;
144
173
  private buildBlueskyUrl;
@@ -148,4 +177,4 @@ declare class FollowGateClient {
148
177
  }
149
178
  declare const FollowGate: FollowGateClient;
150
179
 
151
- export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo };
180
+ export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo, type VerificationStatus };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,18 @@ interface UnlockStatus {
66
66
  username?: string;
67
67
  completedActions?: CompleteOptions[];
68
68
  }
69
+ /**
70
+ * Server-side verification status
71
+ */
72
+ interface VerificationStatus {
73
+ verified: boolean;
74
+ userId: string;
75
+ completedAt?: string;
76
+ actions?: Array<{
77
+ action: string;
78
+ target: string;
79
+ }>;
80
+ }
69
81
  /**
70
82
  * FollowGate SDK Client
71
83
  */
@@ -130,6 +142,18 @@ declare class FollowGateClient {
130
142
  isUnlocked(): boolean;
131
143
  getUnlockStatus(): UnlockStatus;
132
144
  getCompletedActions(): CompleteOptions[];
145
+ /**
146
+ * Check if user is verified server-side
147
+ * Requires userId to be set in config
148
+ * @returns Promise<boolean> - true if verified, false otherwise
149
+ */
150
+ isVerified(): Promise<boolean>;
151
+ /**
152
+ * Get full verification status from server
153
+ * Requires userId to be set in config
154
+ * @returns Promise<VerificationStatus> - full verification details
155
+ */
156
+ getVerificationStatus(): Promise<VerificationStatus>;
133
157
  on(event: EventType, callback: EventCallback): void;
134
158
  off(event: EventType, callback: EventCallback): void;
135
159
  /**
@@ -139,6 +163,11 @@ declare class FollowGateClient {
139
163
  private getStorageKey;
140
164
  private restoreSession;
141
165
  private saveCompletedActions;
166
+ /**
167
+ * Save completion to server for verification
168
+ * Only works if userId is set in config
169
+ */
170
+ private saveCompletion;
142
171
  private buildIntentUrl;
143
172
  private buildTwitterUrl;
144
173
  private buildBlueskyUrl;
@@ -148,4 +177,4 @@ declare class FollowGateClient {
148
177
  }
149
178
  declare const FollowGate: FollowGateClient;
150
179
 
151
- export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo };
180
+ export { type CompleteOptions, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, FollowGateError, type Platform, type SocialAction, type TwitterConfig, type UnlockStatus, type UserInfo, type VerificationStatus };
package/dist/index.js CHANGED
@@ -307,6 +307,45 @@ var MODAL_STYLES = `
307
307
  height: 20px;
308
308
  color: #fbbf24;
309
309
  flex-shrink: 0;
310
+ }
311
+
312
+ .fg-verify-box {
313
+ background: rgba(59, 130, 246, 0.05);
314
+ border: 1px solid rgba(96, 165, 250, 0.5);
315
+ border-radius: 12px;
316
+ padding: 12px 16px;
317
+ margin-bottom: 8px;
318
+ display: flex;
319
+ align-items: center;
320
+ justify-content: space-between;
321
+ gap: 12px;
322
+ }
323
+
324
+ .fg-verify-box-left {
325
+ display: flex;
326
+ align-items: center;
327
+ gap: 8px;
328
+ }
329
+
330
+ .fg-verify-spinner {
331
+ width: 20px;
332
+ height: 20px;
333
+ border: 2px solid rgba(96, 165, 250, 0.3);
334
+ border-top-color: #60a5fa;
335
+ border-radius: 50%;
336
+ animation: fg-spin 1s linear infinite;
337
+ }
338
+
339
+ .fg-verify-text {
340
+ font-size: 14px;
341
+ color: #93c5fd;
342
+ }
343
+
344
+ .fg-verify-hint {
345
+ font-size: 12px;
346
+ color: #64748b;
347
+ text-align: center;
348
+ margin-bottom: 16px;
310
349
  margin-top: 2px;
311
350
  }
312
351
 
@@ -784,8 +823,22 @@ var FollowGateClient = class {
784
823
  renderConfirmStep() {
785
824
  const content = this.getContentElement();
786
825
  if (!content) return;
826
+ const username = this.currentUser?.username;
787
827
  content.innerHTML = `
788
828
  <h2 class="fg-title">Almost done!</h2>
829
+ <div class="fg-verify-box">
830
+ <div class="fg-verify-box-left">
831
+ <div class="fg-verify-spinner"></div>
832
+ <span class="fg-verify-text">Verifying follow & repost</span>
833
+ </div>
834
+ ${username ? `
835
+ <div class="fg-user-badge" style="margin: 0;">
836
+ <div class="fg-user-badge-dot" style="background: #facc15;"></div>
837
+ <span class="fg-user-badge-text">@${username}</span>
838
+ </div>
839
+ ` : ""}
840
+ </div>
841
+ <p class="fg-verify-hint">Verification may take some time</p>
789
842
  <div class="fg-warning-box">
790
843
  ${ICONS.warning}
791
844
  <p><strong>Note:</strong> Access may be revoked if actions are not completed.</p>
@@ -865,7 +918,10 @@ var FollowGateClient = class {
865
918
  platform
866
919
  };
867
920
  if (typeof localStorage !== "undefined") {
868
- localStorage.setItem(this.getStorageKey("followgate_user"), JSON.stringify(this.currentUser));
921
+ localStorage.setItem(
922
+ this.getStorageKey("followgate_user"),
923
+ JSON.stringify(this.currentUser)
924
+ );
869
925
  }
870
926
  if (this.config.debug) {
871
927
  console.log("[FollowGate] Username set:", normalizedUsername);
@@ -959,6 +1015,7 @@ var FollowGateClient = class {
959
1015
  if (typeof localStorage !== "undefined") {
960
1016
  localStorage.setItem(this.getStorageKey("followgate_unlocked"), "true");
961
1017
  }
1018
+ await this.saveCompletion();
962
1019
  await this.trackEvent("gate_unlocked", {
963
1020
  username: this.currentUser?.username,
964
1021
  actions: this.completedActions
@@ -986,6 +1043,93 @@ var FollowGateClient = class {
986
1043
  return [...this.completedActions];
987
1044
  }
988
1045
  // ============================================
1046
+ // Server-Side Verification
1047
+ // ============================================
1048
+ /**
1049
+ * Check if user is verified server-side
1050
+ * Requires userId to be set in config
1051
+ * @returns Promise<boolean> - true if verified, false otherwise
1052
+ */
1053
+ async isVerified() {
1054
+ if (!this.config) {
1055
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
1056
+ }
1057
+ if (!this.config.userId) {
1058
+ if (this.config.debug) {
1059
+ console.warn("[FollowGate] isVerified() requires userId to be set");
1060
+ }
1061
+ return false;
1062
+ }
1063
+ try {
1064
+ const response = await fetch(
1065
+ `${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
1066
+ {
1067
+ headers: {
1068
+ Authorization: `Bearer ${this.config.apiKey}`
1069
+ }
1070
+ }
1071
+ );
1072
+ if (!response.ok) {
1073
+ if (this.config.debug) {
1074
+ console.warn(
1075
+ "[FollowGate] Verification check failed:",
1076
+ response.status
1077
+ );
1078
+ }
1079
+ return false;
1080
+ }
1081
+ const data = await response.json();
1082
+ return data.data?.verified === true;
1083
+ } catch (error) {
1084
+ if (this.config.debug) {
1085
+ console.warn("[FollowGate] Verification check error:", error);
1086
+ }
1087
+ return false;
1088
+ }
1089
+ }
1090
+ /**
1091
+ * Get full verification status from server
1092
+ * Requires userId to be set in config
1093
+ * @returns Promise<VerificationStatus> - full verification details
1094
+ */
1095
+ async getVerificationStatus() {
1096
+ if (!this.config) {
1097
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
1098
+ }
1099
+ if (!this.config.userId) {
1100
+ return {
1101
+ verified: false,
1102
+ userId: ""
1103
+ };
1104
+ }
1105
+ try {
1106
+ const response = await fetch(
1107
+ `${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
1108
+ {
1109
+ headers: {
1110
+ Authorization: `Bearer ${this.config.apiKey}`
1111
+ }
1112
+ }
1113
+ );
1114
+ if (!response.ok) {
1115
+ return {
1116
+ verified: false,
1117
+ userId: this.config.userId
1118
+ };
1119
+ }
1120
+ const data = await response.json();
1121
+ return data.data;
1122
+ } catch (error) {
1123
+ if (this.config.debug) {
1124
+ console.warn("[FollowGate] getVerificationStatus error:", error);
1125
+ }
1126
+ return {
1127
+ verified: false,
1128
+ userId: this.config.userId
1129
+ };
1130
+ }
1131
+ }
1132
+ // ============================================
989
1133
  // Event System
990
1134
  // ============================================
991
1135
  on(event, callback) {
@@ -1012,7 +1156,9 @@ var FollowGateClient = class {
1012
1156
  }
1013
1157
  restoreSession() {
1014
1158
  if (typeof localStorage === "undefined") return;
1015
- const userJson = localStorage.getItem(this.getStorageKey("followgate_user"));
1159
+ const userJson = localStorage.getItem(
1160
+ this.getStorageKey("followgate_user")
1161
+ );
1016
1162
  if (userJson) {
1017
1163
  try {
1018
1164
  this.currentUser = JSON.parse(userJson);
@@ -1020,7 +1166,9 @@ var FollowGateClient = class {
1020
1166
  localStorage.removeItem(this.getStorageKey("followgate_user"));
1021
1167
  }
1022
1168
  }
1023
- const actionsJson = localStorage.getItem(this.getStorageKey("followgate_actions"));
1169
+ const actionsJson = localStorage.getItem(
1170
+ this.getStorageKey("followgate_actions")
1171
+ );
1024
1172
  if (actionsJson) {
1025
1173
  try {
1026
1174
  this.completedActions = JSON.parse(actionsJson);
@@ -1037,6 +1185,46 @@ var FollowGateClient = class {
1037
1185
  );
1038
1186
  }
1039
1187
  }
1188
+ /**
1189
+ * Save completion to server for verification
1190
+ * Only works if userId is set in config
1191
+ */
1192
+ async saveCompletion() {
1193
+ if (!this.config?.userId) {
1194
+ return;
1195
+ }
1196
+ try {
1197
+ const response = await fetch(`${this.config.apiUrl}/api/v1/completions`, {
1198
+ method: "POST",
1199
+ headers: {
1200
+ "Content-Type": "application/json",
1201
+ Authorization: `Bearer ${this.config.apiKey}`
1202
+ },
1203
+ body: JSON.stringify({
1204
+ userId: this.config.userId,
1205
+ platform: this.currentUser?.platform || "twitter",
1206
+ actions: this.completedActions.map((a) => ({
1207
+ action: a.action,
1208
+ target: a.target
1209
+ }))
1210
+ })
1211
+ });
1212
+ if (this.config.debug) {
1213
+ if (response.ok) {
1214
+ console.log("[FollowGate] Completion saved to server");
1215
+ } else {
1216
+ console.warn(
1217
+ "[FollowGate] Failed to save completion:",
1218
+ response.status
1219
+ );
1220
+ }
1221
+ }
1222
+ } catch (error) {
1223
+ if (this.config.debug) {
1224
+ console.warn("[FollowGate] Failed to save completion:", error);
1225
+ }
1226
+ }
1227
+ }
1040
1228
  buildIntentUrl(options) {
1041
1229
  const { platform, action, target } = options;
1042
1230
  switch (platform) {
package/dist/index.mjs CHANGED
@@ -281,6 +281,45 @@ var MODAL_STYLES = `
281
281
  height: 20px;
282
282
  color: #fbbf24;
283
283
  flex-shrink: 0;
284
+ }
285
+
286
+ .fg-verify-box {
287
+ background: rgba(59, 130, 246, 0.05);
288
+ border: 1px solid rgba(96, 165, 250, 0.5);
289
+ border-radius: 12px;
290
+ padding: 12px 16px;
291
+ margin-bottom: 8px;
292
+ display: flex;
293
+ align-items: center;
294
+ justify-content: space-between;
295
+ gap: 12px;
296
+ }
297
+
298
+ .fg-verify-box-left {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: 8px;
302
+ }
303
+
304
+ .fg-verify-spinner {
305
+ width: 20px;
306
+ height: 20px;
307
+ border: 2px solid rgba(96, 165, 250, 0.3);
308
+ border-top-color: #60a5fa;
309
+ border-radius: 50%;
310
+ animation: fg-spin 1s linear infinite;
311
+ }
312
+
313
+ .fg-verify-text {
314
+ font-size: 14px;
315
+ color: #93c5fd;
316
+ }
317
+
318
+ .fg-verify-hint {
319
+ font-size: 12px;
320
+ color: #64748b;
321
+ text-align: center;
322
+ margin-bottom: 16px;
284
323
  margin-top: 2px;
285
324
  }
286
325
 
@@ -758,8 +797,22 @@ var FollowGateClient = class {
758
797
  renderConfirmStep() {
759
798
  const content = this.getContentElement();
760
799
  if (!content) return;
800
+ const username = this.currentUser?.username;
761
801
  content.innerHTML = `
762
802
  <h2 class="fg-title">Almost done!</h2>
803
+ <div class="fg-verify-box">
804
+ <div class="fg-verify-box-left">
805
+ <div class="fg-verify-spinner"></div>
806
+ <span class="fg-verify-text">Verifying follow & repost</span>
807
+ </div>
808
+ ${username ? `
809
+ <div class="fg-user-badge" style="margin: 0;">
810
+ <div class="fg-user-badge-dot" style="background: #facc15;"></div>
811
+ <span class="fg-user-badge-text">@${username}</span>
812
+ </div>
813
+ ` : ""}
814
+ </div>
815
+ <p class="fg-verify-hint">Verification may take some time</p>
763
816
  <div class="fg-warning-box">
764
817
  ${ICONS.warning}
765
818
  <p><strong>Note:</strong> Access may be revoked if actions are not completed.</p>
@@ -839,7 +892,10 @@ var FollowGateClient = class {
839
892
  platform
840
893
  };
841
894
  if (typeof localStorage !== "undefined") {
842
- localStorage.setItem(this.getStorageKey("followgate_user"), JSON.stringify(this.currentUser));
895
+ localStorage.setItem(
896
+ this.getStorageKey("followgate_user"),
897
+ JSON.stringify(this.currentUser)
898
+ );
843
899
  }
844
900
  if (this.config.debug) {
845
901
  console.log("[FollowGate] Username set:", normalizedUsername);
@@ -933,6 +989,7 @@ var FollowGateClient = class {
933
989
  if (typeof localStorage !== "undefined") {
934
990
  localStorage.setItem(this.getStorageKey("followgate_unlocked"), "true");
935
991
  }
992
+ await this.saveCompletion();
936
993
  await this.trackEvent("gate_unlocked", {
937
994
  username: this.currentUser?.username,
938
995
  actions: this.completedActions
@@ -960,6 +1017,93 @@ var FollowGateClient = class {
960
1017
  return [...this.completedActions];
961
1018
  }
962
1019
  // ============================================
1020
+ // Server-Side Verification
1021
+ // ============================================
1022
+ /**
1023
+ * Check if user is verified server-side
1024
+ * Requires userId to be set in config
1025
+ * @returns Promise<boolean> - true if verified, false otherwise
1026
+ */
1027
+ async isVerified() {
1028
+ if (!this.config) {
1029
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
1030
+ }
1031
+ if (!this.config.userId) {
1032
+ if (this.config.debug) {
1033
+ console.warn("[FollowGate] isVerified() requires userId to be set");
1034
+ }
1035
+ return false;
1036
+ }
1037
+ try {
1038
+ const response = await fetch(
1039
+ `${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
1040
+ {
1041
+ headers: {
1042
+ Authorization: `Bearer ${this.config.apiKey}`
1043
+ }
1044
+ }
1045
+ );
1046
+ if (!response.ok) {
1047
+ if (this.config.debug) {
1048
+ console.warn(
1049
+ "[FollowGate] Verification check failed:",
1050
+ response.status
1051
+ );
1052
+ }
1053
+ return false;
1054
+ }
1055
+ const data = await response.json();
1056
+ return data.data?.verified === true;
1057
+ } catch (error) {
1058
+ if (this.config.debug) {
1059
+ console.warn("[FollowGate] Verification check error:", error);
1060
+ }
1061
+ return false;
1062
+ }
1063
+ }
1064
+ /**
1065
+ * Get full verification status from server
1066
+ * Requires userId to be set in config
1067
+ * @returns Promise<VerificationStatus> - full verification details
1068
+ */
1069
+ async getVerificationStatus() {
1070
+ if (!this.config) {
1071
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
1072
+ }
1073
+ if (!this.config.userId) {
1074
+ return {
1075
+ verified: false,
1076
+ userId: ""
1077
+ };
1078
+ }
1079
+ try {
1080
+ const response = await fetch(
1081
+ `${this.config.apiUrl}/api/v1/completions/verify/${encodeURIComponent(this.config.userId)}`,
1082
+ {
1083
+ headers: {
1084
+ Authorization: `Bearer ${this.config.apiKey}`
1085
+ }
1086
+ }
1087
+ );
1088
+ if (!response.ok) {
1089
+ return {
1090
+ verified: false,
1091
+ userId: this.config.userId
1092
+ };
1093
+ }
1094
+ const data = await response.json();
1095
+ return data.data;
1096
+ } catch (error) {
1097
+ if (this.config.debug) {
1098
+ console.warn("[FollowGate] getVerificationStatus error:", error);
1099
+ }
1100
+ return {
1101
+ verified: false,
1102
+ userId: this.config.userId
1103
+ };
1104
+ }
1105
+ }
1106
+ // ============================================
963
1107
  // Event System
964
1108
  // ============================================
965
1109
  on(event, callback) {
@@ -986,7 +1130,9 @@ var FollowGateClient = class {
986
1130
  }
987
1131
  restoreSession() {
988
1132
  if (typeof localStorage === "undefined") return;
989
- const userJson = localStorage.getItem(this.getStorageKey("followgate_user"));
1133
+ const userJson = localStorage.getItem(
1134
+ this.getStorageKey("followgate_user")
1135
+ );
990
1136
  if (userJson) {
991
1137
  try {
992
1138
  this.currentUser = JSON.parse(userJson);
@@ -994,7 +1140,9 @@ var FollowGateClient = class {
994
1140
  localStorage.removeItem(this.getStorageKey("followgate_user"));
995
1141
  }
996
1142
  }
997
- const actionsJson = localStorage.getItem(this.getStorageKey("followgate_actions"));
1143
+ const actionsJson = localStorage.getItem(
1144
+ this.getStorageKey("followgate_actions")
1145
+ );
998
1146
  if (actionsJson) {
999
1147
  try {
1000
1148
  this.completedActions = JSON.parse(actionsJson);
@@ -1011,6 +1159,46 @@ var FollowGateClient = class {
1011
1159
  );
1012
1160
  }
1013
1161
  }
1162
+ /**
1163
+ * Save completion to server for verification
1164
+ * Only works if userId is set in config
1165
+ */
1166
+ async saveCompletion() {
1167
+ if (!this.config?.userId) {
1168
+ return;
1169
+ }
1170
+ try {
1171
+ const response = await fetch(`${this.config.apiUrl}/api/v1/completions`, {
1172
+ method: "POST",
1173
+ headers: {
1174
+ "Content-Type": "application/json",
1175
+ Authorization: `Bearer ${this.config.apiKey}`
1176
+ },
1177
+ body: JSON.stringify({
1178
+ userId: this.config.userId,
1179
+ platform: this.currentUser?.platform || "twitter",
1180
+ actions: this.completedActions.map((a) => ({
1181
+ action: a.action,
1182
+ target: a.target
1183
+ }))
1184
+ })
1185
+ });
1186
+ if (this.config.debug) {
1187
+ if (response.ok) {
1188
+ console.log("[FollowGate] Completion saved to server");
1189
+ } else {
1190
+ console.warn(
1191
+ "[FollowGate] Failed to save completion:",
1192
+ response.status
1193
+ );
1194
+ }
1195
+ }
1196
+ } catch (error) {
1197
+ if (this.config.debug) {
1198
+ console.warn("[FollowGate] Failed to save completion:", error);
1199
+ }
1200
+ }
1201
+ }
1014
1202
  buildIntentUrl(options) {
1015
1203
  const { platform, action, target } = options;
1016
1204
  switch (platform) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@followgate/js",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "FollowGate SDK - Grow your audience with every download. Require social actions (follow, repost) before users can access your app.",
5
5
  "author": "FollowGate <hello@followgate.app>",
6
6
  "homepage": "https://followgate.app",